diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/txrx.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/txrx.c | 72 |
1 files changed, 53 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index a3dc6943c7f7..f85353fd1792 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2004-2011 Atheros Communications Inc. + * Copyright (c) 2011-2012 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -158,8 +159,8 @@ static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn, */ if (is_apsdq_empty) { ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, - vif->fw_vif_idx, - conn->aid, 1, 0); + vif->fw_vif_idx, + conn->aid, 1, 0); } *flags |= WMI_DATA_HDR_FLAGS_UAPSD; @@ -284,6 +285,9 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb, int status = 0; struct ath6kl_cookie *cookie = NULL; + if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) + return -EACCES; + spin_lock_bh(&ar->lock); ath6kl_dbg(ATH6KL_DBG_WLAN_TX, @@ -359,6 +363,11 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) return 0; } + if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) { + dev_kfree_skb(skb); + return 0; + } + if (!test_bit(WMI_READY, &ar->flag)) goto fail_tx; @@ -370,7 +379,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) if (test_bit(WMI_ENABLED, &ar->flag)) { if ((dev->features & NETIF_F_IP_CSUM) && - (csum == CHECKSUM_PARTIAL)) { + (csum == CHECKSUM_PARTIAL)) { csum_start = skb->csum_start - (skb_network_header(skb) - skb->head) + sizeof(struct ath6kl_llc_snap_hdr); @@ -394,7 +403,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) } if ((dev->features & NETIF_F_IP_CSUM) && - (csum == CHECKSUM_PARTIAL)) { + (csum == CHECKSUM_PARTIAL)) { meta_v2.csum_start = csum_start; meta_v2.csum_dest = csum_dest; @@ -419,7 +428,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) } if ((vif->nw_type == ADHOC_NETWORK) && - ar->ibss_ps_enable && test_bit(CONNECTED, &vif->flags)) + ar->ibss_ps_enable && test_bit(CONNECTED, &vif->flags)) chk_adhoc_ps_mapping = true; else { /* get the stream mapping */ @@ -593,7 +602,8 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, */ if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] < ar->hiac_stream_active_pri && - ar->cookie_count <= MAX_HI_COOKIE_NUM) + ar->cookie_count <= + target->endpoint[endpoint].tx_drop_packet_threshold) /* * Give preference to the highest priority stream by * dropping the packets which overflowed. @@ -876,7 +886,7 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint) if (!IS_ALIGNED((unsigned long) skb->data, 4)) skb->data = PTR_ALIGN(skb->data - 4, 4); set_htc_rxpkt_info(packet, skb, skb->data, - ATH6KL_BUFFER_SIZE, endpoint); + ATH6KL_BUFFER_SIZE, endpoint); list_add_tail(&packet->list, &queue); } @@ -1256,8 +1266,8 @@ static void ath6kl_uapsd_trigger_frame_rx(struct ath6kl_vif *vif, flags = 0; ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, - vif->fw_vif_idx, - conn->aid, 0, flags); + vif->fw_vif_idx, + conn->aid, 0, flags); } return; @@ -1296,7 +1306,15 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) skb_put(skb, packet->act_len + HTC_HDR_LENGTH); skb_pull(skb, HTC_HDR_LENGTH); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ", + skb->data, skb->len); + if (ept == ar->ctrl_ep) { + if (test_bit(WMI_ENABLED, &ar->flag)) { + ath6kl_check_wow_status(ar); + ath6kl_wmi_control_rx(ar->wmi, skb); + return; + } if_idx = wmi_cmd_hdr_get_if_idx((struct wmi_cmd_hdr *) skb->data); } else { @@ -1321,10 +1339,6 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) spin_unlock_bh(&vif->if_lock); - - ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ", - skb->data, skb->len); - skb->dev = vif->ndev; if (!test_bit(WMI_ENABLED, &ar->flag)) { @@ -1336,11 +1350,6 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ath6kl_check_wow_status(ar); - if (ept == ar->ctrl_ep) { - ath6kl_wmi_control_rx(ar->wmi, skb); - return; - } - min_hdr_len = sizeof(struct ethhdr) + sizeof(struct wmi_data_hdr) + sizeof(struct ath6kl_llc_snap_hdr); @@ -1416,8 +1425,33 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) if (!(conn->sta_flags & STA_PS_SLEEP)) { struct sk_buff *skbuff = NULL; bool is_apsdq_empty; + struct ath6kl_mgmt_buff *mgmt; + u8 idx; spin_lock_bh(&conn->psq_lock); + while (conn->mgmt_psq_len > 0) { + mgmt = list_first_entry( + &conn->mgmt_psq, + struct ath6kl_mgmt_buff, + list); + list_del(&mgmt->list); + conn->mgmt_psq_len--; + spin_unlock_bh(&conn->psq_lock); + idx = vif->fw_vif_idx; + + ath6kl_wmi_send_mgmt_cmd(ar->wmi, + idx, + mgmt->id, + mgmt->freq, + mgmt->wait, + mgmt->buf, + mgmt->len, + mgmt->no_cck); + + kfree(mgmt); + spin_lock_bh(&conn->psq_lock); + } + conn->mgmt_psq_len = 0; while ((skbuff = skb_dequeue(&conn->psq))) { spin_unlock_bh(&conn->psq_lock); ath6kl_data_tx(skbuff, vif->ndev); @@ -1541,7 +1575,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) aggr_conn = vif->aggr_cntxt->aggr_conn; if (aggr_process_recv_frm(aggr_conn, tid, seq_no, - is_amsdu, skb)) { + is_amsdu, skb)) { /* aggregation code will handle the skb */ return; } |