X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fbrcm80211%2Fbrcmfmac%2Fusb.c;h=4572defc280fa42e7100115540a32581912bf2e2;hb=1459143386c5d868c87903b8d433a52cffcf3e66;hp=d06fcb05adf2517a292ab727467e69d0abf28259;hpb=6c8ff877cdf13cd5287ed9d700cfb6cb70e2bfa1;p=cascardo%2Flinux.git diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index d06fcb05adf2..4572defc280f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -21,40 +21,97 @@ #include #include +#include #include -#include -#include - +#include "bus.h" +#include "debug.h" #include "firmware.h" -#include "usb_rdl.h" #include "usb.h" -#define IOCTL_RESP_TIMEOUT 2000 + +#define IOCTL_RESP_TIMEOUT 2000 #define BRCMF_USB_RESET_GETVER_SPINWAIT 100 /* in unit of ms */ #define BRCMF_USB_RESET_GETVER_LOOP_CNT 10 #define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle has boot up */ -#define BRCMF_USB_NRXQ 50 -#define BRCMF_USB_NTXQ 50 +#define BRCMF_USB_NRXQ 50 +#define BRCMF_USB_NTXQ 50 + +#define BRCMF_USB_CBCTL_WRITE 0 +#define BRCMF_USB_CBCTL_READ 1 +#define BRCMF_USB_MAX_PKT_SIZE 1600 + +#define BRCMF_USB_43143_FW_NAME "brcm/brcmfmac43143.bin" +#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin" +#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin" +#define BRCMF_USB_43569_FW_NAME "brcm/brcmfmac43569.bin" + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +#define TRX_MAX_OFFSET 3 /* Max number of file offsets */ +#define TRX_UNCOMP_IMAGE 0x20 /* Trx holds uncompressed img */ +#define TRX_RDL_CHUNK 1500 /* size of each dl transfer */ +#define TRX_OFFSETS_DLFWLEN_IDX 0 + +/* Control messages: bRequest values */ +#define DL_GETSTATE 0 /* returns the rdl_state_t struct */ +#define DL_CHECK_CRC 1 /* currently unused */ +#define DL_GO 2 /* execute downloaded image */ +#define DL_START 3 /* initialize dl state */ +#define DL_REBOOT 4 /* reboot the device in 2 seconds */ +#define DL_GETVER 5 /* returns the bootrom_id_t struct */ +#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset + * event to occur in 2 seconds. It is the + * responsibility of the downloaded code to + * clear this event + */ +#define DL_EXEC 7 /* jump to a supplied address */ +#define DL_RESETCFG 8 /* To support single enum on dongle + * - Not used by bootloader + */ +#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup + * if resp unavailable + */ + +/* states */ +#define DL_WAITING 0 /* waiting to rx first pkt */ +#define DL_READY 1 /* hdr was good, waiting for more of the + * compressed image + */ +#define DL_BAD_HDR 2 /* hdr was corrupted */ +#define DL_BAD_CRC 3 /* compressed image was corrupted */ +#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ +#define DL_START_FAIL 5 /* failed to initialize correctly */ +#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM + * value + */ +#define DL_IMAGE_TOOBIG 7 /* firmware image too big */ -#define CONFIGDESC(usb) (&((usb)->actconfig)->desc) -#define IFPTR(usb, idx) ((usb)->actconfig->interface[(idx)]) -#define IFALTS(usb, idx) (IFPTR((usb), (idx))->altsetting[0]) -#define IFDESC(usb, idx) IFALTS((usb), (idx)).desc -#define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[(ep)]).desc -#define CONTROL_IF 0 -#define BULK_IF 0 +struct trx_header_le { + __le32 magic; /* "HDR0" */ + __le32 len; /* Length of file including header */ + __le32 crc32; /* CRC from flag_version to end of file */ + __le32 flag_version; /* 0:15 flags, 16:31 version */ + __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of + * header + */ +}; -#define BRCMF_USB_CBCTL_WRITE 0 -#define BRCMF_USB_CBCTL_READ 1 -#define BRCMF_USB_MAX_PKT_SIZE 1600 +struct rdl_state_le { + __le32 state; + __le32 bytes; +}; -#define BRCMF_USB_43143_FW_NAME "brcm/brcmfmac43143.bin" -#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin" -#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin" +struct bootrom_id_le { + __le32 chip; /* Chip id */ + __le32 chiprev; /* Chip rev */ + __le32 ramsize; /* Size of RAM */ + __le32 remapbase; /* Current remap base address */ + __le32 boardtype; /* Type of board */ + __le32 boardrev; /* Board revision */ +}; struct brcmf_usb_image { struct list_head list; @@ -70,7 +127,7 @@ struct brcmf_usbdev_info { struct list_head rx_postq; struct list_head tx_freeq; struct list_head tx_postq; - uint rx_pipe, tx_pipe, rx_pipe2; + uint rx_pipe, tx_pipe; int rx_low_watermark; int tx_low_watermark; @@ -97,8 +154,11 @@ struct brcmf_usbdev_info { int ctl_completed; wait_queue_head_t ioctl_resp_wait; ulong ctl_op; + u8 ifnum; struct urb *bulk_urb; /* used for FW download */ + + bool wowl_enabled; }; static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, @@ -576,7 +636,6 @@ fail: static int brcmf_usb_up(struct device *dev) { struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); - u16 ifnum; brcmf_dbg(USB, "Enter\n"); if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) @@ -589,26 +648,34 @@ static int brcmf_usb_up(struct device *dev) devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0); devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0); - ifnum = IFDESC(devinfo->usbdev, CONTROL_IF).bInterfaceNumber; - /* CTL Write */ devinfo->ctl_write.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; devinfo->ctl_write.bRequest = 0; devinfo->ctl_write.wValue = cpu_to_le16(0); - devinfo->ctl_write.wIndex = cpu_to_le16p(&ifnum); + devinfo->ctl_write.wIndex = cpu_to_le16(devinfo->ifnum); /* CTL Read */ devinfo->ctl_read.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; devinfo->ctl_read.bRequest = 1; devinfo->ctl_read.wValue = cpu_to_le16(0); - devinfo->ctl_read.wIndex = cpu_to_le16p(&ifnum); + devinfo->ctl_read.wIndex = cpu_to_le16(devinfo->ifnum); } brcmf_usb_rx_fill_all(devinfo); return 0; } +static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo) +{ + if (devinfo->ctl_urb) + usb_kill_urb(devinfo->ctl_urb); + if (devinfo->bulk_urb) + usb_kill_urb(devinfo->bulk_urb); + brcmf_usb_free_q(&devinfo->tx_postq, true); + brcmf_usb_free_q(&devinfo->rx_postq, true); +} + static void brcmf_usb_down(struct device *dev) { struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); @@ -622,14 +689,7 @@ static void brcmf_usb_down(struct device *dev) brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN); - if (devinfo->ctl_urb) - usb_kill_urb(devinfo->ctl_urb); - - if (devinfo->bulk_urb) - usb_kill_urb(devinfo->bulk_urb); - brcmf_usb_free_q(&devinfo->tx_postq, true); - - brcmf_usb_free_q(&devinfo->rx_postq, true); + brcmf_cancel_all_urbs(devinfo); } static void @@ -642,19 +702,19 @@ brcmf_usb_sync_complete(struct urb *urb) brcmf_usb_ioctl_resp_wake(devinfo); } -static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, - void *buffer, int buflen) +static int brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, + void *buffer, int buflen) { - int ret = 0; + int ret; char *tmpbuf; u16 size; if ((!devinfo) || (devinfo->ctl_urb == NULL)) - return false; + return -EINVAL; tmpbuf = kmalloc(buflen, GFP_ATOMIC); if (!tmpbuf) - return false; + return -ENOMEM; size = buflen; devinfo->ctl_urb->transfer_buffer_length = size; @@ -675,14 +735,18 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); if (ret < 0) { brcmf_err("usb_submit_urb failed %d\n", ret); - kfree(tmpbuf); - return false; + goto finalize; } - ret = brcmf_usb_ioctl_resp_wait(devinfo); - memcpy(buffer, tmpbuf, buflen); - kfree(tmpbuf); + if (!brcmf_usb_ioctl_resp_wait(devinfo)) { + usb_kill_urb(devinfo->ctl_urb); + ret = -ETIMEDOUT; + } else { + memcpy(buffer, tmpbuf, buflen); + } +finalize: + kfree(tmpbuf); return ret; } @@ -724,6 +788,7 @@ brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo) { struct bootrom_id_le id; u32 loop_cnt; + int err; brcmf_dbg(USB, "Enter\n"); @@ -732,7 +797,9 @@ brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo) mdelay(BRCMF_USB_RESET_GETVER_SPINWAIT); loop_cnt++; id.chip = cpu_to_le32(0xDEAD); /* Get the ID */ - brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id)); + err = brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id)); + if ((err) && (err != -ETIMEDOUT)) + return err; if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) break; } while (loop_cnt < BRCMF_USB_RESET_GETVER_LOOP_CNT); @@ -787,15 +854,14 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen); - bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC); + bulkchunk = kmalloc(TRX_RDL_CHUNK, GFP_ATOMIC); if (bulkchunk == NULL) { err = -ENOMEM; goto fail; } /* 1) Prepare USB boot loader for runtime image */ - brcmf_usb_dl_cmd(devinfo, DL_START, &state, - sizeof(struct rdl_state_le)); + brcmf_usb_dl_cmd(devinfo, DL_START, &state, sizeof(state)); rdlstate = le32_to_cpu(state.state); rdlbytes = le32_to_cpu(state.bytes); @@ -815,10 +881,10 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) /* Wait until the usb device reports it received all * the bytes we sent */ if ((rdlbytes == sent) && (rdlbytes != dllen)) { - if ((dllen-sent) < RDL_CHUNK) + if ((dllen-sent) < TRX_RDL_CHUNK) sendlen = dllen-sent; else - sendlen = RDL_CHUNK; + sendlen = TRX_RDL_CHUNK; /* simply avoid having to send a ZLP by ensuring we * never have an even @@ -839,10 +905,10 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) dlpos += sendlen; sent += sendlen; } - if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, - sizeof(struct rdl_state_le))) { - brcmf_err("DL_GETSTATE Failed xxxx\n"); - err = -EINVAL; + err = brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, + sizeof(state)); + if (err) { + brcmf_err("DL_GETSTATE Failed\n"); goto fail; } @@ -898,13 +964,12 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo) return -EINVAL; /* Check we are runnable */ - brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, - sizeof(struct rdl_state_le)); + state.state = 0; + brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, sizeof(state)); /* Start the image */ if (state.state == cpu_to_le32(DL_RUNNABLE)) { - if (!brcmf_usb_dl_cmd(devinfo, DL_GO, &state, - sizeof(struct rdl_state_le))) + if (brcmf_usb_dl_cmd(devinfo, DL_GO, &state, sizeof(state))) return -ENODEV; if (brcmf_usb_resetcfg(devinfo)) return -ENODEV; @@ -920,13 +985,16 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo) static bool brcmf_usb_chip_support(int chipid, int chiprev) { switch(chipid) { - case 43143: + case BRCM_CC_43143_CHIP_ID: return true; - case 43235: - case 43236: - case 43238: + case BRCM_CC_43235_CHIP_ID: + case BRCM_CC_43236_CHIP_ID: + case BRCM_CC_43238_CHIP_ID: return (chiprev == 3); - case 43242: + case BRCM_CC_43242_CHIP_ID: + return true; + case BRCM_CC_43566_CHIP_ID: + case BRCM_CC_43569_CHIP_ID: return true; default: break; @@ -981,21 +1049,6 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) kfree(devinfo->rx_reqs); } -#define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 /* Version 1 */ -#define TRX_MAX_LEN 0x3B0000 /* Max length */ -#define TRX_NO_HEADER 1 /* Do not write TRX header */ -#define TRX_MAX_OFFSET 3 /* Max number of individual files */ -#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed image */ - -struct trx_header_le { - __le32 magic; /* "HDR0" */ - __le32 len; /* Length of file including header */ - __le32 crc32; /* CRC from flag_version to end of file */ - __le32 flag_version; /* 0:15 flags, 16:31 version */ - __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of - * header */ -}; static int check_file(const u8 *headers) { @@ -1020,14 +1073,17 @@ static int check_file(const u8 *headers) static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo) { switch (devinfo->bus_pub.devid) { - case 43143: + case BRCM_CC_43143_CHIP_ID: return BRCMF_USB_43143_FW_NAME; - case 43235: - case 43236: - case 43238: + case BRCM_CC_43235_CHIP_ID: + case BRCM_CC_43236_CHIP_ID: + case BRCM_CC_43238_CHIP_ID: return BRCMF_USB_43236_FW_NAME; - case 43242: + case BRCM_CC_43242_CHIP_ID: return BRCMF_USB_43242_FW_NAME; + case BRCM_CC_43566_CHIP_ID: + case BRCM_CC_43569_CHIP_ID: + return BRCMF_USB_43569_FW_NAME; default: return NULL; } @@ -1094,11 +1150,24 @@ error: return NULL; } +static void brcmf_usb_wowl_config(struct device *dev, bool enabled) +{ + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + + brcmf_dbg(USB, "Configuring WOWL, enabled=%d\n", enabled); + devinfo->wowl_enabled = enabled; + if (enabled) + device_set_wakeup_enable(devinfo->dev, true); + else + device_set_wakeup_enable(devinfo->dev, false); +} + static struct brcmf_bus_ops brcmf_usb_bus_ops = { .txdata = brcmf_usb_tx, .stop = brcmf_usb_down, .txctl = brcmf_usb_tx_ctlpkt, .rxctl = brcmf_usb_rx_ctlpkt, + .wowl_config = brcmf_usb_wowl_config, }; static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) @@ -1186,6 +1255,9 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) bus->ops = &brcmf_usb_bus_ops; bus->proto_type = BRCMF_PROTO_BCDC; bus->always_use_fws_queue = true; +#ifdef CONFIG_PM + bus->wowl_supported = true; +#endif if (!brcmf_usb_dlneeded(devinfo)) { ret = brcmf_usb_bus_setup(devinfo); @@ -1222,15 +1294,15 @@ brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo) static int brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - int ep; - struct usb_endpoint_descriptor *endpoint; - int ret = 0; struct usb_device *usb = interface_to_usbdev(intf); - int num_of_eps; - u8 endpoint_num; struct brcmf_usbdev_info *devinfo; + struct usb_interface_descriptor *desc; + struct usb_endpoint_descriptor *endpoint; + int ret = 0; + u32 num_of_eps; + u8 endpoint_num, ep; - brcmf_dbg(USB, "Enter\n"); + brcmf_dbg(USB, "Enter 0x%04x:0x%04x\n", id->idVendor, id->idProduct); devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC); if (devinfo == NULL) @@ -1238,92 +1310,71 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->usbdev = usb; devinfo->dev = &usb->dev; - usb_set_intfdata(intf, devinfo); /* Check that the device supports only one configuration */ if (usb->descriptor.bNumConfigurations != 1) { - ret = -1; + brcmf_err("Number of configurations: %d not supported\n", + usb->descriptor.bNumConfigurations); + ret = -ENODEV; goto fail; } - if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { - ret = -1; + if ((usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) && + (usb->descriptor.bDeviceClass != USB_CLASS_MISC) && + (usb->descriptor.bDeviceClass != USB_CLASS_WIRELESS_CONTROLLER)) { + brcmf_err("Device class: 0x%x not supported\n", + usb->descriptor.bDeviceClass); + ret = -ENODEV; goto fail; } - /* - * Only the BDC interface configuration is supported: - * Device class: USB_CLASS_VENDOR_SPEC - * if0 class: USB_CLASS_VENDOR_SPEC - * if0/ep0: control - * if0/ep1: bulk in - * if0/ep2: bulk out (ok if swapped with bulk in) - */ - if (CONFIGDESC(usb)->bNumInterfaces != 1) { - ret = -1; + desc = &intf->altsetting[0].desc; + if ((desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || + (desc->bInterfaceSubClass != 2) || + (desc->bInterfaceProtocol != 0xff)) { + brcmf_err("non WLAN interface %d: 0x%x:0x%x:0x%x\n", + desc->bInterfaceNumber, desc->bInterfaceClass, + desc->bInterfaceSubClass, desc->bInterfaceProtocol); + ret = -ENODEV; goto fail; } - /* Check interface */ - if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC || - IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 || - IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) { - brcmf_err("invalid control interface: class %d, subclass %d, proto %d\n", - IFDESC(usb, CONTROL_IF).bInterfaceClass, - IFDESC(usb, CONTROL_IF).bInterfaceSubClass, - IFDESC(usb, CONTROL_IF).bInterfaceProtocol); - ret = -1; - goto fail; - } - - /* Check control endpoint */ - endpoint = &IFEPDESC(usb, CONTROL_IF, 0); - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_INT) { - brcmf_err("invalid control endpoint %d\n", - endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); - ret = -1; - goto fail; - } - - devinfo->rx_pipe = 0; - devinfo->rx_pipe2 = 0; - devinfo->tx_pipe = 0; - num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1; - - /* Check data endpoints and get pipes */ - for (ep = 1; ep <= num_of_eps; ep++) { - endpoint = &IFEPDESC(usb, BULK_IF, ep); - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != - USB_ENDPOINT_XFER_BULK) { - brcmf_err("invalid data endpoint %d\n", ep); - ret = -1; - goto fail; - } - - endpoint_num = endpoint->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) { - if (!devinfo->rx_pipe) { + num_of_eps = desc->bNumEndpoints; + for (ep = 0; ep < num_of_eps; ep++) { + endpoint = &intf->altsetting[0].endpoint[ep].desc; + endpoint_num = usb_endpoint_num(endpoint); + if (!usb_endpoint_xfer_bulk(endpoint)) + continue; + if (usb_endpoint_dir_in(endpoint)) { + if (!devinfo->rx_pipe) devinfo->rx_pipe = usb_rcvbulkpipe(usb, endpoint_num); - } else { - devinfo->rx_pipe2 = - usb_rcvbulkpipe(usb, endpoint_num); - } } else { - devinfo->tx_pipe = usb_sndbulkpipe(usb, endpoint_num); + if (!devinfo->tx_pipe) + devinfo->tx_pipe = + usb_sndbulkpipe(usb, endpoint_num); } } + if (devinfo->rx_pipe == 0) { + brcmf_err("No RX (in) Bulk EP found\n"); + ret = -ENODEV; + goto fail; + } + if (devinfo->tx_pipe == 0) { + brcmf_err("No TX (out) Bulk EP found\n"); + ret = -ENODEV; + goto fail; + } + + devinfo->ifnum = desc->bInterfaceNumber; if (usb->speed == USB_SPEED_SUPER) - brcmf_dbg(USB, "Broadcom super speed USB wireless device detected\n"); + brcmf_dbg(USB, "Broadcom super speed USB WLAN interface detected\n"); else if (usb->speed == USB_SPEED_HIGH) - brcmf_dbg(USB, "Broadcom high speed USB wireless device detected\n"); + brcmf_dbg(USB, "Broadcom high speed USB WLAN interface detected\n"); else - brcmf_dbg(USB, "Broadcom full speed USB wireless device detected\n"); + brcmf_dbg(USB, "Broadcom full speed USB WLAN interface detected\n"); ret = brcmf_usb_probe_cb(devinfo); if (ret) @@ -1333,11 +1384,9 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) return 0; fail: - brcmf_err("failed with errno %d\n", ret); kfree(devinfo); usb_set_intfdata(intf, NULL); return ret; - } static void @@ -1362,7 +1411,10 @@ static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state) brcmf_dbg(USB, "Enter\n"); devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP; - brcmf_detach(&usb->dev); + if (devinfo->wowl_enabled) + brcmf_cancel_all_urbs(devinfo); + else + brcmf_detach(&usb->dev); return 0; } @@ -1375,13 +1427,19 @@ static int brcmf_usb_resume(struct usb_interface *intf) struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); brcmf_dbg(USB, "Enter\n"); - return brcmf_usb_bus_setup(devinfo); + if (!devinfo->wowl_enabled) + return brcmf_usb_bus_setup(devinfo); + + devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP; + brcmf_usb_rx_fill_all(devinfo); + return 0; } static int brcmf_usb_reset_resume(struct usb_interface *intf) { struct usb_device *usb = interface_to_usbdev(intf); struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); + brcmf_dbg(USB, "Enter\n"); return brcmf_fw_get_firmwares(&usb->dev, 0, @@ -1389,25 +1447,24 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf) brcmf_usb_probe_phase2); } -#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c -#define BRCMF_USB_DEVICE_ID_43143 0xbd1e -#define BRCMF_USB_DEVICE_ID_43236 0xbd17 -#define BRCMF_USB_DEVICE_ID_43242 0xbd1f -#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc +#define BRCMF_USB_DEVICE(dev_id) \ + { USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) } static struct usb_device_id brcmf_usb_devid_table[] = { - { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) }, - { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) }, - { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) }, + BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID), + BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID), + BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID), + BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID), /* special entry for device with firmware loaded and running */ - { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, - { } + BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID), + { /* end: all zeroes */ } }; MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME); MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME); MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME); +MODULE_FIRMWARE(BRCMF_USB_43569_FW_NAME); static struct usb_driver brcmf_usbdrvr = { .name = KBUILD_MODNAME,