summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/carl9170/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/usb.c')
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c61
1 files changed, 50 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index e4eb666c6eea..564ca6a61985 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -178,7 +178,7 @@ static void carl9170_usb_tx_data_complete(struct urb *urb)
switch (urb->status) {
/* everything is fine */
case 0:
- carl9170_tx_callback(ar, (void *)urb->context);
+ carl9170_tx_callback(ar, urb->context);
break;
/* disconnect */
@@ -369,7 +369,7 @@ void carl9170_usb_handle_tx_err(struct ar9170 *ar)
struct urb *urb;
while ((urb = usb_get_from_anchor(&ar->tx_err))) {
- struct sk_buff *skb = (void *)urb->context;
+ struct sk_buff *skb = urb->context;
carl9170_tx_drop(ar, skb);
carl9170_tx_callback(ar, skb);
@@ -397,7 +397,7 @@ static void carl9170_usb_tasklet(struct tasklet_struct *t)
static void carl9170_usb_rx_complete(struct urb *urb)
{
- struct ar9170 *ar = (struct ar9170 *)urb->context;
+ struct ar9170 *ar = urb->context;
int err;
if (WARN_ON_ONCE(!ar))
@@ -438,14 +438,21 @@ static void carl9170_usb_rx_complete(struct urb *urb)
if (atomic_read(&ar->rx_anch_urbs) == 0) {
/*
- * The system is too slow to cope with
- * the enormous workload. We have simply
- * run out of active rx urbs and this
- * unfortunately leads to an unpredictable
- * device.
+ * At this point, either the system is too slow to
+ * cope with the enormous workload (so we have simply
+ * run out of active rx urbs and this unfortunately
+ * leads to an unpredictable device), or the device
+ * is not fully functional after an unsuccessful
+ * firmware loading attempts (so it doesn't pass
+ * ieee80211_register_hw() and there is no internal
+ * workqueue at all).
*/
- ieee80211_queue_work(ar->hw, &ar->ping_work);
+ if (ar->registered)
+ ieee80211_queue_work(ar->hw, &ar->ping_work);
+ else
+ pr_warn_once("device %s is not registered\n",
+ dev_name(&ar->udev->dev));
}
} else {
/*
@@ -559,7 +566,7 @@ static int carl9170_usb_flush(struct ar9170 *ar)
int ret, err = 0;
while ((urb = usb_get_from_anchor(&ar->tx_wait))) {
- struct sk_buff *skb = (void *)urb->context;
+ struct sk_buff *skb = urb->context;
carl9170_tx_drop(ar, skb);
carl9170_tx_callback(ar, skb);
usb_free_urb(urb);
@@ -668,7 +675,7 @@ int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd,
memcpy(ar->cmd.data, payload, plen);
spin_lock_bh(&ar->cmd_lock);
- ar->readbuf = (u8 *)out;
+ ar->readbuf = out;
ar->readlen = outlen;
spin_unlock_bh(&ar->cmd_lock);
@@ -1069,6 +1076,38 @@ static int carl9170_usb_probe(struct usb_interface *intf,
ar->usb_ep_cmd_is_bulk = true;
}
+ /* Verify that all expected endpoints are present */
+ if (ar->usb_ep_cmd_is_bulk) {
+ u8 bulk_ep_addr[] = {
+ AR9170_USB_EP_RX | USB_DIR_IN,
+ AR9170_USB_EP_TX | USB_DIR_OUT,
+ AR9170_USB_EP_CMD | USB_DIR_OUT,
+ 0};
+ u8 int_ep_addr[] = {
+ AR9170_USB_EP_IRQ | USB_DIR_IN,
+ 0};
+ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
+ !usb_check_int_endpoints(intf, int_ep_addr))
+ err = -ENODEV;
+ } else {
+ u8 bulk_ep_addr[] = {
+ AR9170_USB_EP_RX | USB_DIR_IN,
+ AR9170_USB_EP_TX | USB_DIR_OUT,
+ 0};
+ u8 int_ep_addr[] = {
+ AR9170_USB_EP_IRQ | USB_DIR_IN,
+ AR9170_USB_EP_CMD | USB_DIR_OUT,
+ 0};
+ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
+ !usb_check_int_endpoints(intf, int_ep_addr))
+ err = -ENODEV;
+ }
+
+ if (err) {
+ carl9170_free(ar);
+ return err;
+ }
+
usb_set_intfdata(intf, ar);
SET_IEEE80211_DEV(ar->hw, &intf->dev);