diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/htc_pipe.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/htc_pipe.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index ba6bd497b78..756fe52a12c 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c @@ -137,7 +137,6 @@ static void get_htc_packet_credit_based(struct htc_target *target, credits_required = 0; } else { - if (ep->cred_dist.credits < credits_required) break; @@ -169,7 +168,6 @@ static void get_htc_packet_credit_based(struct htc_target *target, /* queue this packet into the caller's queue */ list_add_tail(&packet->list, queue); } - } static void get_htc_packet(struct htc_target *target, @@ -279,7 +277,6 @@ static int htc_issue_packets(struct htc_target *target, list_add(&packet->list, pkt_queue); break; } - } if (status != 0) { @@ -385,7 +382,6 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target, */ list_for_each_entry_safe(packet, tmp_pkt, txq, list) { - ath6kl_dbg(ATH6KL_DBG_HTC, "%s: Indicat overflowed TX pkts: %p\n", __func__, packet); @@ -403,7 +399,6 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target, list_move_tail(&packet->list, &send_queue); } - } if (list_empty(&send_queue)) { @@ -454,7 +449,6 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target, * enough transmit resources. */ while (true) { - if (get_queue_depth(&ep->txq) == 0) break; @@ -495,8 +489,8 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target, } spin_lock_bh(&target->tx_lock); - } + /* done with this endpoint, we can clear the count */ ep->tx_proc_cnt = 0; spin_unlock_bh(&target->tx_lock); @@ -509,9 +503,7 @@ static void destroy_htc_txctrl_packet(struct htc_packet *packet) { struct sk_buff *skb; skb = packet->skb; - if (skb != NULL) - dev_kfree_skb(skb); - + dev_kfree_skb(skb); kfree(packet); } @@ -969,13 +961,27 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, u16 payload_len; int status = 0; + /* + * ar->htc_target can be NULL due to a race condition that can occur + * during driver initialization(we do 'ath6kl_hif_power_on' before + * initializing 'ar->htc_target' via 'ath6kl_htc_create'). + * 'ath6kl_hif_power_on' assigns 'ath6kl_recv_complete' as + * usb_complete_t/callback function for 'usb_fill_bulk_urb'. + * Thus the possibility of ar->htc_target being NULL + * via ath6kl_recv_complete -> ath6kl_usb_io_comp_work. + */ + if (WARN_ON_ONCE(!target)) { + ath6kl_err("Target not yet initialized\n"); + status = -EINVAL; + goto free_skb; + } + + netdata = skb->data; netlen = skb->len; htc_hdr = (struct htc_frame_hdr *) netdata; - ep = &target->endpoint[htc_hdr->eid]; - if (htc_hdr->eid >= ENDPOINT_MAX) { ath6kl_dbg(ATH6KL_DBG_HTC, "HTC Rx: invalid EndpointID=%d\n", @@ -983,6 +989,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, status = -EINVAL; goto free_skb; } + ep = &target->endpoint[htc_hdr->eid]; payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); @@ -1054,6 +1061,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, dev_kfree_skb(skb); skb = NULL; + goto free_skb; } @@ -1089,11 +1097,9 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, skb = NULL; free_skb: - if (skb != NULL) - dev_kfree_skb(skb); + dev_kfree_skb(skb); return status; - } static void htc_flush_rx_queue(struct htc_target *target, @@ -1154,8 +1160,8 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target) } if (count <= 0) { - ath6kl_dbg(ATH6KL_DBG_HTC, "%s: Timeout!\n", __func__); - return -ECOMM; + ath6kl_warn("htc pipe control receive timeout!\n"); + return -ETIMEDOUT; } return 0; @@ -1184,7 +1190,7 @@ static void reset_endpoint_states(struct htc_target *target) INIT_LIST_HEAD(&ep->pipe.tx_lookup_queue); INIT_LIST_HEAD(&ep->rx_bufq); ep->target = target; - ep->pipe.tx_credit_flow_enabled = (bool) 1; /* FIXME */ + ep->pipe.tx_credit_flow_enabled = true; } } @@ -1245,7 +1251,6 @@ static int ath6kl_htc_pipe_conn_service(struct htc_target *target, tx_alloc = 0; } else { - tx_alloc = htc_get_credit_alloc(target, conn_req->svc_id); if (tx_alloc == 0) { status = -ENOMEM; @@ -1568,16 +1573,16 @@ static int ath6kl_htc_pipe_wait_target(struct htc_target *target) return status; if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) { - ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg len:%d!\n", - target->pipe.ctrl_response_len); + ath6kl_warn("invalid htc pipe ready msg len: %d\n", + target->pipe.ctrl_response_len); return -ECOMM; } ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf; if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) { - ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg : 0x%X !\n", - ready_msg->ver2_0_info.msg_id); + ath6kl_warn("invalid htc pipe ready msg: 0x%x\n", + ready_msg->ver2_0_info.msg_id); return -ECOMM; } |
