.. | .. |
---|
| 1 | +// SPDX-License-Identifier: ISC |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2011 Broadcom Corporation |
---|
3 | | - * |
---|
4 | | - * Permission to use, copy, modify, and/or distribute this software for any |
---|
5 | | - * purpose with or without fee is hereby granted, provided that the above |
---|
6 | | - * copyright notice and this permission notice appear in all copies. |
---|
7 | | - * |
---|
8 | | - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
---|
9 | | - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
---|
10 | | - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
---|
11 | | - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
---|
12 | | - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
---|
13 | | - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
---|
14 | | - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
---|
15 | 4 | */ |
---|
16 | 5 | |
---|
17 | 6 | #include <linux/kernel.h> |
---|
.. | .. |
---|
175 | 164 | |
---|
176 | 165 | struct urb *bulk_urb; /* used for FW download */ |
---|
177 | 166 | |
---|
178 | | - bool wowl_enabled; |
---|
179 | 167 | struct brcmf_mp_device *settings; |
---|
180 | 168 | }; |
---|
181 | 169 | |
---|
.. | .. |
---|
323 | 311 | int err = 0; |
---|
324 | 312 | int timeout = 0; |
---|
325 | 313 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); |
---|
| 314 | + struct usb_interface *intf = to_usb_interface(dev); |
---|
326 | 315 | |
---|
327 | 316 | brcmf_dbg(USB, "Enter\n"); |
---|
328 | | - if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) |
---|
329 | | - return -EIO; |
---|
330 | 317 | |
---|
331 | | - if (test_and_set_bit(0, &devinfo->ctl_op)) |
---|
332 | | - return -EIO; |
---|
| 318 | + err = usb_autopm_get_interface(intf); |
---|
| 319 | + if (err) |
---|
| 320 | + goto out; |
---|
| 321 | + |
---|
| 322 | + if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { |
---|
| 323 | + err = -EIO; |
---|
| 324 | + goto fail; |
---|
| 325 | + } |
---|
| 326 | + |
---|
| 327 | + if (test_and_set_bit(0, &devinfo->ctl_op)) { |
---|
| 328 | + err = -EIO; |
---|
| 329 | + goto fail; |
---|
| 330 | + } |
---|
333 | 331 | |
---|
334 | 332 | devinfo->ctl_completed = false; |
---|
335 | 333 | err = brcmf_usb_send_ctl(devinfo, buf, len); |
---|
336 | 334 | if (err) { |
---|
337 | 335 | brcmf_err("fail %d bytes: %d\n", err, len); |
---|
338 | 336 | clear_bit(0, &devinfo->ctl_op); |
---|
339 | | - return err; |
---|
| 337 | + goto fail; |
---|
340 | 338 | } |
---|
341 | 339 | timeout = brcmf_usb_ioctl_resp_wait(devinfo); |
---|
342 | | - clear_bit(0, &devinfo->ctl_op); |
---|
343 | 340 | if (!timeout) { |
---|
344 | 341 | brcmf_err("Txctl wait timed out\n"); |
---|
| 342 | + usb_kill_urb(devinfo->ctl_urb); |
---|
345 | 343 | err = -EIO; |
---|
| 344 | + goto fail; |
---|
346 | 345 | } |
---|
| 346 | + clear_bit(0, &devinfo->ctl_op); |
---|
| 347 | + |
---|
| 348 | +fail: |
---|
| 349 | + usb_autopm_put_interface(intf); |
---|
| 350 | +out: |
---|
347 | 351 | return err; |
---|
348 | 352 | } |
---|
349 | 353 | |
---|
.. | .. |
---|
352 | 356 | int err = 0; |
---|
353 | 357 | int timeout = 0; |
---|
354 | 358 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); |
---|
| 359 | + struct usb_interface *intf = to_usb_interface(dev); |
---|
355 | 360 | |
---|
356 | 361 | brcmf_dbg(USB, "Enter\n"); |
---|
357 | | - if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) |
---|
358 | | - return -EIO; |
---|
359 | 362 | |
---|
360 | | - if (test_and_set_bit(0, &devinfo->ctl_op)) |
---|
361 | | - return -EIO; |
---|
| 363 | + err = usb_autopm_get_interface(intf); |
---|
| 364 | + if (err) |
---|
| 365 | + goto out; |
---|
| 366 | + |
---|
| 367 | + if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { |
---|
| 368 | + err = -EIO; |
---|
| 369 | + goto fail; |
---|
| 370 | + } |
---|
| 371 | + |
---|
| 372 | + if (test_and_set_bit(0, &devinfo->ctl_op)) { |
---|
| 373 | + err = -EIO; |
---|
| 374 | + goto fail; |
---|
| 375 | + } |
---|
362 | 376 | |
---|
363 | 377 | devinfo->ctl_completed = false; |
---|
364 | 378 | err = brcmf_usb_recv_ctl(devinfo, buf, len); |
---|
365 | 379 | if (err) { |
---|
366 | 380 | brcmf_err("fail %d bytes: %d\n", err, len); |
---|
367 | 381 | clear_bit(0, &devinfo->ctl_op); |
---|
368 | | - return err; |
---|
| 382 | + goto fail; |
---|
369 | 383 | } |
---|
370 | 384 | timeout = brcmf_usb_ioctl_resp_wait(devinfo); |
---|
371 | 385 | err = devinfo->ctl_urb_status; |
---|
372 | | - clear_bit(0, &devinfo->ctl_op); |
---|
373 | 386 | if (!timeout) { |
---|
374 | 387 | brcmf_err("rxctl wait timed out\n"); |
---|
| 388 | + usb_kill_urb(devinfo->ctl_urb); |
---|
375 | 389 | err = -EIO; |
---|
| 390 | + goto fail; |
---|
376 | 391 | } |
---|
| 392 | + clear_bit(0, &devinfo->ctl_op); |
---|
| 393 | +fail: |
---|
| 394 | + usb_autopm_put_interface(intf); |
---|
377 | 395 | if (!err) |
---|
378 | 396 | return devinfo->ctl_urb_actual_length; |
---|
379 | | - else |
---|
380 | | - return err; |
---|
| 397 | +out: |
---|
| 398 | + return err; |
---|
381 | 399 | } |
---|
382 | 400 | |
---|
383 | 401 | static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo, |
---|
.. | .. |
---|
446 | 464 | |
---|
447 | 465 | } |
---|
448 | 466 | |
---|
449 | | -static void brcmf_usb_free_q(struct list_head *q, bool pending) |
---|
| 467 | +static void brcmf_usb_free_q(struct list_head *q) |
---|
450 | 468 | { |
---|
451 | 469 | struct brcmf_usbreq *req, *next; |
---|
452 | | - int i = 0; |
---|
| 470 | + |
---|
453 | 471 | list_for_each_entry_safe(req, next, q, list) { |
---|
454 | 472 | if (!req->urb) { |
---|
455 | 473 | brcmf_err("bad req\n"); |
---|
456 | 474 | break; |
---|
457 | 475 | } |
---|
458 | | - i++; |
---|
459 | | - if (pending) { |
---|
460 | | - usb_kill_urb(req->urb); |
---|
461 | | - } else { |
---|
462 | | - usb_free_urb(req->urb); |
---|
463 | | - list_del_init(&req->list); |
---|
464 | | - } |
---|
| 476 | + usb_free_urb(req->urb); |
---|
| 477 | + list_del_init(&req->list); |
---|
465 | 478 | } |
---|
466 | 479 | } |
---|
467 | 480 | |
---|
.. | .. |
---|
509 | 522 | skb = req->skb; |
---|
510 | 523 | req->skb = NULL; |
---|
511 | 524 | |
---|
512 | | - /* zero lenght packets indicate usb "failure". Do not refill */ |
---|
| 525 | + /* zero length packets indicate usb "failure". Do not refill */ |
---|
513 | 526 | if (urb->status != 0 || !urb->actual_length) { |
---|
514 | 527 | brcmu_pkt_buf_free_skb(skb); |
---|
515 | 528 | brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL); |
---|
516 | 529 | return; |
---|
517 | 530 | } |
---|
518 | 531 | |
---|
519 | | - if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { |
---|
| 532 | + if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP || |
---|
| 533 | + devinfo->bus_pub.state == BRCMFMAC_USB_STATE_SLEEP) { |
---|
520 | 534 | skb_put(skb, urb->actual_length); |
---|
521 | | - brcmf_rx_frame(devinfo->dev, skb, true); |
---|
| 535 | + brcmf_rx_frame(devinfo->dev, skb, true, true); |
---|
522 | 536 | brcmf_usb_rx_refill(devinfo, req); |
---|
| 537 | + usb_mark_last_busy(urb->dev); |
---|
523 | 538 | } else { |
---|
524 | 539 | brcmu_pkt_buf_free_skb(skb); |
---|
525 | 540 | brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL); |
---|
.. | .. |
---|
576 | 591 | brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state) |
---|
577 | 592 | { |
---|
578 | 593 | struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus; |
---|
579 | | - int old_state; |
---|
580 | 594 | |
---|
581 | 595 | brcmf_dbg(USB, "Enter, current state=%d, new state=%d\n", |
---|
582 | 596 | devinfo->bus_pub.state, state); |
---|
.. | .. |
---|
584 | 598 | if (devinfo->bus_pub.state == state) |
---|
585 | 599 | return; |
---|
586 | 600 | |
---|
587 | | - old_state = devinfo->bus_pub.state; |
---|
588 | 601 | devinfo->bus_pub.state = state; |
---|
589 | 602 | |
---|
590 | 603 | /* update state of upper layer */ |
---|
.. | .. |
---|
605 | 618 | struct brcmf_usbreq *req; |
---|
606 | 619 | int ret; |
---|
607 | 620 | unsigned long flags; |
---|
| 621 | + struct usb_interface *intf = to_usb_interface(dev); |
---|
| 622 | + |
---|
| 623 | + ret = usb_autopm_get_interface(intf); |
---|
| 624 | + if (ret) |
---|
| 625 | + goto out; |
---|
608 | 626 | |
---|
609 | 627 | brcmf_dbg(USB, "Enter, skb=%p\n", skb); |
---|
610 | 628 | if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { |
---|
.. | .. |
---|
643 | 661 | devinfo->tx_flowblock = true; |
---|
644 | 662 | } |
---|
645 | 663 | spin_unlock_irqrestore(&devinfo->tx_flowblock_lock, flags); |
---|
646 | | - return 0; |
---|
647 | 664 | |
---|
648 | 665 | fail: |
---|
| 666 | + usb_autopm_put_interface(intf); |
---|
| 667 | +out: |
---|
649 | 668 | return ret; |
---|
650 | 669 | } |
---|
651 | 670 | |
---|
.. | .. |
---|
1009 | 1028 | brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo) |
---|
1010 | 1029 | { |
---|
1011 | 1030 | int err; |
---|
| 1031 | + struct usb_interface *intf; |
---|
1012 | 1032 | |
---|
1013 | 1033 | brcmf_dbg(USB, "Enter\n"); |
---|
1014 | | - if (devinfo == NULL) |
---|
1015 | | - return -ENODEV; |
---|
| 1034 | + if (!devinfo) { |
---|
| 1035 | + err = -ENODEV; |
---|
| 1036 | + goto out; |
---|
| 1037 | + } |
---|
1016 | 1038 | |
---|
1017 | 1039 | if (!devinfo->image) { |
---|
1018 | 1040 | brcmf_err("No firmware!\n"); |
---|
1019 | | - return -ENOENT; |
---|
| 1041 | + err = -ENOENT; |
---|
| 1042 | + goto out; |
---|
1020 | 1043 | } |
---|
| 1044 | + |
---|
| 1045 | + intf = to_usb_interface(devinfo->dev); |
---|
| 1046 | + err = usb_autopm_get_interface(intf); |
---|
| 1047 | + if (err) |
---|
| 1048 | + goto out; |
---|
1021 | 1049 | |
---|
1022 | 1050 | err = brcmf_usb_dlstart(devinfo, |
---|
1023 | 1051 | (u8 *)devinfo->image, devinfo->image_len); |
---|
1024 | 1052 | if (err == 0) |
---|
1025 | 1053 | err = brcmf_usb_dlrun(devinfo); |
---|
| 1054 | + |
---|
| 1055 | + usb_autopm_put_interface(intf); |
---|
| 1056 | +out: |
---|
1026 | 1057 | return err; |
---|
1027 | 1058 | } |
---|
1028 | 1059 | |
---|
.. | .. |
---|
1032 | 1063 | brcmf_dbg(USB, "Enter, devinfo %p\n", devinfo); |
---|
1033 | 1064 | |
---|
1034 | 1065 | /* free the URBS */ |
---|
1035 | | - brcmf_usb_free_q(&devinfo->rx_freeq, false); |
---|
1036 | | - brcmf_usb_free_q(&devinfo->tx_freeq, false); |
---|
| 1066 | + brcmf_usb_free_q(&devinfo->rx_freeq); |
---|
| 1067 | + brcmf_usb_free_q(&devinfo->tx_freeq); |
---|
1037 | 1068 | |
---|
1038 | 1069 | usb_free_urb(devinfo->ctl_urb); |
---|
1039 | 1070 | usb_free_urb(devinfo->bulk_urb); |
---|
.. | .. |
---|
1123 | 1154 | return NULL; |
---|
1124 | 1155 | } |
---|
1125 | 1156 | |
---|
1126 | | -static void brcmf_usb_wowl_config(struct device *dev, bool enabled) |
---|
1127 | | -{ |
---|
1128 | | - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); |
---|
1129 | | - |
---|
1130 | | - brcmf_dbg(USB, "Configuring WOWL, enabled=%d\n", enabled); |
---|
1131 | | - devinfo->wowl_enabled = enabled; |
---|
1132 | | - if (enabled) |
---|
1133 | | - device_set_wakeup_enable(devinfo->dev, true); |
---|
1134 | | - else |
---|
1135 | | - device_set_wakeup_enable(devinfo->dev, false); |
---|
1136 | | -} |
---|
1137 | | - |
---|
1138 | 1157 | static |
---|
1139 | 1158 | int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name) |
---|
1140 | 1159 | { |
---|
.. | .. |
---|
1161 | 1180 | .txdata = brcmf_usb_tx, |
---|
1162 | 1181 | .txctl = brcmf_usb_tx_ctlpkt, |
---|
1163 | 1182 | .rxctl = brcmf_usb_rx_ctlpkt, |
---|
1164 | | - .wowl_config = brcmf_usb_wowl_config, |
---|
1165 | 1183 | .get_fwname = brcmf_usb_get_fwname, |
---|
1166 | 1184 | }; |
---|
1167 | 1185 | |
---|
.. | .. |
---|
1197 | 1215 | if (ret) |
---|
1198 | 1216 | goto error; |
---|
1199 | 1217 | |
---|
| 1218 | + ret = brcmf_alloc(devinfo->dev, devinfo->settings); |
---|
| 1219 | + if (ret) |
---|
| 1220 | + goto error; |
---|
| 1221 | + |
---|
1200 | 1222 | /* Attach to the common driver interface */ |
---|
1201 | | - ret = brcmf_attach(devinfo->dev, devinfo->settings); |
---|
| 1223 | + ret = brcmf_attach(devinfo->dev); |
---|
1202 | 1224 | if (ret) |
---|
1203 | 1225 | goto error; |
---|
1204 | 1226 | |
---|
.. | .. |
---|
1270 | 1292 | } |
---|
1271 | 1293 | |
---|
1272 | 1294 | if (!brcmf_usb_dlneeded(devinfo)) { |
---|
1273 | | - ret = brcmf_attach(devinfo->dev, devinfo->settings); |
---|
| 1295 | + ret = brcmf_alloc(devinfo->dev, devinfo->settings); |
---|
| 1296 | + if (ret) |
---|
| 1297 | + goto fail; |
---|
| 1298 | + ret = brcmf_attach(devinfo->dev); |
---|
1274 | 1299 | if (ret) |
---|
1275 | 1300 | goto fail; |
---|
1276 | 1301 | /* we are done */ |
---|
.. | .. |
---|
1298 | 1323 | |
---|
1299 | 1324 | fail: |
---|
1300 | 1325 | /* Release resources in reverse order */ |
---|
| 1326 | + brcmf_free(devinfo->dev); |
---|
1301 | 1327 | kfree(bus); |
---|
1302 | 1328 | brcmf_usb_detach(devinfo); |
---|
1303 | 1329 | return ret; |
---|
.. | .. |
---|
1311 | 1337 | brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo); |
---|
1312 | 1338 | |
---|
1313 | 1339 | brcmf_detach(devinfo->dev); |
---|
| 1340 | + brcmf_free(devinfo->dev); |
---|
1314 | 1341 | kfree(devinfo->bus_pub.bus); |
---|
1315 | 1342 | brcmf_usb_detach(devinfo); |
---|
1316 | 1343 | } |
---|
.. | .. |
---|
1340 | 1367 | init_completion(&devinfo->dev_init_done); |
---|
1341 | 1368 | |
---|
1342 | 1369 | usb_set_intfdata(intf, devinfo); |
---|
| 1370 | + |
---|
| 1371 | + intf->needs_remote_wakeup = 1; |
---|
1343 | 1372 | |
---|
1344 | 1373 | /* Check that the device supports only one configuration */ |
---|
1345 | 1374 | if (usb->descriptor.bNumConfigurations != 1) { |
---|
.. | .. |
---|
1454 | 1483 | |
---|
1455 | 1484 | brcmf_dbg(USB, "Enter\n"); |
---|
1456 | 1485 | devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP; |
---|
1457 | | - if (devinfo->wowl_enabled) |
---|
1458 | | - brcmf_cancel_all_urbs(devinfo); |
---|
1459 | | - else |
---|
1460 | | - brcmf_detach(&usb->dev); |
---|
| 1486 | + brcmf_cancel_all_urbs(devinfo); |
---|
| 1487 | + device_set_wakeup_enable(devinfo->dev, true); |
---|
1461 | 1488 | return 0; |
---|
1462 | 1489 | } |
---|
1463 | 1490 | |
---|
.. | .. |
---|
1470 | 1497 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); |
---|
1471 | 1498 | |
---|
1472 | 1499 | brcmf_dbg(USB, "Enter\n"); |
---|
1473 | | - if (!devinfo->wowl_enabled) |
---|
1474 | | - return brcmf_attach(devinfo->dev, devinfo->settings); |
---|
1475 | 1500 | |
---|
1476 | 1501 | devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP; |
---|
1477 | 1502 | brcmf_usb_rx_fill_all(devinfo); |
---|
| 1503 | + device_set_wakeup_enable(devinfo->dev, false); |
---|
1478 | 1504 | return 0; |
---|
1479 | 1505 | } |
---|
1480 | 1506 | |
---|
.. | .. |
---|
1531 | 1557 | .suspend = brcmf_usb_suspend, |
---|
1532 | 1558 | .resume = brcmf_usb_resume, |
---|
1533 | 1559 | .reset_resume = brcmf_usb_reset_resume, |
---|
| 1560 | + .supports_autosuspend = true, |
---|
1534 | 1561 | .disable_hub_initiated_lpm = 1, |
---|
1535 | 1562 | }; |
---|
1536 | 1563 | |
---|
.. | .. |
---|
1551 | 1578 | brcmf_dbg(USB, "Enter\n"); |
---|
1552 | 1579 | ret = driver_for_each_device(drv, NULL, NULL, |
---|
1553 | 1580 | brcmf_usb_reset_device); |
---|
| 1581 | + if (ret) |
---|
| 1582 | + brcmf_err("failed to reset all usb devices %d\n", ret); |
---|
| 1583 | + |
---|
1554 | 1584 | usb_deregister(&brcmf_usbdrvr); |
---|
1555 | 1585 | } |
---|
1556 | 1586 | |
---|
1557 | | -void brcmf_usb_register(void) |
---|
| 1587 | +int brcmf_usb_register(void) |
---|
1558 | 1588 | { |
---|
1559 | 1589 | brcmf_dbg(USB, "Enter\n"); |
---|
1560 | | - usb_register(&brcmf_usbdrvr); |
---|
| 1590 | + return usb_register(&brcmf_usbdrvr); |
---|
1561 | 1591 | } |
---|