aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wil6210/wmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/wmi.c')
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c136
1 files changed, 124 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 063963ee422a..2ba56eef0c45 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -307,14 +307,14 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
307 u32 freq = ieee80211_channel_to_frequency(ch_no, 307 u32 freq = ieee80211_channel_to_frequency(ch_no,
308 IEEE80211_BAND_60GHZ); 308 IEEE80211_BAND_60GHZ);
309 struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); 309 struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq);
310 /* TODO convert LE to CPU */ 310 s32 signal = data->info.sqi;
311 s32 signal = 0; /* TODO */
312 __le16 fc = rx_mgmt_frame->frame_control; 311 __le16 fc = rx_mgmt_frame->frame_control;
313 u32 d_len = le32_to_cpu(data->info.len); 312 u32 d_len = le32_to_cpu(data->info.len);
314 u16 d_status = le16_to_cpu(data->info.status); 313 u16 d_status = le16_to_cpu(data->info.status);
315 314
316 wil_dbg_wmi(wil, "MGMT: channel %d MCS %d SNR %d\n", 315 wil_dbg_wmi(wil, "MGMT: channel %d MCS %d SNR %d SQI %d%%\n",
317 data->info.channel, data->info.mcs, data->info.snr); 316 data->info.channel, data->info.mcs, data->info.snr,
317 data->info.sqi);
318 wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len, 318 wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
319 le16_to_cpu(fc)); 319 le16_to_cpu(fc));
320 wil_dbg_wmi(wil, "qid %d mid %d cid %d\n", 320 wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
@@ -384,6 +384,11 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
384 evt->assoc_req_len, evt->assoc_resp_len); 384 evt->assoc_req_len, evt->assoc_resp_len);
385 return; 385 return;
386 } 386 }
387 if (evt->cid >= WIL6210_MAX_CID) {
388 wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
389 return;
390 }
391
387 ch = evt->channel + 1; 392 ch = evt->channel + 1;
388 wil_dbg_wmi(wil, "Connect %pM channel [%d] cid %d\n", 393 wil_dbg_wmi(wil, "Connect %pM channel [%d] cid %d\n",
389 evt->bssid, ch, evt->cid); 394 evt->bssid, ch, evt->cid);
@@ -439,7 +444,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
439 444
440 /* FIXME FW can transmit only ucast frames to peer */ 445 /* FIXME FW can transmit only ucast frames to peer */
441 /* FIXME real ring_id instead of hard coded 0 */ 446 /* FIXME real ring_id instead of hard coded 0 */
442 memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); 447 memcpy(wil->sta[evt->cid].addr, evt->bssid, ETH_ALEN);
448 wil->sta[evt->cid].status = wil_sta_conn_pending;
443 449
444 wil->pending_connect_cid = evt->cid; 450 wil->pending_connect_cid = evt->cid;
445 queue_work(wil->wmi_wq_conn, &wil->connect_worker); 451 queue_work(wil->wmi_wq_conn, &wil->connect_worker);
@@ -456,7 +462,9 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
456 462
457 wil->sinfo_gen++; 463 wil->sinfo_gen++;
458 464
465 mutex_lock(&wil->mutex);
459 wil6210_disconnect(wil, evt->bssid); 466 wil6210_disconnect(wil, evt->bssid);
467 mutex_unlock(&wil->mutex);
460} 468}
461 469
462static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) 470static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len)
@@ -476,11 +484,11 @@ static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len)
476 wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector); 484 wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector);
477 wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector); 485 wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector);
478 wil_dbg_wmi(wil, "Link status, MCS %d TSF 0x%016llx\n" 486 wil_dbg_wmi(wil, "Link status, MCS %d TSF 0x%016llx\n"
479 "BF status 0x%08x SNR 0x%08x\n" 487 "BF status 0x%08x SNR 0x%08x SQI %d%%\n"
480 "Tx Tpt %d goodput %d Rx goodput %d\n" 488 "Tx Tpt %d goodput %d Rx goodput %d\n"
481 "Sectors(rx:tx) my %d:%d peer %d:%d\n", 489 "Sectors(rx:tx) my %d:%d peer %d:%d\n",
482 wil->stats.bf_mcs, wil->stats.tsf, evt->status, 490 wil->stats.bf_mcs, wil->stats.tsf, evt->status,
483 wil->stats.snr, le32_to_cpu(evt->tx_tpt), 491 wil->stats.snr, evt->sqi, le32_to_cpu(evt->tx_tpt),
484 le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput), 492 le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput),
485 wil->stats.my_rx_sector, wil->stats.my_tx_sector, 493 wil->stats.my_rx_sector, wil->stats.my_tx_sector,
486 wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); 494 wil->stats.peer_rx_sector, wil->stats.peer_tx_sector);
@@ -499,10 +507,16 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
499 int sz = eapol_len + ETH_HLEN; 507 int sz = eapol_len + ETH_HLEN;
500 struct sk_buff *skb; 508 struct sk_buff *skb;
501 struct ethhdr *eth; 509 struct ethhdr *eth;
510 int cid;
511 struct wil_net_stats *stats = NULL;
502 512
503 wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len, 513 wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
504 evt->src_mac); 514 evt->src_mac);
505 515
516 cid = wil_find_cid(wil, evt->src_mac);
517 if (cid >= 0)
518 stats = &wil->sta[cid].stats;
519
506 if (eapol_len > 196) { /* TODO: revisit size limit */ 520 if (eapol_len > 196) { /* TODO: revisit size limit */
507 wil_err(wil, "EAPOL too large\n"); 521 wil_err(wil, "EAPOL too large\n");
508 return; 522 return;
@@ -513,6 +527,7 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
513 wil_err(wil, "Failed to allocate skb\n"); 527 wil_err(wil, "Failed to allocate skb\n");
514 return; 528 return;
515 } 529 }
530
516 eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); 531 eth = (struct ethhdr *)skb_put(skb, ETH_HLEN);
517 memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN); 532 memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN);
518 memcpy(eth->h_source, evt->src_mac, ETH_ALEN); 533 memcpy(eth->h_source, evt->src_mac, ETH_ALEN);
@@ -521,9 +536,15 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
521 skb->protocol = eth_type_trans(skb, ndev); 536 skb->protocol = eth_type_trans(skb, ndev);
522 if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) { 537 if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
523 ndev->stats.rx_packets++; 538 ndev->stats.rx_packets++;
524 ndev->stats.rx_bytes += skb->len; 539 ndev->stats.rx_bytes += sz;
540 if (stats) {
541 stats->rx_packets++;
542 stats->rx_bytes += sz;
543 }
525 } else { 544 } else {
526 ndev->stats.rx_dropped++; 545 ndev->stats.rx_dropped++;
546 if (stats)
547 stats->rx_dropped++;
527 } 548 }
528} 549}
529 550
@@ -531,9 +552,16 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
531{ 552{
532 struct net_device *ndev = wil_to_ndev(wil); 553 struct net_device *ndev = wil_to_ndev(wil);
533 struct wmi_data_port_open_event *evt = d; 554 struct wmi_data_port_open_event *evt = d;
555 u8 cid = evt->cid;
534 556
535 wil_dbg_wmi(wil, "Link UP for CID %d\n", evt->cid); 557 wil_dbg_wmi(wil, "Link UP for CID %d\n", cid);
536 558
559 if (cid >= ARRAY_SIZE(wil->sta)) {
560 wil_err(wil, "Link UP for invalid CID %d\n", cid);
561 return;
562 }
563
564 wil->sta[cid].data_port_open = true;
537 netif_carrier_on(ndev); 565 netif_carrier_on(ndev);
538} 566}
539 567
@@ -541,10 +569,17 @@ static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len)
541{ 569{
542 struct net_device *ndev = wil_to_ndev(wil); 570 struct net_device *ndev = wil_to_ndev(wil);
543 struct wmi_wbe_link_down_event *evt = d; 571 struct wmi_wbe_link_down_event *evt = d;
572 u8 cid = evt->cid;
544 573
545 wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n", 574 wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n",
546 evt->cid, le32_to_cpu(evt->reason)); 575 cid, le32_to_cpu(evt->reason));
576
577 if (cid >= ARRAY_SIZE(wil->sta)) {
578 wil_err(wil, "Link DOWN for invalid CID %d\n", cid);
579 return;
580 }
547 581
582 wil->sta[cid].data_port_open = false;
548 netif_carrier_off(ndev); 583 netif_carrier_off(ndev);
549} 584}
550 585
@@ -552,10 +587,42 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
552 int len) 587 int len)
553{ 588{
554 struct wmi_vring_ba_status_event *evt = d; 589 struct wmi_vring_ba_status_event *evt = d;
590 struct wil_sta_info *sta;
591 uint i, cid;
592
593 /* TODO: use Rx BA status, not Tx one */
555 594
556 wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n", 595 wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n",
557 evt->ringid, evt->status ? "N/A" : "OK", evt->agg_wsize, 596 evt->ringid,
558 __le16_to_cpu(evt->ba_timeout)); 597 evt->status == WMI_BA_AGREED ? "OK" : "N/A",
598 evt->agg_wsize, __le16_to_cpu(evt->ba_timeout));
599
600 if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
601 wil_err(wil, "invalid ring id %d\n", evt->ringid);
602 return;
603 }
604
605 cid = wil->vring2cid_tid[evt->ringid][0];
606 if (cid >= WIL6210_MAX_CID) {
607 wil_err(wil, "invalid CID %d for vring %d\n", cid, evt->ringid);
608 return;
609 }
610
611 sta = &wil->sta[cid];
612 if (sta->status == wil_sta_unused) {
613 wil_err(wil, "CID %d unused\n", cid);
614 return;
615 }
616
617 wil_dbg_wmi(wil, "BACK for CID %d %pM\n", cid, sta->addr);
618 for (i = 0; i < WIL_STA_TID_NUM; i++) {
619 struct wil_tid_ampdu_rx *r = sta->tid_rx[i];
620 sta->tid_rx[i] = NULL;
621 wil_tid_ampdu_rx_free(wil, r);
622 if ((evt->status == WMI_BA_AGREED) && evt->agg_wsize)
623 sta->tid_rx[i] = wil_tid_ampdu_rx_alloc(wil,
624 evt->agg_wsize, 0);
625 }
559} 626}
560 627
561static const struct { 628static const struct {
@@ -893,6 +960,38 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
893 return rc; 960 return rc;
894} 961}
895 962
963/**
964 * wmi_rxon - turn radio on/off
965 * @on: turn on if true, off otherwise
966 *
967 * Only switch radio. Channel should be set separately.
968 * No timeout for rxon - radio turned on forever unless some other call
969 * turns it off
970 */
971int wmi_rxon(struct wil6210_priv *wil, bool on)
972{
973 int rc;
974 struct {
975 struct wil6210_mbox_hdr_wmi wmi;
976 struct wmi_listen_started_event evt;
977 } __packed reply;
978
979 wil_info(wil, "%s(%s)\n", __func__, on ? "on" : "off");
980
981 if (on) {
982 rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
983 WMI_LISTEN_STARTED_EVENTID,
984 &reply, sizeof(reply), 100);
985 if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
986 rc = -EINVAL;
987 } else {
988 rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
989 WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
990 }
991
992 return rc;
993}
994
896int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) 995int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
897{ 996{
898 struct wireless_dev *wdev = wil->wdev; 997 struct wireless_dev *wdev = wil->wdev;
@@ -906,6 +1005,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
906 }, 1005 },
907 .mid = 0, /* TODO - what is it? */ 1006 .mid = 0, /* TODO - what is it? */
908 .decap_trans_type = WMI_DECAP_TYPE_802_3, 1007 .decap_trans_type = WMI_DECAP_TYPE_802_3,
1008 .reorder_type = WMI_RX_SW_REORDER,
909 }; 1009 };
910 struct { 1010 struct {
911 struct wil6210_mbox_hdr_wmi wmi; 1011 struct wil6210_mbox_hdr_wmi wmi;
@@ -973,6 +1073,18 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r)
973 return 0; 1073 return 0;
974} 1074}
975 1075
1076int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason)
1077{
1078 struct wmi_disconnect_sta_cmd cmd = {
1079 .disconnect_reason = cpu_to_le16(reason),
1080 };
1081 memcpy(cmd.dst_mac, mac, ETH_ALEN);
1082
1083 wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason);
1084
1085 return wmi_send(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd));
1086}
1087
976void wmi_event_flush(struct wil6210_priv *wil) 1088void wmi_event_flush(struct wil6210_priv *wil)
977{ 1089{
978 struct pending_wmi_event *evt, *t; 1090 struct pending_wmi_event *evt, *t;