developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 1 | From 9887703630f6949fffbbca476a121a38afc2d558 Mon Sep 17 00:00:00 2001 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 2 | From: Bo Jiao <Bo.Jiao@mediatek.com> |
| 3 | Date: Tue, 11 Jan 2022 12:03:23 +0800 |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 4 | Subject: [PATCH 1002/1040] wifi: mt76: mt7915: air monitor support |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 5 | |
| 6 | --- |
developer | 5ce5ea4 | 2022-08-31 14:12:29 +0800 | [diff] [blame] | 7 | mt76_connac_mcu.h | 2 + |
| 8 | mt7915/mac.c | 4 + |
| 9 | mt7915/main.c | 3 + |
| 10 | mt7915/mt7915.h | 34 +++++ |
developer | 83ed06a | 2023-04-27 20:45:39 +0800 | [diff] [blame] | 11 | mt7915/vendor.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++ |
developer | 5ce5ea4 | 2022-08-31 14:12:29 +0800 | [diff] [blame] | 12 | mt7915/vendor.h | 38 +++++ |
developer | 83ed06a | 2023-04-27 20:45:39 +0800 | [diff] [blame] | 13 | 6 files changed, 442 insertions(+) |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 14 | |
| 15 | diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 16 | index 8a377dd..c1d9191 100644 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 17 | --- a/mt76_connac_mcu.h |
| 18 | +++ b/mt76_connac_mcu.h |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 19 | @@ -1208,6 +1208,8 @@ enum { |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 20 | MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, |
| 21 | MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, |
| 22 | MCU_EXT_CMD_PHY_STAT_INFO = 0xad, |
| 23 | + /* for vendor csi and air monitor */ |
| 24 | + MCU_EXT_CMD_SMESH_CTRL = 0xae, |
| 25 | MCU_EXT_CMD_CSI_CTRL = 0xc2, |
| 26 | }; |
| 27 | |
| 28 | diff --git a/mt7915/mac.c b/mt7915/mac.c |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 29 | index 2650b87..f171e97 100644 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 30 | --- a/mt7915/mac.c |
| 31 | +++ b/mt7915/mac.c |
developer | 2157bf8 | 2023-06-26 02:27:49 +0800 | [diff] [blame] | 32 | @@ -524,6 +524,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 33 | seq_ctrl = le16_to_cpu(hdr->seq_ctrl); |
| 34 | qos_ctl = *ieee80211_get_qos_ctl(hdr); |
| 35 | } |
| 36 | +#ifdef CONFIG_MTK_VENDOR |
| 37 | + if (phy->amnt_ctrl.enable) |
| 38 | + mt7915_vendor_amnt_fill_rx(phy, skb); |
| 39 | +#endif |
| 40 | } else { |
| 41 | status->flag |= RX_FLAG_8023; |
developer | 144824b | 2022-11-25 21:27:43 +0800 | [diff] [blame] | 42 | mt7915_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb, |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 43 | diff --git a/mt7915/main.c b/mt7915/main.c |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 44 | index b4dfe4b..d667b44 100644 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 45 | --- a/mt7915/main.c |
| 46 | +++ b/mt7915/main.c |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 47 | @@ -772,6 +772,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 48 | if (ret) |
| 49 | return ret; |
| 50 | |
| 51 | +#ifdef CONFIG_MTK_VENDOR |
| 52 | + mt7915_vendor_amnt_sta_remove(mvif->phy, sta); |
| 53 | +#endif |
| 54 | return mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); |
| 55 | } |
| 56 | |
| 57 | diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 58 | index 6a96996..6192e81 100644 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 59 | --- a/mt7915/mt7915.h |
| 60 | +++ b/mt7915/mt7915.h |
developer | 8f0d89b | 2023-07-28 07:16:44 +0800 | [diff] [blame] | 61 | @@ -195,6 +195,35 @@ struct mt7915_hif { |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 62 | int irq; |
| 63 | }; |
| 64 | |
| 65 | +#ifdef CONFIG_MTK_VENDOR |
| 66 | +#define MT7915_AIR_MONITOR_MAX_ENTRY 16 |
developer | 83ed06a | 2023-04-27 20:45:39 +0800 | [diff] [blame] | 67 | +#define MT7915_AIR_MONITOR_MAX_GROUP MT7915_AIR_MONITOR_MAX_ENTRY >> 1 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 68 | + |
| 69 | +struct mt7915_air_monitor_group { |
| 70 | + bool enable; |
| 71 | + bool used[2]; |
| 72 | +}; |
| 73 | + |
| 74 | +struct mt7915_air_monitor_entry { |
| 75 | + bool enable; |
| 76 | + |
| 77 | + u8 group_idx; |
| 78 | + u8 group_used_idx; |
| 79 | + u8 muar_idx; |
| 80 | + u8 addr[ETH_ALEN]; |
| 81 | + unsigned int last_seen; |
| 82 | + s8 rssi[4]; |
| 83 | + struct ieee80211_sta *sta; |
| 84 | +}; |
| 85 | + |
| 86 | +struct mt7915_air_monitor_ctrl { |
| 87 | + u8 enable; |
| 88 | + |
| 89 | + struct mt7915_air_monitor_group group[MT7915_AIR_MONITOR_MAX_GROUP]; |
| 90 | + struct mt7915_air_monitor_entry entry[MT7915_AIR_MONITOR_MAX_ENTRY]; |
| 91 | +}; |
| 92 | +#endif |
| 93 | + |
| 94 | struct mt7915_phy { |
| 95 | struct mt76_phy *mt76; |
| 96 | struct mt7915_dev *dev; |
developer | 8f0d89b | 2023-07-28 07:16:44 +0800 | [diff] [blame] | 97 | @@ -256,6 +285,8 @@ struct mt7915_phy { |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 98 | u32 interval; |
| 99 | u32 last_record; |
| 100 | } csi; |
| 101 | + |
| 102 | + struct mt7915_air_monitor_ctrl amnt_ctrl; |
| 103 | #endif |
| 104 | }; |
| 105 | |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 106 | @@ -642,6 +673,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 107 | void mt7915_vendor_register(struct mt7915_phy *phy); |
| 108 | int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode, |
| 109 | u8 cfg, u8 v1, u32 v2, u8 *mac_addr); |
| 110 | +void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb); |
| 111 | +int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, |
| 112 | + struct ieee80211_sta *sta); |
| 113 | #endif |
| 114 | |
| 115 | #ifdef MTK_DEBUG |
| 116 | diff --git a/mt7915/vendor.c b/mt7915/vendor.c |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 117 | index 98fd9c2..43f9690 100644 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 118 | --- a/mt7915/vendor.c |
| 119 | +++ b/mt7915/vendor.c |
developer | 83ed06a | 2023-04-27 20:45:39 +0800 | [diff] [blame] | 120 | @@ -430,6 +430,355 @@ out: |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 121 | return err; |
| 122 | } |
| 123 | |
| 124 | +static const struct nla_policy |
| 125 | +amnt_ctrl_policy[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL] = { |
| 126 | + [MTK_VENDOR_ATTR_AMNT_CTRL_SET] = {.type = NLA_NESTED }, |
| 127 | + [MTK_VENDOR_ATTR_AMNT_CTRL_DUMP] = { .type = NLA_NESTED }, |
| 128 | +}; |
| 129 | + |
| 130 | +static const struct nla_policy |
| 131 | +amnt_set_policy[NUM_MTK_VENDOR_ATTRS_AMNT_SET] = { |
| 132 | + [MTK_VENDOR_ATTR_AMNT_SET_INDEX] = {.type = NLA_U8 }, |
| 133 | + [MTK_VENDOR_ATTR_AMNT_SET_MACADDR] = { .type = NLA_NESTED }, |
| 134 | +}; |
| 135 | + |
| 136 | +static const struct nla_policy |
| 137 | +amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = { |
| 138 | + [MTK_VENDOR_ATTR_AMNT_DUMP_INDEX] = {.type = NLA_U8 }, |
| 139 | + [MTK_VENDOR_ATTR_AMNT_DUMP_LEN] = { .type = NLA_U8 }, |
| 140 | + [MTK_VENDOR_ATTR_AMNT_DUMP_RESULT] = { .type = NLA_NESTED }, |
| 141 | +}; |
| 142 | + |
| 143 | +struct mt7915_amnt_data { |
| 144 | + u8 idx; |
| 145 | + u8 addr[ETH_ALEN]; |
| 146 | + s8 rssi[4]; |
| 147 | + u32 last_seen; |
| 148 | +}; |
| 149 | + |
| 150 | +struct mt7915_smesh { |
| 151 | + u8 band; |
| 152 | + u8 write; |
| 153 | + u8 enable; |
| 154 | + bool a2; |
| 155 | + bool a1; |
| 156 | + bool data; |
| 157 | + bool mgnt; |
| 158 | + bool ctrl; |
| 159 | +} __packed; |
| 160 | + |
| 161 | +struct mt7915_smesh_event { |
| 162 | + u8 band; |
| 163 | + __le32 value; |
| 164 | +} __packed; |
| 165 | + |
| 166 | +static int |
| 167 | +mt7915_vendor_smesh_ctrl(struct mt7915_phy *phy, u8 write, |
| 168 | + u8 enable, u32 *value) |
| 169 | +{ |
| 170 | + struct mt7915_dev *dev = phy->dev; |
| 171 | + struct mt7915_smesh req = { |
| 172 | + .band = phy != &dev->phy, |
| 173 | + .write = write, |
| 174 | + .enable = enable, |
| 175 | + .a2 = 1, |
| 176 | + .a1 = 1, |
| 177 | + .data = 1, |
| 178 | + }; |
| 179 | + struct mt7915_smesh_event *res; |
| 180 | + struct sk_buff *skb; |
| 181 | + int ret = 0; |
| 182 | + |
| 183 | + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(SMESH_CTRL), |
| 184 | + &req, sizeof(req), !write, &skb); |
| 185 | + |
| 186 | + if (ret || write) |
| 187 | + return ret; |
| 188 | + |
| 189 | + res = (struct mt7915_smesh_event *) skb->data; |
| 190 | + |
| 191 | + if (!value) |
| 192 | + return -EINVAL; |
| 193 | + |
| 194 | + *value = res->value; |
| 195 | + |
| 196 | + dev_kfree_skb(skb); |
| 197 | + |
| 198 | + return 0; |
| 199 | +} |
| 200 | + |
| 201 | +static int |
| 202 | +mt7915_vendor_amnt_muar(struct mt7915_phy *phy, u8 muar_idx, u8 *addr) |
| 203 | +{ |
| 204 | + struct mt7915_dev *dev = phy->dev; |
| 205 | + struct { |
| 206 | + u8 mode; |
| 207 | + u8 force_clear; |
| 208 | + u8 clear_bitmap[8]; |
| 209 | + u8 entry_count; |
| 210 | + u8 write; |
| 211 | + u8 band; |
| 212 | + |
| 213 | + u8 index; |
| 214 | + u8 bssid; |
| 215 | + u8 addr[ETH_ALEN]; |
| 216 | + } __packed req = { |
| 217 | + .entry_count = 1, |
| 218 | + .write = 1, |
| 219 | + .band = phy != &dev->phy, |
| 220 | + .index = muar_idx, |
| 221 | + }; |
| 222 | + |
| 223 | + ether_addr_copy(req.addr, addr); |
| 224 | + |
| 225 | + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MUAR_UPDATE), &req, |
| 226 | + sizeof(req), true); |
| 227 | +} |
| 228 | + |
| 229 | +static int |
| 230 | +mt7915_vendor_amnt_set_en(struct mt7915_phy *phy, u8 enable) |
| 231 | +{ |
| 232 | + u32 status; |
| 233 | + int ret; |
| 234 | + |
| 235 | + ret = mt7915_vendor_smesh_ctrl(phy, 0, enable, &status); |
| 236 | + if (ret) |
| 237 | + return ret; |
| 238 | + |
| 239 | + status = status & 0xff; |
| 240 | + |
| 241 | + if (status == enable) |
| 242 | + return 0; |
| 243 | + |
| 244 | + ret = mt7915_vendor_smesh_ctrl(phy, 1, enable, &status); |
| 245 | + if (ret) |
| 246 | + return ret; |
| 247 | + |
| 248 | + return 0; |
| 249 | +} |
| 250 | + |
| 251 | +static int |
| 252 | +mt7915_vendor_amnt_set_addr(struct mt7915_phy *phy, u8 index, u8 *addr) |
| 253 | +{ |
| 254 | + struct mt7915_air_monitor_ctrl *amnt_ctrl = &phy->amnt_ctrl; |
| 255 | + struct mt7915_air_monitor_group *group; |
| 256 | + struct mt7915_air_monitor_entry *entry = &amnt_ctrl->entry[index]; |
| 257 | + const u8 zero_addr[ETH_ALEN] = {}; |
| 258 | + int enable = !ether_addr_equal(addr, zero_addr); |
| 259 | + int ret, i, j; |
| 260 | + |
| 261 | + if (enable == 1 && entry->enable == 1) { |
| 262 | + ether_addr_copy(entry->addr, addr); |
| 263 | + } else if (enable == 1 && entry->enable == 0){ |
| 264 | + for (i = 0; i < MT7915_AIR_MONITOR_MAX_GROUP; i++) { |
| 265 | + group = &(amnt_ctrl->group[i]); |
| 266 | + if (group->used[0] == 0) |
| 267 | + j = 0; |
developer | 83ed06a | 2023-04-27 20:45:39 +0800 | [diff] [blame] | 268 | + else if (group->used[1] == 0) |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 269 | + j = 1; |
developer | 83ed06a | 2023-04-27 20:45:39 +0800 | [diff] [blame] | 270 | + else |
| 271 | + continue; |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 272 | + |
| 273 | + group->enable = 1; |
| 274 | + group->used[j] = 1; |
| 275 | + entry->enable = 1; |
| 276 | + entry->group_idx = i; |
| 277 | + entry->group_used_idx = j; |
| 278 | + entry->muar_idx = 32 + 2 * i + 2 * i + 2 * j; |
| 279 | + ether_addr_copy(entry->addr, addr); |
| 280 | + break; |
| 281 | + } |
| 282 | + } else { |
| 283 | + group = &(amnt_ctrl->group[entry->group_idx]); |
| 284 | + |
| 285 | + group->used[entry->group_used_idx] = 0; |
| 286 | + if (group->used[0] == 0 && group->used[1] == 0) |
| 287 | + group->enable = 0; |
| 288 | + |
| 289 | + entry->enable = 0; |
| 290 | + ether_addr_copy(entry->addr, addr); |
| 291 | + } |
| 292 | + |
| 293 | + amnt_ctrl->enable &= ~(1 << entry->group_idx); |
| 294 | + amnt_ctrl->enable |= entry->enable << entry->group_idx; |
| 295 | + ret = mt7915_vendor_amnt_muar(phy, entry->muar_idx, addr); |
| 296 | + if (ret) |
| 297 | + return ret; |
| 298 | + |
| 299 | + return mt7915_vendor_amnt_set_en(phy, amnt_ctrl->enable); |
| 300 | +} |
| 301 | + |
| 302 | +void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb) |
| 303 | +{ |
| 304 | + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; |
| 305 | + struct mt7915_air_monitor_ctrl *ctrl = &phy->amnt_ctrl; |
| 306 | + struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); |
| 307 | + __le16 fc = hdr->frame_control; |
| 308 | + u8 addr[ETH_ALEN]; |
| 309 | + int i; |
| 310 | + |
| 311 | + if (!ieee80211_has_fromds(fc)) |
| 312 | + ether_addr_copy(addr, hdr->addr2); |
| 313 | + else if (ieee80211_has_tods(fc)) |
| 314 | + ether_addr_copy(addr, hdr->addr4); |
| 315 | + else |
| 316 | + ether_addr_copy(addr, hdr->addr3); |
| 317 | + |
| 318 | + for (i = 0; i < MT7915_AIR_MONITOR_MAX_ENTRY; i++) { |
| 319 | + struct mt7915_air_monitor_entry *entry; |
| 320 | + |
| 321 | + if (ether_addr_equal(addr, ctrl->entry[i].addr)) { |
| 322 | + entry = &ctrl->entry[i]; |
| 323 | + entry->rssi[0] = status->chain_signal[0]; |
| 324 | + entry->rssi[1] = status->chain_signal[1]; |
| 325 | + entry->rssi[2] = status->chain_signal[2]; |
| 326 | + entry->rssi[3] = status->chain_signal[3]; |
| 327 | + entry->last_seen = jiffies; |
| 328 | + } |
| 329 | + } |
| 330 | + |
| 331 | + if (ieee80211_has_tods(fc) && |
| 332 | + !ether_addr_equal(hdr->addr3, phy->mt76->macaddr)) |
| 333 | + return; |
| 334 | + else if (!ether_addr_equal(hdr->addr1, phy->mt76->macaddr)) |
| 335 | + return; |
| 336 | +} |
| 337 | + |
| 338 | +int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, |
| 339 | + struct ieee80211_sta *sta) |
| 340 | +{ |
| 341 | + u8 zero[ETH_ALEN] = {}; |
| 342 | + int i; |
| 343 | + |
| 344 | + if (!phy->amnt_ctrl.enable) |
| 345 | + return 0; |
| 346 | + |
| 347 | + for (i = 0; i < MT7915_AIR_MONITOR_MAX_ENTRY; i++) |
| 348 | + if (ether_addr_equal(sta->addr, phy->amnt_ctrl.entry[i].addr)) |
| 349 | + return mt7915_vendor_amnt_set_addr(phy, i, zero); |
| 350 | + |
| 351 | + return 0; |
| 352 | +} |
| 353 | + |
| 354 | +static int |
| 355 | +mt7915_vendor_amnt_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev, |
| 356 | + const void *data, int data_len) |
| 357 | +{ |
| 358 | + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
| 359 | + struct mt7915_phy *phy = mt7915_hw_phy(hw); |
| 360 | + struct nlattr *tb1[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL]; |
| 361 | + struct nlattr *tb2[NUM_MTK_VENDOR_ATTRS_AMNT_SET]; |
| 362 | + struct nlattr *cur; |
| 363 | + u8 index = 0, i = 0; |
| 364 | + u8 mac_addr[ETH_ALEN] = {}; |
| 365 | + int err, rem; |
| 366 | + |
| 367 | + err = nla_parse(tb1, MTK_VENDOR_ATTR_AMNT_CTRL_MAX, data, data_len, |
| 368 | + amnt_ctrl_policy, NULL); |
| 369 | + if (err) |
| 370 | + return err; |
| 371 | + |
| 372 | + if (!tb1[MTK_VENDOR_ATTR_AMNT_CTRL_SET]) |
| 373 | + return -EINVAL; |
| 374 | + |
| 375 | + err = nla_parse_nested(tb2, MTK_VENDOR_ATTR_AMNT_SET_MAX, |
| 376 | + tb1[MTK_VENDOR_ATTR_AMNT_CTRL_SET], amnt_set_policy, NULL); |
| 377 | + |
| 378 | + if (!tb2[MTK_VENDOR_ATTR_AMNT_SET_INDEX] || |
| 379 | + !tb2[MTK_VENDOR_ATTR_AMNT_SET_MACADDR]) |
| 380 | + return -EINVAL; |
| 381 | + |
| 382 | + index = nla_get_u8(tb2[MTK_VENDOR_ATTR_AMNT_SET_INDEX]); |
| 383 | + nla_for_each_nested(cur, tb2[MTK_VENDOR_ATTR_AMNT_SET_MACADDR], rem) { |
| 384 | + mac_addr[i++] = nla_get_u8(cur); |
| 385 | + } |
| 386 | + |
| 387 | + return mt7915_vendor_amnt_set_addr(phy, index, mac_addr); |
| 388 | +} |
| 389 | + |
| 390 | +static int |
| 391 | +mt7915_amnt_dump(struct mt7915_phy *phy, struct sk_buff *skb, |
| 392 | + u8 amnt_idx, int *attrtype) |
| 393 | +{ |
| 394 | + struct mt7915_air_monitor_entry *entry = |
| 395 | + &phy->amnt_ctrl.entry[amnt_idx]; |
| 396 | + struct mt7915_amnt_data data; |
| 397 | + u32 last_seen = 0; |
| 398 | + |
| 399 | + if (entry->enable == 0) |
| 400 | + return 0; |
| 401 | + |
| 402 | + last_seen = jiffies_to_msecs(jiffies - entry->last_seen); |
| 403 | + |
| 404 | + data.idx = amnt_idx; |
| 405 | + ether_addr_copy(data.addr, entry->addr); |
| 406 | + data.rssi[0] = entry->rssi[0]; |
| 407 | + data.rssi[1] = entry->rssi[1]; |
| 408 | + data.rssi[2] = entry->rssi[2]; |
| 409 | + data.rssi[3] = entry->rssi[3]; |
| 410 | + data.last_seen = last_seen; |
| 411 | + |
| 412 | + nla_put(skb, (*attrtype)++, sizeof(struct mt7915_amnt_data), &data); |
| 413 | + |
| 414 | + return 1; |
| 415 | +} |
| 416 | + |
| 417 | +static int |
| 418 | +mt7915_vendor_amnt_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev, |
| 419 | + struct sk_buff *skb, const void *data, int data_len, |
| 420 | + unsigned long *storage) |
| 421 | +{ |
| 422 | + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
| 423 | + struct mt7915_phy *phy = mt7915_hw_phy(hw); |
| 424 | + struct nlattr *tb1[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL]; |
| 425 | + struct nlattr *tb2[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP]; |
| 426 | + void *a, *b; |
| 427 | + int err = 0, attrtype = 0, i, len = 0; |
| 428 | + u8 amnt_idx; |
| 429 | + |
| 430 | + if (*storage == 1) |
| 431 | + return -ENOENT; |
| 432 | + *storage = 1; |
| 433 | + |
| 434 | + err = nla_parse(tb1, MTK_VENDOR_ATTR_AMNT_CTRL_MAX, data, data_len, |
| 435 | + amnt_ctrl_policy, NULL); |
| 436 | + if (err) |
| 437 | + return err; |
| 438 | + |
| 439 | + if (!tb1[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP]) |
| 440 | + return -EINVAL; |
| 441 | + |
| 442 | + err = nla_parse_nested(tb2, MTK_VENDOR_ATTR_AMNT_DUMP_MAX, |
| 443 | + tb1[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP], |
| 444 | + amnt_dump_policy, NULL); |
| 445 | + if (err) |
| 446 | + return err; |
| 447 | + |
| 448 | + if (!tb2[MTK_VENDOR_ATTR_AMNT_DUMP_INDEX]) |
| 449 | + return -EINVAL; |
| 450 | + |
| 451 | + amnt_idx = nla_get_u8(tb2[MTK_VENDOR_ATTR_AMNT_DUMP_INDEX]); |
| 452 | + |
| 453 | + a = nla_nest_start(skb, MTK_VENDOR_ATTR_AMNT_CTRL_DUMP); |
| 454 | + b = nla_nest_start(skb, MTK_VENDOR_ATTR_AMNT_DUMP_RESULT); |
| 455 | + |
| 456 | + if (amnt_idx != 0xff) { |
| 457 | + len += mt7915_amnt_dump(phy, skb, amnt_idx, &attrtype); |
| 458 | + } else { |
| 459 | + for (i = 0; i < MT7915_AIR_MONITOR_MAX_ENTRY; i++) { |
| 460 | + len += mt7915_amnt_dump(phy, skb, i, &attrtype); |
| 461 | + } |
| 462 | + } |
| 463 | + |
| 464 | + nla_nest_end(skb, b); |
| 465 | + |
| 466 | + nla_put_u8(skb, MTK_VENDOR_ATTR_AMNT_DUMP_LEN, len); |
| 467 | + |
| 468 | + nla_nest_end(skb, a); |
| 469 | + |
| 470 | + return len + 1; |
| 471 | +} |
| 472 | + |
| 473 | static const struct wiphy_vendor_command mt7915_vendor_commands[] = { |
| 474 | { |
| 475 | .info = { |
developer | 83ed06a | 2023-04-27 20:45:39 +0800 | [diff] [blame] | 476 | @@ -442,6 +791,18 @@ static const struct wiphy_vendor_command mt7915_vendor_commands[] = { |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 477 | .dumpit = mt7915_vendor_csi_ctrl_dump, |
| 478 | .policy = csi_ctrl_policy, |
| 479 | .maxattr = MTK_VENDOR_ATTR_CSI_CTRL_MAX, |
| 480 | + }, |
| 481 | + { |
| 482 | + .info = { |
| 483 | + .vendor_id = MTK_NL80211_VENDOR_ID, |
| 484 | + .subcmd = MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL, |
| 485 | + }, |
| 486 | + .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | |
| 487 | + WIPHY_VENDOR_CMD_NEED_RUNNING, |
| 488 | + .doit = mt7915_vendor_amnt_ctrl, |
| 489 | + .dumpit = mt7915_vendor_amnt_ctrl_dump, |
| 490 | + .policy = amnt_ctrl_policy, |
| 491 | + .maxattr = MTK_VENDOR_ATTR_AMNT_CTRL_MAX, |
| 492 | } |
| 493 | }; |
| 494 | |
| 495 | diff --git a/mt7915/vendor.h b/mt7915/vendor.h |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 496 | index 9d3db2a..976817f 100644 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 497 | --- a/mt7915/vendor.h |
| 498 | +++ b/mt7915/vendor.h |
| 499 | @@ -4,6 +4,7 @@ |
| 500 | #define MTK_NL80211_VENDOR_ID 0x0ce7 |
| 501 | |
| 502 | enum mtk_nl80211_vendor_subcmds { |
| 503 | + MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae, |
| 504 | MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL = 0xc2, |
| 505 | }; |
| 506 | |
| 507 | @@ -57,4 +58,41 @@ enum mtk_vendor_attr_csi_data { |
| 508 | NUM_MTK_VENDOR_ATTRS_CSI_DATA - 1 |
| 509 | }; |
| 510 | |
| 511 | +enum mtk_vendor_attr_mnt_ctrl { |
| 512 | + MTK_VENDOR_ATTR_AMNT_CTRL_UNSPEC, |
| 513 | + |
| 514 | + MTK_VENDOR_ATTR_AMNT_CTRL_SET, |
| 515 | + MTK_VENDOR_ATTR_AMNT_CTRL_DUMP, |
| 516 | + |
| 517 | + /* keep last */ |
| 518 | + NUM_MTK_VENDOR_ATTRS_AMNT_CTRL, |
| 519 | + MTK_VENDOR_ATTR_AMNT_CTRL_MAX = |
| 520 | + NUM_MTK_VENDOR_ATTRS_AMNT_CTRL - 1 |
| 521 | +}; |
| 522 | + |
| 523 | +enum mtk_vendor_attr_mnt_set { |
| 524 | + MTK_VENDOR_ATTR_AMNT_SET_UNSPEC, |
| 525 | + |
| 526 | + MTK_VENDOR_ATTR_AMNT_SET_INDEX, |
| 527 | + MTK_VENDOR_ATTR_AMNT_SET_MACADDR, |
| 528 | + |
| 529 | + /* keep last */ |
| 530 | + NUM_MTK_VENDOR_ATTRS_AMNT_SET, |
| 531 | + MTK_VENDOR_ATTR_AMNT_SET_MAX = |
| 532 | + NUM_MTK_VENDOR_ATTRS_AMNT_SET - 1 |
| 533 | +}; |
| 534 | + |
| 535 | +enum mtk_vendor_attr_mnt_dump { |
| 536 | + MTK_VENDOR_ATTR_AMNT_DUMP_UNSPEC, |
| 537 | + |
| 538 | + MTK_VENDOR_ATTR_AMNT_DUMP_INDEX, |
| 539 | + MTK_VENDOR_ATTR_AMNT_DUMP_LEN, |
| 540 | + MTK_VENDOR_ATTR_AMNT_DUMP_RESULT, |
| 541 | + |
| 542 | + /* keep last */ |
| 543 | + NUM_MTK_VENDOR_ATTRS_AMNT_DUMP, |
| 544 | + MTK_VENDOR_ATTR_AMNT_DUMP_MAX = |
| 545 | + NUM_MTK_VENDOR_ATTRS_AMNT_DUMP - 1 |
| 546 | +}; |
| 547 | + |
| 548 | #endif |
| 549 | -- |
developer | 0443cd3 | 2023-09-19 14:11:49 +0800 | [diff] [blame] | 550 | 2.18.0 |
developer | e2cc0fa | 2022-03-29 17:31:03 +0800 | [diff] [blame] | 551 | |