aboutsummaryrefslogtreecommitdiff
path: root/drivers/uwb/hwa-rc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/uwb/hwa-rc.c')
-rw-r--r--drivers/uwb/hwa-rc.c92
1 files changed, 54 insertions, 38 deletions
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c
index 3d26fa0f8ae..0257f35cfb9 100644
--- a/drivers/uwb/hwa-rc.c
+++ b/drivers/uwb/hwa-rc.c
@@ -51,16 +51,15 @@
*
*
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/wusb.h>
#include <linux/usb/wusb-wa.h>
#include <linux/uwb.h>
+
#include "uwb-internal.h"
-#define D_LOCAL 1
-#include <linux/uwb/debug.h>
/* The device uses commands and events from the WHCI specification, although
* reporting itself as WUSB compliant. */
@@ -503,7 +502,7 @@ int hwarc_filter_event_WUSB_0100(struct uwb_rc *rc, struct uwb_rceb **header,
int result = -ENOANO;
struct uwb_rceb *rceb = *header;
int event = le16_to_cpu(rceb->wEvent);
- size_t event_size;
+ ssize_t event_size;
size_t core_size, offset;
if (rceb->bEventType != UWB_RC_CET_GENERAL)
@@ -612,7 +611,16 @@ static
int hwarc_reset(struct uwb_rc *uwb_rc)
{
struct hwarc *hwarc = uwb_rc->priv;
- return usb_reset_device(hwarc->usb_dev);
+ int result;
+
+ /* device lock must be held when calling usb_reset_device. */
+ result = usb_lock_device_for_reset(hwarc->usb_dev, NULL);
+ if (result >= 0) {
+ result = usb_reset_device(hwarc->usb_dev);
+ usb_unlock_device(hwarc->usb_dev);
+ }
+
+ return result;
}
/**
@@ -631,17 +639,13 @@ void hwarc_neep_cb(struct urb *urb)
switch (result = urb->status) {
case 0:
- d_printf(3, dev, "NEEP: receive stat %d, %zu bytes\n",
- urb->status, (size_t)urb->actual_length);
uwb_rc_neh_grok(hwarc->uwb_rc, urb->transfer_buffer,
urb->actual_length);
break;
case -ECONNRESET: /* Not an error, but a controlled situation; */
case -ENOENT: /* (we killed the URB)...so, no broadcast */
- d_printf(2, dev, "NEEP: URB reset/noent %d\n", urb->status);
goto out;
case -ESHUTDOWN: /* going away! */
- d_printf(2, dev, "NEEP: URB down %d\n", urb->status);
goto out;
default: /* On general errors, retry unless it gets ugly */
if (edc_inc(&hwarc->neep_edc, EDC_MAX_ERRORS,
@@ -650,8 +654,8 @@ void hwarc_neep_cb(struct urb *urb)
dev_err(dev, "NEEP: URB error %d\n", urb->status);
}
result = usb_submit_urb(urb, GFP_ATOMIC);
- d_printf(3, dev, "NEEP: submit %d\n", result);
- if (result < 0) {
+ if (result < 0 && result != -ENODEV && result != -EPERM) {
+ /* ignoring unrecoverable errors */
dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n",
result);
goto error;
@@ -714,8 +718,10 @@ static int hwarc_neep_init(struct uwb_rc *rc)
error_neep_submit:
usb_free_urb(hwarc->neep_urb);
+ hwarc->neep_urb = NULL;
error_urb_alloc:
free_page((unsigned long)hwarc->rd_buffer);
+ hwarc->rd_buffer = NULL;
error_rd_buffer:
return -ENOMEM;
}
@@ -728,7 +734,10 @@ static void hwarc_neep_release(struct uwb_rc *rc)
usb_kill_urb(hwarc->neep_urb);
usb_free_urb(hwarc->neep_urb);
+ hwarc->neep_urb = NULL;
+
free_page((unsigned long)hwarc->rd_buffer);
+ hwarc->rd_buffer = NULL;
}
/**
@@ -759,11 +768,11 @@ static int hwarc_get_version(struct uwb_rc *rc)
itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength);
while (itr_size >= sizeof(*hdr)) {
hdr = (struct usb_descriptor_header *) itr;
- d_printf(3, dev, "Extra device descriptor: "
- "type %02x/%u bytes @ %zu (%zu left)\n",
- hdr->bDescriptorType, hdr->bLength,
- (itr - usb_dev->rawdescriptors[actconfig_idx]),
- itr_size);
+ dev_dbg(dev, "Extra device descriptor: "
+ "type %02x/%u bytes @ %zu (%zu left)\n",
+ hdr->bDescriptorType, hdr->bLength,
+ (itr - usb_dev->rawdescriptors[actconfig_idx]),
+ itr_size);
if (hdr->bDescriptorType == USB_DT_CS_RADIO_CONTROL)
goto found;
itr += hdr->bLength;
@@ -795,8 +804,7 @@ found:
goto error;
}
rc->version = version;
- d_printf(3, dev, "Device supports WUSB protocol version 0x%04x \n",
- rc->version);
+ dev_dbg(dev, "Device supports WUSB protocol version 0x%04x \n", rc->version);
result = 0;
error:
return result;
@@ -877,19 +885,41 @@ static void hwarc_disconnect(struct usb_interface *iface)
uwb_rc_rm(uwb_rc);
usb_put_intf(hwarc->usb_iface);
usb_put_dev(hwarc->usb_dev);
- d_printf(1, &hwarc->usb_iface->dev, "freed hwarc %p\n", hwarc);
kfree(hwarc);
uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */
}
+static int hwarc_pre_reset(struct usb_interface *iface)
+{
+ struct hwarc *hwarc = usb_get_intfdata(iface);
+ struct uwb_rc *uwb_rc = hwarc->uwb_rc;
+
+ uwb_rc_pre_reset(uwb_rc);
+ return 0;
+}
+
+static int hwarc_post_reset(struct usb_interface *iface)
+{
+ struct hwarc *hwarc = usb_get_intfdata(iface);
+ struct uwb_rc *uwb_rc = hwarc->uwb_rc;
+
+ return uwb_rc_post_reset(uwb_rc);
+}
+
/** USB device ID's that we handle */
-static struct usb_device_id hwarc_id_table[] = {
+static const struct usb_device_id hwarc_id_table[] = {
/* D-Link DUB-1210 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3d02, 0xe0, 0x01, 0x02),
.driver_info = WUSB_QUIRK_WHCI_CMD_EVT },
/* Intel i1480 (using firmware 1.3PA2-20070828) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x8086, 0x0c3b, 0xe0, 0x01, 0x02),
.driver_info = WUSB_QUIRK_WHCI_CMD_EVT },
+ /* Alereon 5310 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5310, 0xe0, 0x01, 0x02),
+ .driver_info = WUSB_QUIRK_WHCI_CMD_EVT },
+ /* Alereon 5611 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5611, 0xe0, 0x01, 0x02),
+ .driver_info = WUSB_QUIRK_WHCI_CMD_EVT },
/* Generic match for the Radio Control interface */
{ USB_INTERFACE_INFO(0xe0, 0x01, 0x02), },
{ },
@@ -898,28 +928,14 @@ MODULE_DEVICE_TABLE(usb, hwarc_id_table);
static struct usb_driver hwarc_driver = {
.name = "hwa-rc",
+ .id_table = hwarc_id_table,
.probe = hwarc_probe,
.disconnect = hwarc_disconnect,
- .id_table = hwarc_id_table,
+ .pre_reset = hwarc_pre_reset,
+ .post_reset = hwarc_post_reset,
};
-static int __init hwarc_driver_init(void)
-{
- int result;
- result = usb_register(&hwarc_driver);
- if (result < 0)
- printk(KERN_ERR "HWA-RC: Cannot register USB driver: %d\n",
- result);
- return result;
-
-}
-module_init(hwarc_driver_init);
-
-static void __exit hwarc_driver_exit(void)
-{
- usb_deregister(&hwarc_driver);
-}
-module_exit(hwarc_driver_exit);
+module_usb_driver(hwarc_driver);
MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
MODULE_DESCRIPTION("Host Wireless Adapter Radio Control Driver");