blob: 44043ac3ec42b2cf5b76512d3d6929890b1944ad [file] [log] [blame]
From a218fd8e2e8a2d390d995e62ba9e351c6cee30fb Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Tue, 11 Jun 2024 16:10:12 +0800
Subject: [PATCH 78/89] mtk: mac80211: add per-radio antenna config
Add per-radio antenna config
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
include/net/cfg80211.h | 9 ++--
include/net/mac80211.h | 4 +-
net/mac80211/cfg.c | 19 +++++---
net/mac80211/driver-ops.h | 12 ++---
net/mac80211/trace.h | 22 +++++----
net/wireless/nl80211.c | 97 +++++++++++++++++++++++++--------------
net/wireless/rdev-ops.h | 12 ++---
net/wireless/trace.h | 24 ++++++----
8 files changed, 122 insertions(+), 77 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 110e555..835735f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4881,8 +4881,8 @@ struct cfg80211_ops {
struct wireless_dev *wdev,
struct mgmt_frame_regs *upd);
- int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
- int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
+ int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant, int band);
+ int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant, int band);
int (*sched_scan_start)(struct wiphy *wiphy,
struct net_device *dev,
@@ -5831,8 +5831,9 @@ struct wiphy {
u8 max_num_pmkids;
- u32 available_antennas_tx;
- u32 available_antennas_rx;
+ /* FIXME: This should move to per-radio data struct */
+ u32 available_antennas_tx[NUM_NL80211_BANDS];
+ u32 available_antennas_rx[NUM_NL80211_BANDS];
u32 probe_resp_offload;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 08c15a7..9471892 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4650,8 +4650,8 @@ struct ieee80211_ops {
void (*channel_switch)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel_switch *ch_switch);
- int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
- int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
+ int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant, int band);
+ int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant, int band);
int (*remain_on_channel)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 51a9b21..69c3e81 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4255,15 +4255,22 @@ ieee80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
ieee80211_configure_filter(local);
}
-static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
+static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant, int band)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
int ret;
- if (local->started)
- return -EOPNOTSUPP;
+ /* FIXME:
+ * This flag should be moved to per-radio data struct; otherwise,
+ * radio 1 or 2 will be blocked when radio 0 is started.
+ * Temporarily disable this check until we have a better solution.
+ * if (local->started)
+ * return -EOPNOTSUPP;
+ */
+ wiphy_info(wiphy,
+ "Temporarily disable local->started check during setting antenna\n");
- ret = drv_set_antenna(local, tx_ant, rx_ant);
+ ret = drv_set_antenna(local, tx_ant, rx_ant, band);
if (ret)
return ret;
@@ -4271,11 +4278,11 @@ static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
return 0;
}
-static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
+static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant, int band)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
- return drv_get_antenna(local, tx_ant, rx_ant);
+ return drv_get_antenna(local, tx_ant, rx_ant, band);
}
static int ieee80211_set_rekey_data(struct wiphy *wiphy,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 4c0ac85..3bf8768 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -762,26 +762,26 @@ static inline void drv_channel_switch(struct ieee80211_local *local,
static inline int drv_set_antenna(struct ieee80211_local *local,
- u32 tx_ant, u32 rx_ant)
+ u32 tx_ant, u32 rx_ant, int band)
{
int ret = -EOPNOTSUPP;
might_sleep();
lockdep_assert_wiphy(local->hw.wiphy);
if (local->ops->set_antenna)
- ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant);
- trace_drv_set_antenna(local, tx_ant, rx_ant, ret);
+ ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant, band);
+ trace_drv_set_antenna(local, tx_ant, rx_ant, band, ret);
return ret;
}
static inline int drv_get_antenna(struct ieee80211_local *local,
- u32 *tx_ant, u32 *rx_ant)
+ u32 *tx_ant, u32 *rx_ant, int band)
{
int ret = -EOPNOTSUPP;
might_sleep();
lockdep_assert_wiphy(local->hw.wiphy);
if (local->ops->get_antenna)
- ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant);
- trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret);
+ ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant, band);
+ trace_drv_get_antenna(local, *tx_ant, *rx_ant, band, ret);
return ret;
}
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 48fcc8f..84b5c35 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1263,14 +1263,16 @@ DEFINE_EVENT(chanswitch_evt, drv_channel_switch,
);
TRACE_EVENT(drv_set_antenna,
- TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret),
+ TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant,
+ int band, int ret),
- TP_ARGS(local, tx_ant, rx_ant, ret),
+ TP_ARGS(local, tx_ant, rx_ant, band, ret),
TP_STRUCT__entry(
LOCAL_ENTRY
__field(u32, tx_ant)
__field(u32, rx_ant)
+ __field(int, band)
__field(int, ret)
),
@@ -1278,24 +1280,27 @@ TRACE_EVENT(drv_set_antenna,
LOCAL_ASSIGN;
__entry->tx_ant = tx_ant;
__entry->rx_ant = rx_ant;
+ __entry->band = band;
__entry->ret = ret;
),
TP_printk(
- LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d",
- LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret
+ LOCAL_PR_FMT " tx_ant:%d rx_ant:%d band:%d ret:%d",
+ LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant,
+ __entry->band, __entry->ret
)
);
TRACE_EVENT(drv_get_antenna,
- TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret),
+ TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int band, int ret),
- TP_ARGS(local, tx_ant, rx_ant, ret),
+ TP_ARGS(local, tx_ant, rx_ant, band, ret),
TP_STRUCT__entry(
LOCAL_ENTRY
__field(u32, tx_ant)
__field(u32, rx_ant)
+ __field(int, band)
__field(int, ret)
),
@@ -1303,12 +1308,13 @@ TRACE_EVENT(drv_get_antenna,
LOCAL_ASSIGN;
__entry->tx_ant = tx_ant;
__entry->rx_ant = rx_ant;
+ __entry->rx_ant = band;
__entry->ret = ret;
),
TP_printk(
- LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d",
- LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret
+ LOCAL_PR_FMT " tx_ant:%d rx_ant:%d band:%d ret:%d",
+ LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->band, __entry->ret
)
);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e62116e..c38a5d0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -618,8 +618,6 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
[NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
- [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
- [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
[NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
[NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
[NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
@@ -2626,10 +2624,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
goto nla_put_failure;
- if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
- rdev->wiphy.available_antennas_tx) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
- rdev->wiphy.available_antennas_rx))
+ if (nla_put(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
+ sizeof(rdev->wiphy.available_antennas_tx),
+ rdev->wiphy.available_antennas_tx) ||
+ nla_put(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
+ sizeof(rdev->wiphy.available_antennas_rx),
+ rdev->wiphy.available_antennas_rx))
goto nla_put_failure;
if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
@@ -2637,22 +2637,29 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
rdev->wiphy.probe_resp_offload))
goto nla_put_failure;
- if ((rdev->wiphy.available_antennas_tx ||
- rdev->wiphy.available_antennas_rx) &&
- rdev->ops->get_antenna) {
- u32 tx_ant = 0, rx_ant = 0;
+ if (rdev->ops->get_antenna) {
+ u32 tx_ants[NUM_NL80211_BANDS], rx_ants[NUM_NL80211_BANDS];
+ u32 tx_ant, rx_ant;
int res;
- res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
- if (!res) {
- if (nla_put_u32(msg,
- NL80211_ATTR_WIPHY_ANTENNA_TX,
- tx_ant) ||
- nla_put_u32(msg,
- NL80211_ATTR_WIPHY_ANTENNA_RX,
- rx_ant))
- goto nla_put_failure;
+ memset(tx_ants, 0, sizeof(tx_ants));
+ memset(rx_ants, 0, sizeof(rx_ants));
+ for (i = 0; i < NUM_NL80211_BANDS; i++) {
+ if (!rdev->wiphy.available_antennas_tx[i] ||
+ !rdev->wiphy.available_antennas_rx[i])
+ continue;
+
+ res = rdev_get_antenna(rdev, &tx_ant, &rx_ant, i);
+ if (!res) {
+ tx_ants[i] = tx_ant;
+ rx_ants[i] = rx_ant;
+ }
}
+ if (nla_put(msg, NL80211_ATTR_WIPHY_ANTENNA_TX,
+ sizeof(tx_ants), tx_ants) ||
+ nla_put(msg, NL80211_ATTR_WIPHY_ANTENNA_RX,
+ sizeof(rx_ants), rx_ants))
+ goto nla_put_failure;
}
state->split_start++;
@@ -3784,32 +3791,52 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
- u32 tx_ant, rx_ant;
+ u32 *tx_ants, *rx_ants;
+ int bandid, tx_num, rx_num;
- if ((!rdev->wiphy.available_antennas_tx &&
- !rdev->wiphy.available_antennas_rx) ||
- !rdev->ops->set_antenna) {
+ if (!rdev->ops->set_antenna) {
result = -EOPNOTSUPP;
goto out;
}
- tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
- rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
-
- /* reject antenna configurations which don't match the
- * available antenna masks, except for the "all" mask */
- if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
- (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
+ tx_num = nla_len(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]) / sizeof(u32);
+ rx_num = nla_len(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) / sizeof(u32);
+ if (tx_num != rx_num || tx_num != NUM_NL80211_BANDS) {
result = -EINVAL;
goto out;
}
+ tx_ants = nla_data(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
+ rx_ants = nla_data(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
- tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
- rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
+ /* reject antenna configurations which don't match the
+ * available antenna masks in wiphy, except for the "all" mask
+ */
+ for (bandid = 0; bandid < NUM_NL80211_BANDS; bandid++) {
+ struct ieee80211_supported_band *sband = rdev->wiphy.bands[bandid];
+ u32 tx_ant = tx_ants[bandid], rx_ant = rx_ants[bandid];
+ u32 avail_ants_tx = rdev->wiphy.available_antennas_tx[bandid];
+ u32 avail_ants_rx = rdev->wiphy.available_antennas_rx[bandid];
- result = rdev_set_antenna(rdev, tx_ant, rx_ant);
- if (result)
- goto out;
+ if (!sband || !tx_ant || !rx_ant)
+ continue;
+
+ if (!avail_ants_tx && !avail_ants_rx) {
+ result = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if ((~tx_ant && (tx_ant & ~avail_ants_tx)) ||
+ (~rx_ant && (rx_ant & ~avail_ants_rx))) {
+ result = -EINVAL;
+ goto out;
+ }
+
+ tx_ant = tx_ant & avail_ants_tx;
+ rx_ant = rx_ant & avail_ants_rx;
+ result = rdev_set_antenna(rdev, tx_ant, rx_ant, bandid);
+ if (result)
+ goto out;
+ }
}
changed = 0;
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 9b411db..bcd51fc 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -857,26 +857,26 @@ rdev_update_mgmt_frame_registrations(struct cfg80211_registered_device *rdev,
}
static inline int rdev_set_antenna(struct cfg80211_registered_device *rdev,
- u32 tx_ant, u32 rx_ant)
+ u32 tx_ant, u32 rx_ant, int band)
{
int ret;
- trace_rdev_set_antenna(&rdev->wiphy, tx_ant, rx_ant);
- ret = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
+ trace_rdev_set_antenna(&rdev->wiphy, tx_ant, rx_ant, band);
+ ret = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant, band);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
static inline int rdev_get_antenna(struct cfg80211_registered_device *rdev,
- u32 *tx_ant, u32 *rx_ant)
+ u32 *tx_ant, u32 *rx_ant, int band)
{
int ret;
trace_rdev_get_antenna(&rdev->wiphy);
- ret = rdev->ops->get_antenna(&rdev->wiphy, tx_ant, rx_ant);
+ ret = rdev->ops->get_antenna(&rdev->wiphy, tx_ant, rx_ant, band);
if (ret)
trace_rdev_return_int(&rdev->wiphy, ret);
else
trace_rdev_return_int_tx_rx(&rdev->wiphy, ret, *tx_ant,
- *rx_ant);
+ *rx_ant, band);
return ret;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 6af432e..90ba38a 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1818,22 +1818,24 @@ TRACE_EVENT(rdev_update_mgmt_frame_registrations,
);
TRACE_EVENT(rdev_return_int_tx_rx,
- TP_PROTO(struct wiphy *wiphy, int ret, u32 tx, u32 rx),
- TP_ARGS(wiphy, ret, tx, rx),
+ TP_PROTO(struct wiphy *wiphy, int ret, u32 tx, u32 rx, int band),
+ TP_ARGS(wiphy, ret, tx, rx, band),
TP_STRUCT__entry(
WIPHY_ENTRY
__field(int, ret)
__field(u32, tx)
__field(u32, rx)
+ __field(int, band)
),
TP_fast_assign(
WIPHY_ASSIGN;
__entry->ret = ret;
__entry->tx = tx;
__entry->rx = rx;
+ __entry->band = band;
),
- TP_printk(WIPHY_PR_FMT ", returned %d, tx: %u, rx: %u",
- WIPHY_PR_ARG, __entry->ret, __entry->tx, __entry->rx)
+ TP_printk(WIPHY_PR_FMT ", returned %d, tx: %u, rx: %u band %d",
+ WIPHY_PR_ARG, __entry->ret, __entry->tx, __entry->rx, __entry->band)
);
TRACE_EVENT(rdev_return_void_tx_rx,
@@ -1860,25 +1862,27 @@ TRACE_EVENT(rdev_return_void_tx_rx,
);
DECLARE_EVENT_CLASS(tx_rx_evt,
- TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
- TP_ARGS(wiphy, tx, rx),
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx, int band),
+ TP_ARGS(wiphy, rx, tx, band),
TP_STRUCT__entry(
WIPHY_ENTRY
__field(u32, tx)
__field(u32, rx)
+ __field(int, band)
),
TP_fast_assign(
WIPHY_ASSIGN;
__entry->tx = tx;
__entry->rx = rx;
+ __entry->band = band;
),
- TP_printk(WIPHY_PR_FMT ", tx: %u, rx: %u ",
- WIPHY_PR_ARG, __entry->tx, __entry->rx)
+ TP_printk(WIPHY_PR_FMT ", tx: %u, rx: %u band: %d ",
+ WIPHY_PR_ARG, __entry->tx, __entry->rx, __entry->band)
);
DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
- TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
- TP_ARGS(wiphy, tx, rx)
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx, int band),
+ TP_ARGS(wiphy, rx, tx, band)
);
DECLARE_EVENT_CLASS(wiphy_netdev_id_evt,
--
2.18.0