diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_hst.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_hst.c | 101 |
1 files changed, 68 insertions, 33 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index c41ab8c3016..a0ff5b63705 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications 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 @@ -14,11 +14,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "htc.h" static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, - u16 len, u8 flags, u8 epid, - struct ath9k_htc_tx_ctl *tx_ctl) + u16 len, u8 flags, u8 epid) + { struct htc_frame_hdr *hdr; struct htc_endpoint *endpoint = &target->endpoint[epid]; @@ -30,8 +32,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, hdr->flags = flags; hdr->payload_len = cpu_to_be16(len); - status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, - tx_ctl); + status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb); + return status; } @@ -162,7 +164,7 @@ static int htc_config_pipe_credits(struct htc_target *target) target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); if (ret) goto err; @@ -197,7 +199,7 @@ static int htc_setup_complete(struct htc_target *target) target->htc_flags |= HTC_OP_START_WAIT; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); if (ret) goto err; @@ -268,7 +270,7 @@ int htc_connect_service(struct htc_target *target, conn_msg->dl_pipeid = endpoint->dl_pipeid; conn_msg->ul_pipeid = endpoint->ul_pipeid; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); if (ret) goto err; @@ -286,35 +288,33 @@ err: return ret; } -int htc_send(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) +int htc_send(struct htc_target *target, struct sk_buff *skb) { - return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); + struct ath9k_htc_tx_ctl *tx_ctl; + + tx_ctl = HTC_SKB_CB(skb); + return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid); } -void htc_stop(struct htc_target *target) +int htc_send_epid(struct htc_target *target, struct sk_buff *skb, + enum htc_endpoint_id epid) { - enum htc_endpoint_id epid; - struct htc_endpoint *endpoint; + return htc_issue_send(target, skb, skb->len, 0, epid); +} - for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { - endpoint = &target->endpoint[epid]; - if (endpoint->service_id != 0) - target->hif->stop(target->hif_dev, endpoint->ul_pipeid); - } +void htc_stop(struct htc_target *target) +{ + target->hif->stop(target->hif_dev); } void htc_start(struct htc_target *target) { - enum htc_endpoint_id epid; - struct htc_endpoint *endpoint; + target->hif->start(target->hif_dev); +} - for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { - endpoint = &target->endpoint[epid]; - if (endpoint->service_id != 0) - target->hif->start(target->hif_dev, - endpoint->ul_pipeid); - } +void htc_sta_drain(struct htc_target *target, u8 idx) +{ + target->hif->sta_drain(target->hif_dev, idx); } void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, @@ -344,6 +344,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, skb, htc_hdr->endpoint_id, txok); + } else { + kfree_skb(skb); } } @@ -356,11 +358,41 @@ ret: kfree_skb(skb); } +static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle, + struct sk_buff *skb) +{ + uint32_t *pattern = (uint32_t *)skb->data; + + switch (*pattern) { + case 0x33221199: + { + struct htc_panic_bad_vaddr *htc_panic; + htc_panic = (struct htc_panic_bad_vaddr *) skb->data; + dev_err(htc_handle->dev, "ath: firmware panic! " + "exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n", + htc_panic->exccause, htc_panic->pc, + htc_panic->badvaddr); + break; + } + case 0x33221299: + { + struct htc_panic_bad_epid *htc_panic; + htc_panic = (struct htc_panic_bad_epid *) skb->data; + dev_err(htc_handle->dev, "ath: firmware panic! " + "bad epid: 0x%08x\n", htc_panic->epid); + break; + } + default: + dev_err(htc_handle->dev, "ath: uknown panic pattern!\n"); + break; + } +} + /* * HTC Messages are handled directly here and the obtained SKB * is freed. * - * Sevice messages (Data, WMI) passed to the corresponding + * Service messages (Data, WMI) passed to the corresponding * endpoint RX handlers, which have to free the SKB. */ void ath9k_htc_rx_msg(struct htc_target *htc_handle, @@ -377,6 +409,12 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, htc_hdr = (struct htc_frame_hdr *) skb->data; epid = htc_hdr->endpoint_id; + if (epid == 0x99) { + ath9k_htc_fw_panic_report(htc_handle, skb); + kfree_skb(skb); + return; + } + if (epid >= ENDPOINT_MAX) { if (pipe_id != USB_REG_IN_PIPE) dev_kfree_skb_any(skb); @@ -433,11 +471,8 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, struct htc_target *target; target = kzalloc(sizeof(struct htc_target), GFP_KERNEL); - if (!target) { - printk(KERN_ERR "Unable to allocate memory for" - "target device\n"); + if (!target) return NULL; - } init_completion(&target->target_wait); init_completion(&target->cmd_wait); @@ -466,7 +501,7 @@ int ath9k_htc_hw_init(struct htc_target *target, char *product, u32 drv_info) { if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) { - printk(KERN_ERR "Failed to initialize the device\n"); + pr_err("Failed to initialize the device\n"); return -ENODEV; } |
