diff options
author | Sujith Manoharan <Sujith.Manoharan@atheros.com> | 2011-04-13 01:56:52 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-13 15:24:37 -0400 |
commit | 821f9414c0546fbc99a999e9dc613d1756e1de8a (patch) | |
tree | cef5c7efdd46a12e9de971b572ebba74a8eb6d84 /drivers/net/wireless/ath | |
parent | 2f80194c90caea3668d0e3739518bf100449a813 (diff) |
ath9k_htc: Use helper routines for transmission
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 227 |
1 files changed, 127 insertions, 100 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 86f5ce9b6e0e..723a3a9c5cd9 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -211,28 +211,140 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | |||
211 | return error; | 211 | return error; |
212 | } | 212 | } |
213 | 213 | ||
214 | static void ath9k_htc_tx_mgmt(struct ath9k_htc_priv *priv, | ||
215 | struct ath9k_htc_vif *avp, | ||
216 | struct sk_buff *skb, | ||
217 | u8 sta_idx, u8 vif_idx, u8 slot) | ||
218 | { | ||
219 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
220 | struct ieee80211_mgmt *mgmt; | ||
221 | struct ieee80211_hdr *hdr; | ||
222 | struct tx_mgmt_hdr mgmt_hdr; | ||
223 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
224 | u8 *tx_fhdr; | ||
225 | |||
226 | tx_ctl = HTC_SKB_CB(skb); | ||
227 | hdr = (struct ieee80211_hdr *) skb->data; | ||
228 | |||
229 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
230 | memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); | ||
231 | |||
232 | /* | ||
233 | * Set the TSF adjust value for probe response | ||
234 | * frame also. | ||
235 | */ | ||
236 | if (avp && unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { | ||
237 | mgmt = (struct ieee80211_mgmt *)skb->data; | ||
238 | mgmt->u.probe_resp.timestamp = avp->tsfadjust; | ||
239 | } | ||
240 | |||
241 | tx_ctl->type = ATH9K_HTC_MGMT; | ||
242 | |||
243 | mgmt_hdr.node_idx = sta_idx; | ||
244 | mgmt_hdr.vif_idx = vif_idx; | ||
245 | mgmt_hdr.tidno = 0; | ||
246 | mgmt_hdr.flags = 0; | ||
247 | mgmt_hdr.cookie = slot; | ||
248 | |||
249 | mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
250 | if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
251 | mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
252 | else | ||
253 | mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
254 | |||
255 | tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); | ||
256 | memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); | ||
257 | tx_ctl->epid = priv->mgmt_ep; | ||
258 | } | ||
259 | |||
260 | static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv, | ||
261 | struct ieee80211_vif *vif, | ||
262 | struct sk_buff *skb, | ||
263 | u8 sta_idx, u8 vif_idx, u8 slot, | ||
264 | bool is_cab) | ||
265 | { | ||
266 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
267 | struct ieee80211_hdr *hdr; | ||
268 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
269 | struct tx_frame_hdr tx_hdr; | ||
270 | u32 flags = 0; | ||
271 | u8 *qc, *tx_fhdr; | ||
272 | u16 qnum; | ||
273 | |||
274 | tx_ctl = HTC_SKB_CB(skb); | ||
275 | hdr = (struct ieee80211_hdr *) skb->data; | ||
276 | |||
277 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
278 | memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); | ||
279 | |||
280 | tx_hdr.node_idx = sta_idx; | ||
281 | tx_hdr.vif_idx = vif_idx; | ||
282 | tx_hdr.cookie = slot; | ||
283 | |||
284 | /* | ||
285 | * This is a bit redundant but it helps to get | ||
286 | * the per-packet index quickly when draining the | ||
287 | * TX queue in the HIF layer. Otherwise we would | ||
288 | * have to parse the packet contents ... | ||
289 | */ | ||
290 | tx_ctl->sta_idx = sta_idx; | ||
291 | |||
292 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
293 | tx_ctl->type = ATH9K_HTC_AMPDU; | ||
294 | tx_hdr.data_type = ATH9K_HTC_AMPDU; | ||
295 | } else { | ||
296 | tx_ctl->type = ATH9K_HTC_NORMAL; | ||
297 | tx_hdr.data_type = ATH9K_HTC_NORMAL; | ||
298 | } | ||
299 | |||
300 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
301 | qc = ieee80211_get_qos_ctl(hdr); | ||
302 | tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
303 | } | ||
304 | |||
305 | /* Check for RTS protection */ | ||
306 | if (priv->hw->wiphy->rts_threshold != (u32) -1) | ||
307 | if (skb->len > priv->hw->wiphy->rts_threshold) | ||
308 | flags |= ATH9K_HTC_TX_RTSCTS; | ||
309 | |||
310 | /* CTS-to-self */ | ||
311 | if (!(flags & ATH9K_HTC_TX_RTSCTS) && | ||
312 | (vif && vif->bss_conf.use_cts_prot)) | ||
313 | flags |= ATH9K_HTC_TX_CTSONLY; | ||
314 | |||
315 | tx_hdr.flags = cpu_to_be32(flags); | ||
316 | tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
317 | if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
318 | tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
319 | else | ||
320 | tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
321 | |||
322 | tx_fhdr = skb_push(skb, sizeof(tx_hdr)); | ||
323 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); | ||
324 | |||
325 | if (is_cab) { | ||
326 | CAB_STAT_INC; | ||
327 | tx_ctl->epid = priv->cab_ep; | ||
328 | return; | ||
329 | } | ||
330 | |||
331 | qnum = skb_get_queue_mapping(skb); | ||
332 | tx_ctl->epid = get_htc_epid(priv, qnum); | ||
333 | } | ||
334 | |||
214 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, | 335 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, |
215 | struct sk_buff *skb, | 336 | struct sk_buff *skb, |
216 | u8 slot, bool is_cab) | 337 | u8 slot, bool is_cab) |
217 | { | 338 | { |
218 | struct ieee80211_hdr *hdr; | 339 | struct ieee80211_hdr *hdr; |
219 | struct ieee80211_mgmt *mgmt; | ||
220 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 340 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
221 | struct ieee80211_sta *sta = tx_info->control.sta; | 341 | struct ieee80211_sta *sta = tx_info->control.sta; |
222 | struct ieee80211_vif *vif = tx_info->control.vif; | 342 | struct ieee80211_vif *vif = tx_info->control.vif; |
223 | struct ath9k_htc_sta *ista; | 343 | struct ath9k_htc_sta *ista; |
224 | struct ath9k_htc_vif *avp = NULL; | 344 | struct ath9k_htc_vif *avp = NULL; |
225 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
226 | u16 qnum; | ||
227 | __le16 fc; | ||
228 | u8 *tx_fhdr; | ||
229 | u8 sta_idx, vif_idx; | 345 | u8 sta_idx, vif_idx; |
230 | 346 | ||
231 | tx_ctl = HTC_SKB_CB(skb); | ||
232 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
233 | |||
234 | hdr = (struct ieee80211_hdr *) skb->data; | 347 | hdr = (struct ieee80211_hdr *) skb->data; |
235 | fc = hdr->frame_control; | ||
236 | 348 | ||
237 | /* | 349 | /* |
238 | * Find out on which interface this packet has to be | 350 | * Find out on which interface this packet has to be |
@@ -261,99 +373,14 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, | |||
261 | sta_idx = priv->vif_sta_pos[vif_idx]; | 373 | sta_idx = priv->vif_sta_pos[vif_idx]; |
262 | } | 374 | } |
263 | 375 | ||
264 | if (ieee80211_is_data(fc)) { | 376 | if (ieee80211_is_data(hdr->frame_control)) |
265 | struct tx_frame_hdr tx_hdr; | 377 | ath9k_htc_tx_data(priv, vif, skb, |
266 | u32 flags = 0; | 378 | sta_idx, vif_idx, slot, is_cab); |
267 | u8 *qc; | 379 | else |
268 | 380 | ath9k_htc_tx_mgmt(priv, avp, skb, | |
269 | memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); | 381 | sta_idx, vif_idx, slot); |
270 | |||
271 | tx_hdr.node_idx = sta_idx; | ||
272 | tx_hdr.vif_idx = vif_idx; | ||
273 | tx_hdr.cookie = slot; | ||
274 | |||
275 | /* | ||
276 | * This is a bit redundant but it helps to get | ||
277 | * the per-packet index quickly when draining the | ||
278 | * TX queue in the HIF layer. Otherwise we would | ||
279 | * have to parse the packet contents ... | ||
280 | */ | ||
281 | tx_ctl->sta_idx = sta_idx; | ||
282 | |||
283 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
284 | tx_ctl->type = ATH9K_HTC_AMPDU; | ||
285 | tx_hdr.data_type = ATH9K_HTC_AMPDU; | ||
286 | } else { | ||
287 | tx_ctl->type = ATH9K_HTC_NORMAL; | ||
288 | tx_hdr.data_type = ATH9K_HTC_NORMAL; | ||
289 | } | ||
290 | |||
291 | if (ieee80211_is_data_qos(fc)) { | ||
292 | qc = ieee80211_get_qos_ctl(hdr); | ||
293 | tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
294 | } | ||
295 | |||
296 | /* Check for RTS protection */ | ||
297 | if (priv->hw->wiphy->rts_threshold != (u32) -1) | ||
298 | if (skb->len > priv->hw->wiphy->rts_threshold) | ||
299 | flags |= ATH9K_HTC_TX_RTSCTS; | ||
300 | |||
301 | /* CTS-to-self */ | ||
302 | if (!(flags & ATH9K_HTC_TX_RTSCTS) && | ||
303 | (vif && vif->bss_conf.use_cts_prot)) | ||
304 | flags |= ATH9K_HTC_TX_CTSONLY; | ||
305 | |||
306 | tx_hdr.flags = cpu_to_be32(flags); | ||
307 | tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
308 | if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
309 | tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
310 | else | ||
311 | tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
312 | |||
313 | tx_fhdr = skb_push(skb, sizeof(tx_hdr)); | ||
314 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); | ||
315 | |||
316 | if (is_cab) { | ||
317 | CAB_STAT_INC; | ||
318 | tx_ctl->epid = priv->cab_ep; | ||
319 | goto send; | ||
320 | } | ||
321 | |||
322 | qnum = skb_get_queue_mapping(skb); | ||
323 | tx_ctl->epid = get_htc_epid(priv, qnum); | ||
324 | } else { | ||
325 | struct tx_mgmt_hdr mgmt_hdr; | ||
326 | |||
327 | memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); | ||
328 | |||
329 | /* | ||
330 | * Set the TSF adjust value for probe response | ||
331 | * frame also. | ||
332 | */ | ||
333 | if (avp && unlikely(ieee80211_is_probe_resp(fc))) { | ||
334 | mgmt = (struct ieee80211_mgmt *)skb->data; | ||
335 | mgmt->u.probe_resp.timestamp = avp->tsfadjust; | ||
336 | } | ||
337 | |||
338 | tx_ctl->type = ATH9K_HTC_MGMT; | ||
339 | |||
340 | mgmt_hdr.node_idx = sta_idx; | ||
341 | mgmt_hdr.vif_idx = vif_idx; | ||
342 | mgmt_hdr.tidno = 0; | ||
343 | mgmt_hdr.flags = 0; | ||
344 | mgmt_hdr.cookie = slot; | ||
345 | 382 | ||
346 | mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
347 | if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
348 | mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
349 | else | ||
350 | mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
351 | 383 | ||
352 | tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); | ||
353 | memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); | ||
354 | tx_ctl->epid = priv->mgmt_ep; | ||
355 | } | ||
356 | send: | ||
357 | return htc_send(priv->htc, skb); | 384 | return htc_send(priv->htc, skb); |
358 | } | 385 | } |
359 | 386 | ||