aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wil6210/cfg80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/cfg80211.c')
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c241
1 files changed, 212 insertions, 29 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 5b340769d5bb..4806a49cb61b 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -104,41 +104,125 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type)
104 return -EOPNOTSUPP; 104 return -EOPNOTSUPP;
105} 105}
106 106
107static int wil_cfg80211_get_station(struct wiphy *wiphy, 107static int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
108 struct net_device *ndev, 108 struct station_info *sinfo)
109 u8 *mac, struct station_info *sinfo)
110{ 109{
111 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
112 int rc;
113 struct wmi_notify_req_cmd cmd = { 110 struct wmi_notify_req_cmd cmd = {
114 .cid = 0, 111 .cid = cid,
115 .interval_usec = 0, 112 .interval_usec = 0,
116 }; 113 };
114 struct {
115 struct wil6210_mbox_hdr_wmi wmi;
116 struct wmi_notify_req_done_event evt;
117 } __packed reply;
118 struct wil_net_stats *stats = &wil->sta[cid].stats;
119 int rc;
117 120
118 if (memcmp(mac, wil->dst_addr[0], ETH_ALEN))
119 return -ENOENT;
120
121 /* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */
122 rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), 121 rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
123 WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20); 122 WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20);
124 if (rc) 123 if (rc)
125 return rc; 124 return rc;
126 125
126 wil_dbg_wmi(wil, "Link status for CID %d: {\n"
127 " MCS %d TSF 0x%016llx\n"
128 " BF status 0x%08x SNR 0x%08x SQI %d%%\n"
129 " Tx Tpt %d goodput %d Rx goodput %d\n"
130 " Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
131 cid, le16_to_cpu(reply.evt.bf_mcs),
132 le64_to_cpu(reply.evt.tsf), reply.evt.status,
133 le32_to_cpu(reply.evt.snr_val),
134 reply.evt.sqi,
135 le32_to_cpu(reply.evt.tx_tpt),
136 le32_to_cpu(reply.evt.tx_goodput),
137 le32_to_cpu(reply.evt.rx_goodput),
138 le16_to_cpu(reply.evt.my_rx_sector),
139 le16_to_cpu(reply.evt.my_tx_sector),
140 le16_to_cpu(reply.evt.other_rx_sector),
141 le16_to_cpu(reply.evt.other_tx_sector));
142
127 sinfo->generation = wil->sinfo_gen; 143 sinfo->generation = wil->sinfo_gen;
128 144
129 sinfo->filled |= STATION_INFO_TX_BITRATE; 145 sinfo->filled = STATION_INFO_RX_BYTES |
146 STATION_INFO_TX_BYTES |
147 STATION_INFO_RX_PACKETS |
148 STATION_INFO_TX_PACKETS |
149 STATION_INFO_RX_BITRATE |
150 STATION_INFO_TX_BITRATE |
151 STATION_INFO_RX_DROP_MISC |
152 STATION_INFO_TX_FAILED;
153
130 sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; 154 sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
131 sinfo->txrate.mcs = wil->stats.bf_mcs; 155 sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
132 sinfo->filled |= STATION_INFO_RX_BITRATE;
133 sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; 156 sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
134 sinfo->rxrate.mcs = wil->stats.last_mcs_rx; 157 sinfo->rxrate.mcs = stats->last_mcs_rx;
158 sinfo->rx_bytes = stats->rx_bytes;
159 sinfo->rx_packets = stats->rx_packets;
160 sinfo->rx_dropped_misc = stats->rx_dropped;
161 sinfo->tx_bytes = stats->tx_bytes;
162 sinfo->tx_packets = stats->tx_packets;
163 sinfo->tx_failed = stats->tx_errors;
135 164
136 if (test_bit(wil_status_fwconnected, &wil->status)) { 165 if (test_bit(wil_status_fwconnected, &wil->status)) {
137 sinfo->filled |= STATION_INFO_SIGNAL; 166 sinfo->filled |= STATION_INFO_SIGNAL;
138 sinfo->signal = 12; /* TODO: provide real value */ 167 sinfo->signal = reply.evt.sqi;
139 } 168 }
140 169
141 return 0; 170 return rc;
171}
172
173static int wil_cfg80211_get_station(struct wiphy *wiphy,
174 struct net_device *ndev,
175 u8 *mac, struct station_info *sinfo)
176{
177 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
178 int rc;
179
180 int cid = wil_find_cid(wil, mac);
181
182 wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid);
183 if (cid < 0)
184 return cid;
185
186 rc = wil_cid_fill_sinfo(wil, cid, sinfo);
187
188 return rc;
189}
190
191/*
192 * Find @idx-th active STA for station dump.
193 */
194static int wil_find_cid_by_idx(struct wil6210_priv *wil, int idx)
195{
196 int i;
197
198 for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
199 if (wil->sta[i].status == wil_sta_unused)
200 continue;
201 if (idx == 0)
202 return i;
203 idx--;
204 }
205
206 return -ENOENT;
207}
208
209static int wil_cfg80211_dump_station(struct wiphy *wiphy,
210 struct net_device *dev, int idx,
211 u8 *mac, struct station_info *sinfo)
212{
213 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
214 int rc;
215 int cid = wil_find_cid_by_idx(wil, idx);
216
217 if (cid < 0)
218 return -ENOENT;
219
220 memcpy(mac, wil->sta[cid].addr, ETH_ALEN);
221 wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid);
222
223 rc = wil_cid_fill_sinfo(wil, cid, sinfo);
224
225 return rc;
142} 226}
143 227
144static int wil_cfg80211_change_iface(struct wiphy *wiphy, 228static int wil_cfg80211_change_iface(struct wiphy *wiphy,
@@ -181,6 +265,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
181 u16 chnl[4]; 265 u16 chnl[4];
182 } __packed cmd; 266 } __packed cmd;
183 uint i, n; 267 uint i, n;
268 int rc;
184 269
185 if (wil->scan_request) { 270 if (wil->scan_request) {
186 wil_err(wil, "Already scanning\n"); 271 wil_err(wil, "Already scanning\n");
@@ -198,7 +283,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
198 283
199 /* FW don't support scan after connection attempt */ 284 /* FW don't support scan after connection attempt */
200 if (test_bit(wil_status_dontscan, &wil->status)) { 285 if (test_bit(wil_status_dontscan, &wil->status)) {
201 wil_err(wil, "Scan after connect attempt not supported\n"); 286 wil_err(wil, "Can't scan now\n");
202 return -EBUSY; 287 return -EBUSY;
203 } 288 }
204 289
@@ -221,8 +306,13 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
221 request->channels[i]->center_freq); 306 request->channels[i]->center_freq);
222 } 307 }
223 308
224 return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + 309 rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
225 cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); 310 cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
311
312 if (rc)
313 wil->scan_request = NULL;
314
315 return rc;
226} 316}
227 317
228static int wil_cfg80211_connect(struct wiphy *wiphy, 318static int wil_cfg80211_connect(struct wiphy *wiphy,
@@ -237,6 +327,10 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
237 int ch; 327 int ch;
238 int rc = 0; 328 int rc = 0;
239 329
330 if (test_bit(wil_status_fwconnecting, &wil->status) ||
331 test_bit(wil_status_fwconnected, &wil->status))
332 return -EALREADY;
333
240 bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, 334 bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
241 sme->ssid, sme->ssid_len, 335 sme->ssid, sme->ssid_len,
242 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 336 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
@@ -318,10 +412,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
318 412
319 memcpy(conn.bssid, bss->bssid, ETH_ALEN); 413 memcpy(conn.bssid, bss->bssid, ETH_ALEN);
320 memcpy(conn.dst_mac, bss->bssid, ETH_ALEN); 414 memcpy(conn.dst_mac, bss->bssid, ETH_ALEN);
321 /* 415
322 * FW don't support scan after connection attempt
323 */
324 set_bit(wil_status_dontscan, &wil->status);
325 set_bit(wil_status_fwconnecting, &wil->status); 416 set_bit(wil_status_fwconnecting, &wil->status);
326 417
327 rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); 418 rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
@@ -330,7 +421,6 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
330 mod_timer(&wil->connect_timer, 421 mod_timer(&wil->connect_timer,
331 jiffies + msecs_to_jiffies(2000)); 422 jiffies + msecs_to_jiffies(2000));
332 } else { 423 } else {
333 clear_bit(wil_status_dontscan, &wil->status);
334 clear_bit(wil_status_fwconnecting, &wil->status); 424 clear_bit(wil_status_fwconnecting, &wil->status);
335 } 425 }
336 426
@@ -352,6 +442,40 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
352 return rc; 442 return rc;
353} 443}
354 444
445static int wil_cfg80211_mgmt_tx(struct wiphy *wiphy,
446 struct wireless_dev *wdev,
447 struct cfg80211_mgmt_tx_params *params,
448 u64 *cookie)
449{
450 const u8 *buf = params->buf;
451 size_t len = params->len;
452 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
453 int rc;
454 struct ieee80211_mgmt *mgmt_frame = (void *)buf;
455 struct wmi_sw_tx_req_cmd *cmd;
456 struct {
457 struct wil6210_mbox_hdr_wmi wmi;
458 struct wmi_sw_tx_complete_event evt;
459 } __packed evt;
460
461 cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
462 if (!cmd)
463 return -ENOMEM;
464
465 memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
466 cmd->len = cpu_to_le16(len);
467 memcpy(cmd->payload, buf, len);
468
469 rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len,
470 WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
471 if (rc == 0)
472 rc = evt.evt.status;
473
474 kfree(cmd);
475
476 return rc;
477}
478
355static int wil_cfg80211_set_channel(struct wiphy *wiphy, 479static int wil_cfg80211_set_channel(struct wiphy *wiphy,
356 struct cfg80211_chan_def *chandef) 480 struct cfg80211_chan_def *chandef)
357{ 481{
@@ -402,6 +526,41 @@ static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
402 return 0; 526 return 0;
403} 527}
404 528
529static int wil_remain_on_channel(struct wiphy *wiphy,
530 struct wireless_dev *wdev,
531 struct ieee80211_channel *chan,
532 unsigned int duration,
533 u64 *cookie)
534{
535 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
536 int rc;
537
538 /* TODO: handle duration */
539 wil_info(wil, "%s(%d, %d ms)\n", __func__, chan->center_freq, duration);
540
541 rc = wmi_set_channel(wil, chan->hw_value);
542 if (rc)
543 return rc;
544
545 rc = wmi_rxon(wil, true);
546
547 return rc;
548}
549
550static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
551 struct wireless_dev *wdev,
552 u64 cookie)
553{
554 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
555 int rc;
556
557 wil_info(wil, "%s()\n", __func__);
558
559 rc = wmi_rxon(wil, false);
560
561 return rc;
562}
563
405static int wil_fix_bcon(struct wil6210_priv *wil, 564static int wil_fix_bcon(struct wil6210_priv *wil,
406 struct cfg80211_beacon_data *bcon) 565 struct cfg80211_beacon_data *bcon)
407{ 566{
@@ -450,18 +609,20 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
450 if (wil_fix_bcon(wil, bcon)) 609 if (wil_fix_bcon(wil, bcon))
451 wil_dbg_misc(wil, "Fixed bcon\n"); 610 wil_dbg_misc(wil, "Fixed bcon\n");
452 611
612 mutex_lock(&wil->mutex);
613
453 rc = wil_reset(wil); 614 rc = wil_reset(wil);
454 if (rc) 615 if (rc)
455 return rc; 616 goto out;
456 617
457 /* Rx VRING. */ 618 /* Rx VRING. */
458 rc = wil_rx_init(wil); 619 rc = wil_rx_init(wil);
459 if (rc) 620 if (rc)
460 return rc; 621 goto out;
461 622
462 rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); 623 rc = wmi_set_ssid(wil, info->ssid_len, info->ssid);
463 if (rc) 624 if (rc)
464 return rc; 625 goto out;
465 626
466 /* MAC address - pre-requisite for other commands */ 627 /* MAC address - pre-requisite for other commands */
467 wmi_set_mac_address(wil, ndev->dev_addr); 628 wmi_set_mac_address(wil, ndev->dev_addr);
@@ -485,11 +646,13 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
485 rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, 646 rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype,
486 channel->hw_value); 647 channel->hw_value);
487 if (rc) 648 if (rc)
488 return rc; 649 goto out;
489 650
490 651
491 netif_carrier_on(ndev); 652 netif_carrier_on(ndev);
492 653
654out:
655 mutex_unlock(&wil->mutex);
493 return rc; 656 return rc;
494} 657}
495 658
@@ -499,17 +662,36 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
499 int rc = 0; 662 int rc = 0;
500 struct wil6210_priv *wil = wiphy_to_wil(wiphy); 663 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
501 664
665 mutex_lock(&wil->mutex);
666
502 rc = wmi_pcp_stop(wil); 667 rc = wmi_pcp_stop(wil);
503 668
669 mutex_unlock(&wil->mutex);
504 return rc; 670 return rc;
505} 671}
506 672
673static int wil_cfg80211_del_station(struct wiphy *wiphy,
674 struct net_device *dev, u8 *mac)
675{
676 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
677
678 mutex_lock(&wil->mutex);
679 wil6210_disconnect(wil, mac);
680 mutex_unlock(&wil->mutex);
681
682 return 0;
683}
684
507static struct cfg80211_ops wil_cfg80211_ops = { 685static struct cfg80211_ops wil_cfg80211_ops = {
508 .scan = wil_cfg80211_scan, 686 .scan = wil_cfg80211_scan,
509 .connect = wil_cfg80211_connect, 687 .connect = wil_cfg80211_connect,
510 .disconnect = wil_cfg80211_disconnect, 688 .disconnect = wil_cfg80211_disconnect,
511 .change_virtual_intf = wil_cfg80211_change_iface, 689 .change_virtual_intf = wil_cfg80211_change_iface,
512 .get_station = wil_cfg80211_get_station, 690 .get_station = wil_cfg80211_get_station,
691 .dump_station = wil_cfg80211_dump_station,
692 .remain_on_channel = wil_remain_on_channel,
693 .cancel_remain_on_channel = wil_cancel_remain_on_channel,
694 .mgmt_tx = wil_cfg80211_mgmt_tx,
513 .set_monitor_channel = wil_cfg80211_set_channel, 695 .set_monitor_channel = wil_cfg80211_set_channel,
514 .add_key = wil_cfg80211_add_key, 696 .add_key = wil_cfg80211_add_key,
515 .del_key = wil_cfg80211_del_key, 697 .del_key = wil_cfg80211_del_key,
@@ -517,6 +699,7 @@ static struct cfg80211_ops wil_cfg80211_ops = {
517 /* AP mode */ 699 /* AP mode */
518 .start_ap = wil_cfg80211_start_ap, 700 .start_ap = wil_cfg80211_start_ap,
519 .stop_ap = wil_cfg80211_stop_ap, 701 .stop_ap = wil_cfg80211_stop_ap,
702 .del_station = wil_cfg80211_del_station,
520}; 703};
521 704
522static void wil_wiphy_init(struct wiphy *wiphy) 705static void wil_wiphy_init(struct wiphy *wiphy)
@@ -542,7 +725,7 @@ static void wil_wiphy_init(struct wiphy *wiphy)
542 wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz; 725 wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz;
543 726
544 /* TODO: figure this out */ 727 /* TODO: figure this out */
545 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 728 wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
546 729
547 wiphy->cipher_suites = wil_cipher_suites; 730 wiphy->cipher_suites = wil_cipher_suites;
548 wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); 731 wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites);