|
@@ -67,16 +67,6 @@
|
|
|
#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin"
|
|
|
#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
|
|
|
|
|
|
-enum usbdev_suspend_state {
|
|
|
- USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow
|
|
|
- suspend */
|
|
|
- USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be
|
|
|
- * suspended. Wating PM to
|
|
|
- * suspend the device
|
|
|
- */
|
|
|
- USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */
|
|
|
-};
|
|
|
-
|
|
|
struct brcmf_usb_image {
|
|
|
struct list_head list;
|
|
|
s8 *fwname;
|
|
@@ -97,10 +87,8 @@ struct brcmf_usbdev_info {
|
|
|
struct list_head rx_postq;
|
|
|
struct list_head tx_freeq;
|
|
|
struct list_head tx_postq;
|
|
|
- enum usbdev_suspend_state suspend_state;
|
|
|
uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
|
|
|
|
|
|
- bool activity;
|
|
|
int rx_low_watermark;
|
|
|
int tx_low_watermark;
|
|
|
int tx_high_watermark;
|
|
@@ -213,11 +201,6 @@ brcmf_usb_ctlwrite_complete(struct urb *urb)
|
|
|
urb->status);
|
|
|
}
|
|
|
|
|
|
-static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state)
|
|
|
-{
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int
|
|
|
brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
|
|
|
{
|
|
@@ -229,14 +212,6 @@ brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
|
|
|
len == 0 || devinfo->ctl_urb == NULL)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- /* If the USB/HSIC bus in sleep state, wake it up */
|
|
|
- if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED)
|
|
|
- if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
|
|
|
- brcmf_dbg(ERROR, "Could not Resume the bus!\n");
|
|
|
- return -EIO;
|
|
|
- }
|
|
|
-
|
|
|
- devinfo->activity = true;
|
|
|
size = len;
|
|
|
devinfo->ctl_write.wLength = cpu_to_le16p(&size);
|
|
|
devinfo->ctl_urb->transfer_buffer_length = size;
|
|
@@ -299,10 +274,8 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
|
|
|
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
|
|
|
|
|
brcmf_dbg(USB, "Enter\n");
|
|
|
- if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
|
|
|
- /* TODO: handle suspend/resume */
|
|
|
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
|
|
|
return -EIO;
|
|
|
- }
|
|
|
|
|
|
if (test_and_set_bit(0, &devinfo->ctl_op))
|
|
|
return -EIO;
|
|
@@ -330,10 +303,9 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
|
|
|
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
|
|
|
|
|
brcmf_dbg(USB, "Enter\n");
|
|
|
- if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
|
|
|
- /* TODO: handle suspend/resume */
|
|
|
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
|
|
|
return -EIO;
|
|
|
- }
|
|
|
+
|
|
|
if (test_and_set_bit(0, &devinfo->ctl_op))
|
|
|
return -EIO;
|
|
|
|
|
@@ -499,7 +471,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) {
|
|
|
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
|
|
|
skb_put(skb, urb->actual_length);
|
|
|
if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
|
|
|
brcmf_dbg(ERROR, "rx protocol error\n");
|
|
@@ -552,8 +524,8 @@ static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
|
|
|
{
|
|
|
struct brcmf_usbreq *req;
|
|
|
|
|
|
- if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
|
|
|
- brcmf_dbg(ERROR, "bus is not up\n");
|
|
|
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
|
|
|
+ brcmf_dbg(ERROR, "bus is not up=%d\n", devinfo->bus_pub.state);
|
|
|
return;
|
|
|
}
|
|
|
while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq, NULL)) != NULL)
|
|
@@ -573,20 +545,15 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
|
|
|
return;
|
|
|
|
|
|
old_state = devinfo->bus_pub.state;
|
|
|
-
|
|
|
- /* Don't update state if it's PnP firmware re-download */
|
|
|
- if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */
|
|
|
- devinfo->bus_pub.state = state;
|
|
|
-
|
|
|
- if ((old_state == BCMFMAC_USB_STATE_SLEEP)
|
|
|
- && (state == BCMFMAC_USB_STATE_UP)) {
|
|
|
- brcmf_usb_rx_fill_all(devinfo);
|
|
|
- }
|
|
|
+ devinfo->bus_pub.state = state;
|
|
|
|
|
|
/* update state of upper layer */
|
|
|
- if (state == BCMFMAC_USB_STATE_DOWN) {
|
|
|
+ if (state == BRCMFMAC_USB_STATE_DOWN) {
|
|
|
brcmf_dbg(USB, "DBUS is down\n");
|
|
|
bcmf_bus->state = BRCMF_BUS_DOWN;
|
|
|
+ } else if (state == BRCMFMAC_USB_STATE_UP) {
|
|
|
+ brcmf_dbg(USB, "DBUS is up\n");
|
|
|
+ bcmf_bus->state = BRCMF_BUS_DATA;
|
|
|
} else {
|
|
|
brcmf_dbg(USB, "DBUS current state=%d\n", state);
|
|
|
}
|
|
@@ -597,7 +564,7 @@ brcmf_usb_intr_complete(struct urb *urb)
|
|
|
{
|
|
|
struct brcmf_usbdev_info *devinfo =
|
|
|
(struct brcmf_usbdev_info *)urb->context;
|
|
|
- bool killed;
|
|
|
+ int err;
|
|
|
|
|
|
brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
|
|
|
|
|
@@ -605,24 +572,24 @@ brcmf_usb_intr_complete(struct urb *urb)
|
|
|
return;
|
|
|
|
|
|
if (unlikely(urb->status)) {
|
|
|
- if (devinfo->suspend_state ==
|
|
|
- USBOS_SUSPEND_STATE_SUSPEND_PENDING)
|
|
|
- killed = true;
|
|
|
-
|
|
|
- if ((urb->status == -ENOENT && (!killed))
|
|
|
- || urb->status == -ESHUTDOWN ||
|
|
|
- urb->status == -ENODEV) {
|
|
|
- brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
|
|
|
+ if (urb->status == -ENOENT ||
|
|
|
+ urb->status == -ESHUTDOWN ||
|
|
|
+ urb->status == -ENODEV) {
|
|
|
+ brcmf_usb_state_change(devinfo,
|
|
|
+ BRCMFMAC_USB_STATE_DOWN);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) {
|
|
|
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN) {
|
|
|
brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
|
|
|
- usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
|
|
|
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
|
|
|
+ err = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
|
|
|
+ if (err)
|
|
|
+ brcmf_dbg(ERROR, "usb_submit_urb, err=%d\n", err);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
|
|
@@ -632,10 +599,8 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
|
|
|
int ret;
|
|
|
|
|
|
brcmf_dbg(USB, "Enter, skb=%p\n", skb);
|
|
|
- if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
|
|
|
- /* TODO: handle suspend/resume */
|
|
|
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
|
|
|
return -EIO;
|
|
|
- }
|
|
|
|
|
|
req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
|
|
|
&devinfo->tx_freecount);
|
|
@@ -675,26 +640,16 @@ static int brcmf_usb_up(struct device *dev)
|
|
|
{
|
|
|
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
|
|
u16 ifnum;
|
|
|
+ int ret;
|
|
|
|
|
|
brcmf_dbg(USB, "Enter\n");
|
|
|
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
|
|
|
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
|
|
|
return 0;
|
|
|
|
|
|
- /* If the USB/HSIC bus in sleep state, wake it up */
|
|
|
- if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) {
|
|
|
- if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
|
|
|
- brcmf_dbg(ERROR, "Could not Resume the bus!\n");
|
|
|
- return -EIO;
|
|
|
- }
|
|
|
- }
|
|
|
- devinfo->activity = true;
|
|
|
-
|
|
|
/* Success, indicate devinfo is fully up */
|
|
|
- brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP);
|
|
|
+ brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_UP);
|
|
|
|
|
|
if (devinfo->intr_urb) {
|
|
|
- int ret;
|
|
|
-
|
|
|
usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
|
|
|
devinfo->intr_pipe,
|
|
|
&devinfo->intr,
|
|
@@ -743,10 +698,10 @@ static void brcmf_usb_down(struct device *dev)
|
|
|
if (devinfo == NULL)
|
|
|
return;
|
|
|
|
|
|
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN)
|
|
|
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN)
|
|
|
return;
|
|
|
|
|
|
- brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
|
|
|
+ brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
|
|
|
if (devinfo->intr_urb)
|
|
|
usb_kill_urb(devinfo->intr_urb);
|
|
|
|
|
@@ -1006,9 +961,9 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
|
|
|
|
|
|
err = brcmf_usb_dl_writeimage(devinfo, fw, len);
|
|
|
if (err == 0)
|
|
|
- devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE;
|
|
|
+ devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_DONE;
|
|
|
else
|
|
|
- devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING;
|
|
|
+ devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_FAIL;
|
|
|
brcmf_dbg(USB, "Exit, err=%d\n", err);
|
|
|
|
|
|
return err;
|
|
@@ -1221,6 +1176,7 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
|
|
|
devinfo->rx_low_watermark = nrxq / 2;
|
|
|
devinfo->bus_pub.devinfo = devinfo;
|
|
|
devinfo->bus_pub.ntxq = ntxq;
|
|
|
+ devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DOWN;
|
|
|
|
|
|
/* flow control when too many tx urbs posted */
|
|
|
devinfo->tx_low_watermark = ntxq / 4;
|
|
@@ -1491,7 +1447,7 @@ brcmf_usb_disconnect(struct usb_interface *intf)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * only need to signal the bus being down and update the suspend state.
|
|
|
+ * only need to signal the bus being down and update the state.
|
|
|
*/
|
|
|
static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
|
|
|
{
|
|
@@ -1499,13 +1455,13 @@ static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
|
|
|
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
|
|
|
|
|
|
brcmf_dbg(USB, "Enter\n");
|
|
|
- devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN;
|
|
|
- devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
|
|
|
+ devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP;
|
|
|
+ brcmf_detach(&usb->dev);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * mark suspend state active and crank up the bus.
|
|
|
+ * (re-) start the bus.
|
|
|
*/
|
|
|
static int brcmf_usb_resume(struct usb_interface *intf)
|
|
|
{
|
|
@@ -1513,11 +1469,25 @@ 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");
|
|
|
- devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
|
|
|
- brcmf_bus_start(&usb->dev);
|
|
|
+ if (!brcmf_attach(0, devinfo->dev))
|
|
|
+ return brcmf_bus_start(&usb->dev);
|
|
|
+
|
|
|
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");
|
|
|
+
|
|
|
+ if (!brcmf_usb_fw_download(devinfo))
|
|
|
+ return brcmf_usb_resume(intf);
|
|
|
+
|
|
|
+ return -EIO;
|
|
|
+}
|
|
|
+
|
|
|
#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
|
|
|
#define BRCMF_USB_DEVICE_ID_43143 0xbd1e
|
|
|
#define BRCMF_USB_DEVICE_ID_43236 0xbd17
|
|
@@ -1537,7 +1507,6 @@ MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
|
|
|
MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
|
|
|
MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
|
|
|
|
|
|
-/* TODO: suspend and resume entries */
|
|
|
static struct usb_driver brcmf_usbdrvr = {
|
|
|
.name = KBUILD_MODNAME,
|
|
|
.probe = brcmf_usb_probe,
|
|
@@ -1545,6 +1514,7 @@ static struct usb_driver brcmf_usbdrvr = {
|
|
|
.id_table = brcmf_usb_devid_table,
|
|
|
.suspend = brcmf_usb_suspend,
|
|
|
.resume = brcmf_usb_resume,
|
|
|
+ .reset_resume = brcmf_usb_reset_resume,
|
|
|
.supports_autosuspend = 1,
|
|
|
.disable_hub_initiated_lpm = 1,
|
|
|
};
|