aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
authorLevi, Shahar <shahar_levi@ti.com>2011-01-23 01:27:23 -0500
committerLuciano Coelho <coelho@ti.com>2011-01-24 15:58:47 -0500
commitbbba3e6832ad3e974fb593a98abe03f8b60fc7f3 (patch)
tree06a9d4d0a1e1d4838ad4d919ef0abe2e8780f671 /drivers/net/wireless/wl12xx
parent4b7fac77b4c1badac84df3dcbdf07199d94cb1c3 (diff)
wl12xx: BA receiver support
Add new ampdu_action ops to support receiver BA. The BA initiator session management in FW independently. Signed-off-by: Shahar Levi <shahar_levi@ti.com> Reviewed-by: Luciano Coelho <coelho@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r--drivers/net/wireless/wl12xx/acx.c34
-rw-r--r--drivers/net/wireless/wl12xx/acx.h25
-rw-r--r--drivers/net/wireless/wl12xx/init.c1
-rw-r--r--drivers/net/wireless/wl12xx/main.c60
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h1
5 files changed, 117 insertions, 4 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 0b9cacc74903..afdc601aa7ea 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1393,6 +1393,40 @@ out:
1393 return ret; 1393 return ret;
1394} 1394}
1395 1395
1396/* setup BA session receiver setting in the FW. */
1397int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
1398 bool enable)
1399{
1400 struct wl1271_acx_ba_receiver_setup *acx;
1401 int ret;
1402
1403 wl1271_debug(DEBUG_ACX, "acx ba receiver session setting");
1404
1405 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1406 if (!acx) {
1407 ret = -ENOMEM;
1408 goto out;
1409 }
1410
1411 /* Single link for now */
1412 acx->link_id = 1;
1413 acx->tid = tid_index;
1414 acx->enable = enable;
1415 acx->win_size = 0;
1416 acx->ssn = ssn;
1417
1418 ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
1419 sizeof(*acx));
1420 if (ret < 0) {
1421 wl1271_warning("acx ba receiver session failed: %d", ret);
1422 goto out;
1423 }
1424
1425out:
1426 kfree(acx);
1427 return ret;
1428}
1429
1396int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) 1430int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
1397{ 1431{
1398 struct wl1271_acx_fw_tsf_information *tsf_info; 1432 struct wl1271_acx_fw_tsf_information *tsf_info;
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index f643e60a566b..4bbaf04f434e 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1095,6 +1095,25 @@ struct wl1271_acx_ba_session_policy {
1095 u8 padding[3]; 1095 u8 padding[3];
1096} __packed; 1096} __packed;
1097 1097
1098struct wl1271_acx_ba_receiver_setup {
1099 struct acx_header header;
1100
1101 /* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */
1102 u8 link_id;
1103
1104 u8 tid;
1105
1106 u8 enable;
1107
1108 u8 padding[1];
1109
1110 /* Windows size in number of packets */
1111 u16 win_size;
1112
1113 /* BA session starting sequence number. RANGE 0-FFF */
1114 u16 ssn;
1115} __packed;
1116
1098struct wl1271_acx_fw_tsf_information { 1117struct wl1271_acx_fw_tsf_information {
1099 struct acx_header header; 1118 struct acx_header header;
1100 1119
@@ -1244,8 +1263,10 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
1244int wl1271_acx_set_ht_information(struct wl1271 *wl, 1263int wl1271_acx_set_ht_information(struct wl1271 *wl,
1245 u16 ht_operation_mode); 1264 u16 ht_operation_mode);
1246int wl1271_acx_set_ba_session(struct wl1271 *wl, 1265int wl1271_acx_set_ba_session(struct wl1271 *wl,
1247 enum ieee80211_back_parties direction, 1266 enum ieee80211_back_parties direction,
1248 u8 tid_index, u8 policy); 1267 u8 tid_index, u8 policy);
1268int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
1269 bool enable);
1249int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); 1270int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
1250int wl1271_acx_max_tx_retry(struct wl1271 *wl); 1271int wl1271_acx_max_tx_retry(struct wl1271 *wl);
1251 1272
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 2348eadc0de1..70b3dc88a219 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -473,7 +473,6 @@ static int wl1271_set_ba_policies(struct wl1271 *wl)
473 u8 ret = 0; 473 u8 ret = 0;
474 474
475 /* Reset the BA RX indicators */ 475 /* Reset the BA RX indicators */
476 wl->ba_allowed = true;
477 wl->ba_rx_bitmap = 0; 476 wl->ba_rx_bitmap = 0;
478 477
479 /* validate that FW support BA */ 478 /* validate that FW support BA */
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 01ca666b6c2d..eda2f3d8edf1 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2724,6 +2724,65 @@ out:
2724 return ret; 2724 return ret;
2725} 2725}
2726 2726
2727int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2728 enum ieee80211_ampdu_mlme_action action,
2729 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
2730{
2731 struct wl1271 *wl = hw->priv;
2732 int ret;
2733
2734 mutex_lock(&wl->mutex);
2735
2736 if (unlikely(wl->state == WL1271_STATE_OFF)) {
2737 ret = -EAGAIN;
2738 goto out;
2739 }
2740
2741 ret = wl1271_ps_elp_wakeup(wl, false);
2742 if (ret < 0)
2743 goto out;
2744
2745 switch (action) {
2746 case IEEE80211_AMPDU_RX_START:
2747 if (wl->ba_support) {
2748 ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
2749 true);
2750 if (!ret)
2751 wl->ba_rx_bitmap |= BIT(tid);
2752 } else {
2753 ret = -ENOTSUPP;
2754 }
2755 break;
2756
2757 case IEEE80211_AMPDU_RX_STOP:
2758 ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false);
2759 if (!ret)
2760 wl->ba_rx_bitmap &= ~BIT(tid);
2761 break;
2762
2763 /*
2764 * The BA initiator session management in FW independently.
2765 * Falling break here on purpose for all TX APDU commands.
2766 */
2767 case IEEE80211_AMPDU_TX_START:
2768 case IEEE80211_AMPDU_TX_STOP:
2769 case IEEE80211_AMPDU_TX_OPERATIONAL:
2770 ret = -EINVAL;
2771 break;
2772
2773 default:
2774 wl1271_error("Incorrect ampdu action id=%x\n", action);
2775 ret = -EINVAL;
2776 }
2777
2778 wl1271_ps_elp_sleep(wl);
2779
2780out:
2781 mutex_unlock(&wl->mutex);
2782
2783 return ret;
2784}
2785
2727/* can't be const, mac80211 writes to this */ 2786/* can't be const, mac80211 writes to this */
2728static struct ieee80211_rate wl1271_rates[] = { 2787static struct ieee80211_rate wl1271_rates[] = {
2729 { .bitrate = 10, 2788 { .bitrate = 10,
@@ -2973,6 +3032,7 @@ static const struct ieee80211_ops wl1271_ops = {
2973 .get_survey = wl1271_op_get_survey, 3032 .get_survey = wl1271_op_get_survey,
2974 .sta_add = wl1271_op_sta_add, 3033 .sta_add = wl1271_op_sta_add,
2975 .sta_remove = wl1271_op_sta_remove, 3034 .sta_remove = wl1271_op_sta_remove,
3035 .ampdu_action = wl1271_op_ampdu_action,
2976 CFG80211_TESTMODE_CMD(wl1271_tm_cmd) 3036 CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
2977}; 3037};
2978 3038
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index e0bac79cd516..d1de13fe7d9a 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -473,7 +473,6 @@ struct wl1271 {
473 473
474 /* RX BA constraint value */ 474 /* RX BA constraint value */
475 bool ba_support; 475 bool ba_support;
476 u8 ba_allowed;
477 u8 ba_rx_bitmap; 476 u8 ba_rx_bitmap;
478}; 477};
479 478