aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2012-11-28 04:42:31 -0500
committerLuciano Coelho <coelho@ti.com>2012-12-11 02:35:34 -0500
commit530abe195df6918d43c9381fd9a70b7e16d55036 (patch)
treeac8b080cfd5732de975c76e54d7244ec83a0a93b /drivers/net
parent4d703847617fa053689b119e43122088c81ef86d (diff)
wlcore: add ACX_PEER_CAP command
ACX_PEER_CAP command is just ACX_PEER_HT_CAP, but allows configuring the peer's support rates as well. this is needed because we start the station role when the remote rates are not known yet. the two commands should be unified in future fw versions, but for now add a new set_peer_cap per-hw op, that will use ACX_PEER_CAP for 18xx, and ACX_PEER_HT_CAP for 12xx. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c10
-rw-r--r--drivers/net/wireless/ti/wl18xx/acx.c54
-rw-r--r--drivers/net/wireless/ti/wl18xx/acx.h33
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c9
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c7
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h13
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c9
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h5
9 files changed, 134 insertions, 8 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 64dffafa35fb..8b4827f47deb 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1616,6 +1616,15 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
1616 return wlcore_set_key(wl, cmd, vif, sta, key_conf); 1616 return wlcore_set_key(wl, cmd, vif, sta, key_conf);
1617} 1617}
1618 1618
1619static int wl12xx_set_peer_cap(struct wl1271 *wl,
1620 struct ieee80211_sta_ht_cap *ht_cap,
1621 bool allow_ht_operation,
1622 u32 rate_set, u8 hlid)
1623{
1624 return wl1271_acx_set_ht_capabilities(wl, ht_cap, allow_ht_operation,
1625 hlid);
1626}
1627
1619static int wl12xx_setup(struct wl1271 *wl); 1628static int wl12xx_setup(struct wl1271 *wl);
1620 1629
1621static struct wlcore_ops wl12xx_ops = { 1630static struct wlcore_ops wl12xx_ops = {
@@ -1651,6 +1660,7 @@ static struct wlcore_ops wl12xx_ops = {
1651 .set_key = wl12xx_set_key, 1660 .set_key = wl12xx_set_key,
1652 .channel_switch = wl12xx_cmd_channel_switch, 1661 .channel_switch = wl12xx_cmd_channel_switch,
1653 .pre_pkt_send = NULL, 1662 .pre_pkt_send = NULL,
1663 .set_peer_cap = wl12xx_set_peer_cap,
1654}; 1664};
1655 1665
1656static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { 1666static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c
index 801d8af5cef2..a169bb5a5dbf 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.c
+++ b/drivers/net/wireless/ti/wl18xx/acx.c
@@ -140,3 +140,57 @@ out:
140 return ret; 140 return ret;
141 141
142} 142}
143
144/*
145 * this command is basically the same as wl1271_acx_ht_capabilities,
146 * with the addition of supported rates. they should be unified in
147 * the next fw api change
148 */
149int wl18xx_acx_set_peer_cap(struct wl1271 *wl,
150 struct ieee80211_sta_ht_cap *ht_cap,
151 bool allow_ht_operation,
152 u32 rate_set, u8 hlid)
153{
154 struct wlcore_acx_peer_cap *acx;
155 int ret = 0;
156 u32 ht_capabilites = 0;
157
158 wl1271_debug(DEBUG_ACX,
159 "acx set cap ht_supp: %d ht_cap: %d rates: 0x%x",
160 ht_cap->ht_supported, ht_cap->cap, rate_set);
161
162 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
163 if (!acx) {
164 ret = -ENOMEM;
165 goto out;
166 }
167
168 if (allow_ht_operation && ht_cap->ht_supported) {
169 /* no need to translate capabilities - use the spec values */
170 ht_capabilites = ht_cap->cap;
171
172 /*
173 * this bit is not employed by the spec but only by FW to
174 * indicate peer HT support
175 */
176 ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION;
177
178 /* get data from A-MPDU parameters field */
179 acx->ampdu_max_length = ht_cap->ampdu_factor;
180 acx->ampdu_min_spacing = ht_cap->ampdu_density;
181 }
182
183 acx->hlid = hlid;
184 acx->ht_capabilites = cpu_to_le32(ht_capabilites);
185 acx->supported_rates = cpu_to_le32(rate_set);
186
187 ret = wl1271_cmd_configure(wl, ACX_PEER_CAP, acx, sizeof(*acx));
188 if (ret < 0) {
189 wl1271_warning("acx ht capabilities setting failed: %d", ret);
190 goto out;
191 }
192
193out:
194 kfree(acx);
195 return ret;
196}
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index b57e3483509d..0e636def1217 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -297,11 +297,44 @@ struct wlcore_peer_ht_operation_mode {
297 u8 padding[2]; 297 u8 padding[2];
298}; 298};
299 299
300/*
301 * ACX_PEER_CAP
302 * this struct is very similar to wl1271_acx_ht_capabilities, with the
303 * addition of supported rates
304 */
305struct wlcore_acx_peer_cap {
306 struct acx_header header;
307
308 /* bitmask of capability bits supported by the peer */
309 __le32 ht_capabilites;
310
311 /* rates supported by the remote peer */
312 __le32 supported_rates;
313
314 /* Indicates to which link these capabilities apply. */
315 u8 hlid;
316
317 /*
318 * This the maximum A-MPDU length supported by the AP. The FW may not
319 * exceed this length when sending A-MPDUs
320 */
321 u8 ampdu_max_length;
322
323 /* This is the minimal spacing required when sending A-MPDUs to the AP*/
324 u8 ampdu_min_spacing;
325
326 u8 padding;
327} __packed;
328
300int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, 329int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
301 u32 sdio_blk_size, u32 extra_mem_blks, 330 u32 sdio_blk_size, u32 extra_mem_blks,
302 u32 len_field_size); 331 u32 len_field_size);
303int wl18xx_acx_set_checksum_state(struct wl1271 *wl); 332int wl18xx_acx_set_checksum_state(struct wl1271 *wl);
304int wl18xx_acx_clear_statistics(struct wl1271 *wl); 333int wl18xx_acx_clear_statistics(struct wl1271 *wl);
305int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide); 334int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide);
335int wl18xx_acx_set_peer_cap(struct wl1271 *wl,
336 struct ieee80211_sta_ht_cap *ht_cap,
337 bool allow_ht_operation,
338 u32 rate_set, u8 hlid);
306 339
307#endif /* __WL18XX_ACX_H__ */ 340#endif /* __WL18XX_ACX_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index a5119d3d5e70..55fd46b9628d 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1386,6 +1386,14 @@ out:
1386 mutex_unlock(&wl->mutex); 1386 mutex_unlock(&wl->mutex);
1387} 1387}
1388 1388
1389static int wl18xx_set_peer_cap(struct wl1271 *wl,
1390 struct ieee80211_sta_ht_cap *ht_cap,
1391 bool allow_ht_operation,
1392 u32 rate_set, u8 hlid)
1393{
1394 return wl18xx_acx_set_peer_cap(wl, ht_cap, allow_ht_operation,
1395 rate_set, hlid);
1396}
1389 1397
1390static int wl18xx_setup(struct wl1271 *wl); 1398static int wl18xx_setup(struct wl1271 *wl);
1391 1399
@@ -1423,6 +1431,7 @@ static struct wlcore_ops wl18xx_ops = {
1423 .channel_switch = wl18xx_cmd_channel_switch, 1431 .channel_switch = wl18xx_cmd_channel_switch,
1424 .pre_pkt_send = wl18xx_pre_pkt_send, 1432 .pre_pkt_send = wl18xx_pre_pkt_send,
1425 .sta_rc_update = wl18xx_sta_rc_update, 1433 .sta_rc_update = wl18xx_sta_rc_update,
1434 .set_peer_cap = wl18xx_set_peer_cap,
1426}; 1435};
1427 1436
1428/* HT cap appropriate for wide channels in 2Ghz */ 1437/* HT cap appropriate for wide channels in 2Ghz */
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index 9c32f0c840d7..c79654323396 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -1340,6 +1340,8 @@ out:
1340 kfree(acx); 1340 kfree(acx);
1341 return ret; 1341 return ret;
1342} 1342}
1343EXPORT_SYMBOL_GPL(wl1271_acx_set_ht_capabilities);
1344
1343 1345
1344int wl1271_acx_set_ht_information(struct wl1271 *wl, 1346int wl1271_acx_set_ht_information(struct wl1271 *wl,
1345 struct wl12xx_vif *wlvif, 1347 struct wl12xx_vif *wlvif,
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 56432c8cda00..1fbee0d51872 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -506,11 +506,10 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
506 cmd->sta.hlid = wlvif->sta.hlid; 506 cmd->sta.hlid = wlvif->sta.hlid;
507 cmd->sta.session = wl->session_ids[wlvif->sta.hlid]; 507 cmd->sta.session = wl->session_ids[wlvif->sta.hlid];
508 /* 508 /*
509 * We don't have the correct remote rates in this stage, and there 509 * We don't have the correct remote rates in this stage. the rates
510 * is no way to update them later, so use our supported rates instead. 510 * will be reconfigured later, after authorization.
511 * The fw will take the configured rate policies into account anyway.
512 */ 511 */
513 cmd->sta.remote_rates = cpu_to_le32(supported_rates); 512 cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set);
514 513
515 wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " 514 wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
516 "basic_rate_set: 0x%x, remote_rates: 0x%x", 515 "basic_rate_set: 0x%x, remote_rates: 0x%x",
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 0e0b6563a3ff..4db03e14acf7 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -209,4 +209,17 @@ wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif,
209 wl->ops->sta_rc_update(wl, wlvif, sta, changed); 209 wl->ops->sta_rc_update(wl, wlvif, sta, changed);
210} 210}
211 211
212static inline int
213wlcore_hw_set_peer_cap(struct wl1271 *wl,
214 struct ieee80211_sta_ht_cap *ht_cap,
215 bool allow_ht_operation,
216 u32 rate_set, u8 hlid)
217{
218 if (wl->ops->set_peer_cap)
219 return wl->ops->set_peer_cap(wl, ht_cap, allow_ht_operation,
220 rate_set, hlid);
221
222 return 0;
223}
224
212#endif 225#endif
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 486b7fa0259c..fed227c88a8a 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4132,10 +4132,11 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
4132 bool enabled = 4132 bool enabled =
4133 bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT; 4133 bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT;
4134 4134
4135 ret = wl1271_acx_set_ht_capabilities(wl, 4135 ret = wlcore_hw_set_peer_cap(wl,
4136 &sta_ht_cap, 4136 &sta_ht_cap,
4137 enabled, 4137 enabled,
4138 wlvif->sta.hlid); 4138 wlvif->rate_set,
4139 wlvif->sta.hlid);
4139 if (ret < 0) { 4140 if (ret < 0) {
4140 wl1271_warning("Set ht cap failed %d", ret); 4141 wl1271_warning("Set ht cap failed %d", ret);
4141 goto out; 4142 goto out;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index e8245f36a67e..a4441164bb4b 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -106,6 +106,11 @@ struct wlcore_ops {
106 u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len); 106 u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len);
107 void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif, 107 void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
108 struct ieee80211_sta *sta, u32 changed); 108 struct ieee80211_sta *sta, u32 changed);
109 int (*set_peer_cap)(struct wl1271 *wl,
110 struct ieee80211_sta_ht_cap *ht_cap,
111 bool allow_ht_operation,
112 u32 rate_set, u8 hlid);
113
109}; 114};
110 115
111enum wlcore_partitions { 116enum wlcore_partitions {