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.c239
1 files changed, 189 insertions, 50 deletions
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 63476c86cd0e..0f3e4334c8e3 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -23,10 +23,15 @@
23#include "wmi.h" 23#include "wmi.h"
24#include "trace.h" 24#include "trace.h"
25 25
26static uint max_assoc_sta = 1; 26static uint max_assoc_sta = WIL6210_MAX_CID;
27module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR); 27module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR);
28MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP"); 28MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
29 29
30int agg_wsize; /* = 0; */
31module_param(agg_wsize, int, S_IRUGO | S_IWUSR);
32MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
33 " 0 - use default; < 0 - don't auto-establish");
34
30/** 35/**
31 * WMI event receiving - theory of operations 36 * WMI event receiving - theory of operations
32 * 37 *
@@ -197,7 +202,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
197 202
198 might_sleep(); 203 might_sleep();
199 204
200 if (!test_bit(wil_status_fwready, &wil->status)) { 205 if (!test_bit(wil_status_fwready, wil->status)) {
201 wil_err(wil, "WMI: cannot send command while FW not ready\n"); 206 wil_err(wil, "WMI: cannot send command while FW not ready\n");
202 return -EAGAIN; 207 return -EAGAIN;
203 } 208 }
@@ -300,7 +305,7 @@ static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
300 wil_dbg_wmi(wil, "WMI: got FW ready event\n"); 305 wil_dbg_wmi(wil, "WMI: got FW ready event\n");
301 306
302 wil_set_recovery_state(wil, fw_recovery_idle); 307 wil_set_recovery_state(wil, fw_recovery_idle);
303 set_bit(wil_status_fwready, &wil->status); 308 set_bit(wil_status_fwready, wil->status);
304 /* let the reset sequence continue */ 309 /* let the reset sequence continue */
305 complete(&wil->wmi_ready); 310 complete(&wil->wmi_ready);
306} 311}
@@ -438,7 +443,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
438 443
439 if ((wdev->iftype == NL80211_IFTYPE_STATION) || 444 if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
440 (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { 445 (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
441 if (!test_bit(wil_status_fwconnecting, &wil->status)) { 446 if (!test_bit(wil_status_fwconnecting, wil->status)) {
442 wil_err(wil, "Not in connecting state\n"); 447 wil_err(wil, "Not in connecting state\n");
443 return; 448 return;
444 } 449 }
@@ -457,13 +462,12 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
457 if (assoc_req_ie) { 462 if (assoc_req_ie) {
458 sinfo.assoc_req_ies = assoc_req_ie; 463 sinfo.assoc_req_ies = assoc_req_ie;
459 sinfo.assoc_req_ies_len = assoc_req_ielen; 464 sinfo.assoc_req_ies_len = assoc_req_ielen;
460 sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
461 } 465 }
462 466
463 cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); 467 cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
464 } 468 }
465 clear_bit(wil_status_fwconnecting, &wil->status); 469 clear_bit(wil_status_fwconnecting, wil->status);
466 set_bit(wil_status_fwconnected, &wil->status); 470 set_bit(wil_status_fwconnected, wil->status);
467 471
468 /* FIXME FW can transmit only ucast frames to peer */ 472 /* FIXME FW can transmit only ucast frames to peer */
469 /* FIXME real ring_id instead of hard coded 0 */ 473 /* FIXME real ring_id instead of hard coded 0 */
@@ -471,7 +475,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
471 wil->sta[evt->cid].status = wil_sta_conn_pending; 475 wil->sta[evt->cid].status = wil_sta_conn_pending;
472 476
473 wil->pending_connect_cid = evt->cid; 477 wil->pending_connect_cid = evt->cid;
474 queue_work(wil->wmi_wq_conn, &wil->connect_worker); 478 queue_work(wil->wq_service, &wil->connect_worker);
475} 479}
476 480
477static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, 481static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
@@ -544,9 +548,24 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
544 } 548 }
545} 549}
546 550
551static void wil_addba_tx_cid(struct wil6210_priv *wil, u8 cid, u16 wsize)
552{
553 struct vring_tx_data *t;
554 int i;
555
556 for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
557 if (cid != wil->vring2cid_tid[i][0])
558 continue;
559 t = &wil->vring_tx_data[i];
560 if (!t->enabled)
561 continue;
562
563 wil_addba_tx_request(wil, i, wsize);
564 }
565}
566
547static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) 567static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
548{ 568{
549 struct net_device *ndev = wil_to_ndev(wil);
550 struct wmi_data_port_open_event *evt = d; 569 struct wmi_data_port_open_event *evt = d;
551 u8 cid = evt->cid; 570 u8 cid = evt->cid;
552 571
@@ -558,7 +577,8 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
558 } 577 }
559 578
560 wil->sta[cid].data_port_open = true; 579 wil->sta[cid].data_port_open = true;
561 netif_carrier_on(ndev); 580 if (agg_wsize >= 0)
581 wil_addba_tx_cid(wil, cid, agg_wsize);
562} 582}
563 583
564static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) 584static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len)
@@ -583,55 +603,89 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
583 int len) 603 int len)
584{ 604{
585 struct wmi_vring_ba_status_event *evt = d; 605 struct wmi_vring_ba_status_event *evt = d;
586 struct wil_sta_info *sta; 606 struct vring_tx_data *txdata;
587 uint i, cid;
588 607
589 /* TODO: use Rx BA status, not Tx one */ 608 wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
590
591 wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n",
592 evt->ringid, 609 evt->ringid,
593 evt->status == WMI_BA_AGREED ? "OK" : "N/A", 610 evt->status == WMI_BA_AGREED ? "OK" : "N/A",
594 evt->agg_wsize, __le16_to_cpu(evt->ba_timeout)); 611 evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
612 evt->amsdu ? "+" : "-");
595 613
596 if (evt->ringid >= WIL6210_MAX_TX_RINGS) { 614 if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
597 wil_err(wil, "invalid ring id %d\n", evt->ringid); 615 wil_err(wil, "invalid ring id %d\n", evt->ringid);
598 return; 616 return;
599 } 617 }
600 618
601 mutex_lock(&wil->mutex); 619 if (evt->status != WMI_BA_AGREED) {
602 620 evt->ba_timeout = 0;
603 cid = wil->vring2cid_tid[evt->ringid][0]; 621 evt->agg_wsize = 0;
604 if (cid >= WIL6210_MAX_CID) { 622 evt->amsdu = 0;
605 wil_err(wil, "invalid CID %d for vring %d\n", cid, evt->ringid);
606 goto out;
607 } 623 }
608 624
609 sta = &wil->sta[cid]; 625 txdata = &wil->vring_tx_data[evt->ringid];
610 if (sta->status == wil_sta_unused) {
611 wil_err(wil, "CID %d unused\n", cid);
612 goto out;
613 }
614 626
615 wil_dbg_wmi(wil, "BACK for CID %d %pM\n", cid, sta->addr); 627 txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
616 for (i = 0; i < WIL_STA_TID_NUM; i++) { 628 txdata->agg_wsize = evt->agg_wsize;
617 struct wil_tid_ampdu_rx *r; 629 txdata->agg_amsdu = evt->amsdu;
618 unsigned long flags; 630 txdata->addba_in_progress = false;
631}
619 632
620 spin_lock_irqsave(&sta->tid_rx_lock, flags); 633static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
634 int len)
635{
636 struct wmi_rcp_addba_req_event *evt = d;
621 637
622 r = sta->tid_rx[i]; 638 wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
623 sta->tid_rx[i] = NULL; 639 evt->ba_param_set, evt->ba_timeout,
624 wil_tid_ampdu_rx_free(wil, r); 640 evt->ba_seq_ctrl);
641}
625 642
626 spin_unlock_irqrestore(&sta->tid_rx_lock, flags); 643static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
644__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
645{
646 struct wmi_delba_event *evt = d;
647 u8 cid, tid;
648 u16 reason = __le16_to_cpu(evt->reason);
649 struct wil_sta_info *sta;
650 struct wil_tid_ampdu_rx *r;
627 651
628 if ((evt->status == WMI_BA_AGREED) && evt->agg_wsize) 652 might_sleep();
629 sta->tid_rx[i] = wil_tid_ampdu_rx_alloc(wil, 653 parse_cidxtid(evt->cidxtid, &cid, &tid);
630 evt->agg_wsize, 0); 654 wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
655 cid, tid,
656 evt->from_initiator ? "originator" : "recipient",
657 reason);
658 if (!evt->from_initiator) {
659 int i;
660 /* find Tx vring it belongs to */
661 for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
662 if ((wil->vring2cid_tid[i][0] == cid) &&
663 (wil->vring2cid_tid[i][1] == tid)) {
664 struct vring_tx_data *txdata =
665 &wil->vring_tx_data[i];
666
667 wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
668 txdata->agg_timeout = 0;
669 txdata->agg_wsize = 0;
670 txdata->addba_in_progress = false;
671
672 break; /* max. 1 matching ring */
673 }
674 }
675 if (i >= ARRAY_SIZE(wil->vring2cid_tid))
676 wil_err(wil, "DELBA: unable to find Tx vring\n");
677 return;
631 } 678 }
632 679
633out: 680 sta = &wil->sta[cid];
634 mutex_unlock(&wil->mutex); 681
682 spin_lock_bh(&sta->tid_rx_lock);
683
684 r = sta->tid_rx[tid];
685 sta->tid_rx[tid] = NULL;
686 wil_tid_ampdu_rx_free(wil, r);
687
688 spin_unlock_bh(&sta->tid_rx_lock);
635} 689}
636 690
637static const struct { 691static const struct {
@@ -649,6 +703,8 @@ static const struct {
649 {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_linkup}, 703 {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_linkup},
650 {WMI_WBE_LINKDOWN_EVENTID, wmi_evt_linkdown}, 704 {WMI_WBE_LINKDOWN_EVENTID, wmi_evt_linkdown},
651 {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status}, 705 {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status},
706 {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
707 {WMI_DELBA_EVENTID, wmi_evt_delba},
652}; 708};
653 709
654/* 710/*
@@ -668,7 +724,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
668 ulong flags; 724 ulong flags;
669 unsigned n; 725 unsigned n;
670 726
671 if (!test_bit(wil_status_reset_done, &wil->status)) { 727 if (!test_bit(wil_status_reset_done, wil->status)) {
672 wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); 728 wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
673 return; 729 return;
674 } 730 }
@@ -1025,13 +1081,14 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
1025 struct wmi_cfg_rx_chain_cmd cmd = { 1081 struct wmi_cfg_rx_chain_cmd cmd = {
1026 .action = WMI_RX_CHAIN_ADD, 1082 .action = WMI_RX_CHAIN_ADD,
1027 .rx_sw_ring = { 1083 .rx_sw_ring = {
1028 .max_mpdu_size = cpu_to_le16(mtu_max + ETH_HLEN), 1084 .max_mpdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
1029 .ring_mem_base = cpu_to_le64(vring->pa), 1085 .ring_mem_base = cpu_to_le64(vring->pa),
1030 .ring_size = cpu_to_le16(vring->size), 1086 .ring_size = cpu_to_le16(vring->size),
1031 }, 1087 },
1032 .mid = 0, /* TODO - what is it? */ 1088 .mid = 0, /* TODO - what is it? */
1033 .decap_trans_type = WMI_DECAP_TYPE_802_3, 1089 .decap_trans_type = WMI_DECAP_TYPE_802_3,
1034 .reorder_type = WMI_RX_SW_REORDER, 1090 .reorder_type = WMI_RX_SW_REORDER,
1091 .host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
1035 }; 1092 };
1036 struct { 1093 struct {
1037 struct wil6210_mbox_hdr_wmi wmi; 1094 struct wil6210_mbox_hdr_wmi wmi;
@@ -1074,12 +1131,13 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
1074 return rc; 1131 return rc;
1075} 1132}
1076 1133
1077int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r) 1134int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
1078{ 1135{
1079 int rc; 1136 int rc;
1080 struct wmi_temp_sense_cmd cmd = { 1137 struct wmi_temp_sense_cmd cmd = {
1081 .measure_marlon_m_en = cpu_to_le32(!!t_m), 1138 .measure_baseband_en = cpu_to_le32(!!t_bb),
1082 .measure_marlon_r_en = cpu_to_le32(!!t_r), 1139 .measure_rf_en = cpu_to_le32(!!t_rf),
1140 .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
1083 }; 1141 };
1084 struct { 1142 struct {
1085 struct wil6210_mbox_hdr_wmi wmi; 1143 struct wil6210_mbox_hdr_wmi wmi;
@@ -1091,10 +1149,10 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r)
1091 if (rc) 1149 if (rc)
1092 return rc; 1150 return rc;
1093 1151
1094 if (t_m) 1152 if (t_bb)
1095 *t_m = le32_to_cpu(reply.evt.marlon_m_t1000); 1153 *t_bb = le32_to_cpu(reply.evt.baseband_t1000);
1096 if (t_r) 1154 if (t_rf)
1097 *t_r = le32_to_cpu(reply.evt.marlon_r_t1000); 1155 *t_rf = le32_to_cpu(reply.evt.rf_t1000);
1098 1156
1099 return 0; 1157 return 0;
1100} 1158}
@@ -1111,6 +1169,87 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason)
1111 return wmi_send(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd)); 1169 return wmi_send(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd));
1112} 1170}
1113 1171
1172int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
1173{
1174 struct wmi_vring_ba_en_cmd cmd = {
1175 .ringid = ringid,
1176 .agg_max_wsize = size,
1177 .ba_timeout = cpu_to_le16(timeout),
1178 .amsdu = 0,
1179 };
1180
1181 wil_dbg_wmi(wil, "%s(ring %d size %d timeout %d)\n", __func__,
1182 ringid, size, timeout);
1183
1184 return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
1185}
1186
1187int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
1188{
1189 struct wmi_vring_ba_dis_cmd cmd = {
1190 .ringid = ringid,
1191 .reason = cpu_to_le16(reason),
1192 };
1193
1194 wil_dbg_wmi(wil, "%s(ring %d reason %d)\n", __func__,
1195 ringid, reason);
1196
1197 return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
1198}
1199
1200int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
1201{
1202 struct wmi_rcp_delba_cmd cmd = {
1203 .cidxtid = cidxtid,
1204 .reason = cpu_to_le16(reason),
1205 };
1206
1207 wil_dbg_wmi(wil, "%s(CID %d TID %d reason %d)\n", __func__,
1208 cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason);
1209
1210 return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
1211}
1212
1213int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
1214 u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
1215{
1216 int rc;
1217 struct wmi_rcp_addba_resp_cmd cmd = {
1218 .cidxtid = mk_cidxtid(cid, tid),
1219 .dialog_token = token,
1220 .status_code = cpu_to_le16(status),
1221 /* bit 0: A-MSDU supported
1222 * bit 1: policy (should be 0 for us)
1223 * bits 2..5: TID
1224 * bits 6..15: buffer size
1225 */
1226 .ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
1227 (agg_wsize << 6)),
1228 .ba_timeout = cpu_to_le16(timeout),
1229 };
1230 struct {
1231 struct wil6210_mbox_hdr_wmi wmi;
1232 struct wmi_rcp_addba_resp_sent_event evt;
1233 } __packed reply;
1234
1235 wil_dbg_wmi(wil,
1236 "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
1237 cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
1238
1239 rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
1240 WMI_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply), 100);
1241 if (rc)
1242 return rc;
1243
1244 if (reply.evt.status) {
1245 wil_err(wil, "ADDBA response failed with status %d\n",
1246 le16_to_cpu(reply.evt.status));
1247 rc = -EINVAL;
1248 }
1249
1250 return rc;
1251}
1252
1114void wmi_event_flush(struct wil6210_priv *wil) 1253void wmi_event_flush(struct wil6210_priv *wil)
1115{ 1254{
1116 struct pending_wmi_event *evt, *t; 1255 struct pending_wmi_event *evt, *t;