| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: usbnet.c,v 1.47 2022/03/03 05:47:06 riastradh Exp $ */ | | 1 | /* $NetBSD: usbnet.c,v 1.48 2022/03/03 05:47:14 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2019 Matthew R. Green | | 4 | * Copyright (c) 2019 Matthew R. Green |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -21,27 +21,27 @@ | | | @@ -21,27 +21,27 @@ |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. | | 26 | * SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | /* | | 29 | /* |
30 | * Common code shared between USB network drivers. | | 30 | * Common code shared between USB network drivers. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | #include <sys/cdefs.h> | | 33 | #include <sys/cdefs.h> |
34 | __KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.47 2022/03/03 05:47:06 riastradh Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.48 2022/03/03 05:47:14 riastradh Exp $"); |
35 | | | 35 | |
36 | #include <sys/param.h> | | 36 | #include <sys/param.h> |
37 | #include <sys/kernel.h> | | 37 | #include <sys/kernel.h> |
38 | #include <sys/kmem.h> | | 38 | #include <sys/kmem.h> |
39 | #include <sys/module.h> | | 39 | #include <sys/module.h> |
40 | #include <sys/atomic.h> | | 40 | #include <sys/atomic.h> |
41 | | | 41 | |
42 | #include <dev/usb/usbnet.h> | | 42 | #include <dev/usb/usbnet.h> |
43 | #include <dev/usb/usbhist.h> | | 43 | #include <dev/usb/usbhist.h> |
44 | | | 44 | |
45 | struct usbnet_cdata { | | 45 | struct usbnet_cdata { |
46 | struct usbnet_chain *uncd_tx_chain; | | 46 | struct usbnet_chain *uncd_tx_chain; |
47 | struct usbnet_chain *uncd_rx_chain; | | 47 | struct usbnet_chain *uncd_rx_chain; |
| @@ -70,26 +70,27 @@ struct usbnet_private { | | | @@ -70,26 +70,27 @@ struct usbnet_private { |
70 | | | 70 | |
71 | struct usbnet_cdata unp_cdata; | | 71 | struct usbnet_cdata unp_cdata; |
72 | | | 72 | |
73 | struct ethercom unp_ec; | | 73 | struct ethercom unp_ec; |
74 | struct mii_data unp_mii; | | 74 | struct mii_data unp_mii; |
75 | struct usb_task unp_mcasttask; | | 75 | struct usb_task unp_mcasttask; |
76 | struct usb_task unp_ticktask; | | 76 | struct usb_task unp_ticktask; |
77 | struct callout unp_stat_ch; | | 77 | struct callout unp_stat_ch; |
78 | struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; | | 78 | struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; |
79 | | | 79 | |
80 | bool unp_dying; | | 80 | bool unp_dying; |
81 | bool unp_stopping; | | 81 | bool unp_stopping; |
82 | bool unp_attached; | | 82 | bool unp_attached; |
| | | 83 | bool unp_ifp_attached; |
83 | bool unp_link; | | 84 | bool unp_link; |
84 | | | 85 | |
85 | int unp_refcnt; | | 86 | int unp_refcnt; |
86 | int unp_timer; | | 87 | int unp_timer; |
87 | unsigned short unp_if_flags; | | 88 | unsigned short unp_if_flags; |
88 | unsigned unp_number; | | 89 | unsigned unp_number; |
89 | | | 90 | |
90 | krndsource_t unp_rndsrc; | | 91 | krndsource_t unp_rndsrc; |
91 | | | 92 | |
92 | struct timeval unp_rx_notice; | | 93 | struct timeval unp_rx_notice; |
93 | struct timeval unp_tx_notice; | | 94 | struct timeval unp_tx_notice; |
94 | struct timeval unp_intr_notice; | | 95 | struct timeval unp_intr_notice; |
95 | }; | | 96 | }; |
| @@ -1482,63 +1483,65 @@ usbnet_attach_mii(struct usbnet *un, con | | | @@ -1482,63 +1483,65 @@ usbnet_attach_mii(struct usbnet *un, con |
1482 | } | | 1483 | } |
1483 | | | 1484 | |
1484 | void | | 1485 | void |
1485 | usbnet_attach_ifp(struct usbnet *un, | | 1486 | usbnet_attach_ifp(struct usbnet *un, |
1486 | unsigned if_flags, /* additional if_flags */ | | 1487 | unsigned if_flags, /* additional if_flags */ |
1487 | unsigned if_extflags, /* additional if_extflags */ | | 1488 | unsigned if_extflags, /* additional if_extflags */ |
1488 | const struct usbnet_mii *unm) /* additional mii_attach flags */ | | 1489 | const struct usbnet_mii *unm) /* additional mii_attach flags */ |
1489 | { | | 1490 | { |
1490 | USBNETHIST_FUNC(); USBNETHIST_CALLED(); | | 1491 | USBNETHIST_FUNC(); USBNETHIST_CALLED(); |
1491 | struct usbnet_private * const unp = un->un_pri; | | 1492 | struct usbnet_private * const unp = un->un_pri; |
1492 | struct ifnet * const ifp = usbnet_ifp(un); | | 1493 | struct ifnet * const ifp = usbnet_ifp(un); |
1493 | | | 1494 | |
1494 | KASSERT(unp->unp_attached); | | 1495 | KASSERT(unp->unp_attached); |
| | | 1496 | KASSERT(!unp->unp_ifp_attached); |
1495 | | | 1497 | |
| | | 1498 | ifp->if_softc = un; |
1496 | strlcpy(ifp->if_xname, device_xname(un->un_dev), IFNAMSIZ); | | 1499 | strlcpy(ifp->if_xname, device_xname(un->un_dev), IFNAMSIZ); |
1497 | ifp->if_flags = if_flags; | | 1500 | ifp->if_flags = if_flags; |
1498 | ifp->if_extflags = IFEF_MPSAFE | if_extflags; | | 1501 | ifp->if_extflags = IFEF_MPSAFE | if_extflags; |
1499 | ifp->if_ioctl = usbnet_if_ioctl; | | 1502 | ifp->if_ioctl = usbnet_if_ioctl; |
1500 | ifp->if_start = usbnet_if_start; | | 1503 | ifp->if_start = usbnet_if_start; |
1501 | ifp->if_init = usbnet_if_init; | | 1504 | ifp->if_init = usbnet_if_init; |
1502 | ifp->if_stop = usbnet_if_stop; | | 1505 | ifp->if_stop = usbnet_if_stop; |
1503 | | | 1506 | |
1504 | if (unm) | | 1507 | if (unm) |
1505 | usbnet_attach_mii(un, unm); | | 1508 | usbnet_attach_mii(un, unm); |
1506 | else | | 1509 | else |
1507 | unp->unp_link = true; | | 1510 | unp->unp_link = true; |
1508 | | | 1511 | |
1509 | /* Attach the interface. */ | | 1512 | /* Attach the interface. */ |
1510 | if_initialize(ifp); | | 1513 | if_initialize(ifp); |
1511 | if (ifp->_if_input == NULL) | | 1514 | if (ifp->_if_input == NULL) |
1512 | ifp->if_percpuq = if_percpuq_create(ifp); | | 1515 | ifp->if_percpuq = if_percpuq_create(ifp); |
1513 | if_register(ifp); | | 1516 | if_register(ifp); |
| | | 1517 | unp->unp_ifp_attached = true; |
1514 | | | 1518 | |
1515 | /* | | 1519 | /* |
1516 | * If ethernet address is all zero, skip ether_ifattach() and | | 1520 | * If ethernet address is all zero, skip ether_ifattach() and |
1517 | * instead attach bpf here.. | | 1521 | * instead attach bpf here.. |
1518 | */ | | 1522 | */ |
1519 | if (!usbnet_empty_eaddr(un)) { | | 1523 | if (!usbnet_empty_eaddr(un)) { |
1520 | ether_set_ifflags_cb(&unp->unp_ec, usbnet_ifflags_cb); | | 1524 | ether_set_ifflags_cb(&unp->unp_ec, usbnet_ifflags_cb); |
1521 | aprint_normal_dev(un->un_dev, "Ethernet address %s\n", | | 1525 | aprint_normal_dev(un->un_dev, "Ethernet address %s\n", |
1522 | ether_sprintf(un->un_eaddr)); | | 1526 | ether_sprintf(un->un_eaddr)); |
1523 | ether_ifattach(ifp, un->un_eaddr); | | 1527 | ether_ifattach(ifp, un->un_eaddr); |
1524 | } else { | | 1528 | } else { |
1525 | if_alloc_sadl(ifp); | | 1529 | if_alloc_sadl(ifp); |
1526 | bpf_attach(ifp, DLT_RAW, 0); | | 1530 | bpf_attach(ifp, DLT_RAW, 0); |
1527 | } | | 1531 | } |
1528 | | | 1532 | |
1529 | /* Now ready, and attached. */ | | 1533 | /* Now ready, and attached. */ |
1530 | IFQ_SET_READY(&ifp->if_snd); | | 1534 | IFQ_SET_READY(&ifp->if_snd); |
1531 | ifp->if_softc = un; | | | |
1532 | | | 1535 | |
1533 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, un->un_udev, un->un_dev); | | 1536 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, un->un_udev, un->un_dev); |
1534 | | | 1537 | |
1535 | if (!pmf_device_register(un->un_dev, NULL, NULL)) | | 1538 | if (!pmf_device_register(un->un_dev, NULL, NULL)) |
1536 | aprint_error_dev(un->un_dev, "couldn't establish power handler\n"); | | 1539 | aprint_error_dev(un->un_dev, "couldn't establish power handler\n"); |
1537 | } | | 1540 | } |
1538 | | | 1541 | |
1539 | int | | 1542 | int |
1540 | usbnet_detach(device_t self, int flags) | | 1543 | usbnet_detach(device_t self, int flags) |
1541 | { | | 1544 | { |
1542 | USBNETHIST_FUNC(); USBNETHIST_CALLED(); | | 1545 | USBNETHIST_FUNC(); USBNETHIST_CALLED(); |
1543 | struct usbnet * const un = device_private(self); | | 1546 | struct usbnet * const un = device_private(self); |
1544 | struct usbnet_private * const unp = un->un_pri; | | 1547 | struct usbnet_private * const unp = un->un_pri; |
| @@ -1574,27 +1577,27 @@ usbnet_detach(device_t self, int flags) | | | @@ -1574,27 +1577,27 @@ usbnet_detach(device_t self, int flags) |
1574 | } | | 1577 | } |
1575 | mutex_exit(&unp->unp_core_lock); | | 1578 | mutex_exit(&unp->unp_core_lock); |
1576 | | | 1579 | |
1577 | usbnet_rx_list_free(un); | | 1580 | usbnet_rx_list_free(un); |
1578 | usbnet_tx_list_free(un); | | 1581 | usbnet_tx_list_free(un); |
1579 | | | 1582 | |
1580 | callout_destroy(&unp->unp_stat_ch); | | 1583 | callout_destroy(&unp->unp_stat_ch); |
1581 | rnd_detach_source(&unp->unp_rndsrc); | | 1584 | rnd_detach_source(&unp->unp_rndsrc); |
1582 | | | 1585 | |
1583 | if (mii) { | | 1586 | if (mii) { |
1584 | mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY); | | 1587 | mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY); |
1585 | ifmedia_fini(&mii->mii_media); | | 1588 | ifmedia_fini(&mii->mii_media); |
1586 | } | | 1589 | } |
1587 | if (ifp->if_softc) { | | 1590 | if (unp->unp_ifp_attached) { |
1588 | if (!usbnet_empty_eaddr(un)) | | 1591 | if (!usbnet_empty_eaddr(un)) |
1589 | ether_ifdetach(ifp); | | 1592 | ether_ifdetach(ifp); |
1590 | else | | 1593 | else |
1591 | bpf_detach(ifp); | | 1594 | bpf_detach(ifp); |
1592 | if_detach(ifp); | | 1595 | if_detach(ifp); |
1593 | } | | 1596 | } |
1594 | usbnet_ec(un)->ec_mii = NULL; | | 1597 | usbnet_ec(un)->ec_mii = NULL; |
1595 | | | 1598 | |
1596 | /* | | 1599 | /* |
1597 | * We have already waited for the multicast task to complete. | | 1600 | * We have already waited for the multicast task to complete. |
1598 | * Unfortunately, until if_detach, nothing has prevented it | | 1601 | * Unfortunately, until if_detach, nothing has prevented it |
1599 | * from running again -- another thread might issue if_mcast_op | | 1602 | * from running again -- another thread might issue if_mcast_op |
1600 | * between the time of our first usb_rem_task_wait and the time | | 1603 | * between the time of our first usb_rem_task_wait and the time |