aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath6kl/htc_pipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/htc_pipe.c')
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_pipe.c65
1 files changed, 34 insertions, 31 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index f9626c72369..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) {
@@ -374,9 +371,8 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
packet = list_first_entry(txq,
struct htc_packet,
list);
- list_del(&packet->list);
- /* insert into local queue */
- list_add_tail(&packet->list, &send_queue);
+ /* move to local queue */
+ list_move_tail(&packet->list, &send_queue);
}
/*
@@ -386,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);
@@ -399,13 +394,11 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
* for cleanup */
} else {
/* callback wants to keep this packet,
- * remove from caller's queue */
- list_del(&packet->list);
- /* put it in the send queue */
- list_add_tail(&packet->list,
- &send_queue);
+ * move from caller's queue to the send
+ * queue */
+ list_move_tail(&packet->list,
+ &send_queue);
}
-
}
if (list_empty(&send_queue)) {
@@ -456,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;
@@ -497,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);
@@ -511,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);
}
@@ -971,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",
@@ -985,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));
@@ -1056,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;
}
@@ -1091,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,
@@ -1156,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;
@@ -1186,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;
}
}
@@ -1247,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;
@@ -1570,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;
}