diff options
-rw-r--r-- | drivers/usb/gadget/at91_udc.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/dummy_hcd.c | 7 | ||||
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/gmidi.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/goku_udc.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/lh7a40x_udc.c | 13 | ||||
-rw-r--r-- | drivers/usb/gadget/net2280.c | 11 | ||||
-rw-r--r-- | drivers/usb/gadget/omap_udc.c | 13 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa2xx_udc.c | 7 | ||||
-rw-r--r-- | drivers/usb/gadget/serial.c | 2 |
10 files changed, 41 insertions, 47 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 3e0abbb49fe1..81656337381f 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
@@ -1574,7 +1574,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
1574 | if (!driver | 1574 | if (!driver |
1575 | || driver->speed != USB_SPEED_FULL | 1575 | || driver->speed != USB_SPEED_FULL |
1576 | || !driver->bind | 1576 | || !driver->bind |
1577 | || !driver->unbind | ||
1578 | || !driver->setup) { | 1577 | || !driver->setup) { |
1579 | DBG("bad parameter.\n"); | 1578 | DBG("bad parameter.\n"); |
1580 | return -EINVAL; | 1579 | return -EINVAL; |
@@ -1611,7 +1610,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
1611 | { | 1610 | { |
1612 | struct at91_udc *udc = &controller; | 1611 | struct at91_udc *udc = &controller; |
1613 | 1612 | ||
1614 | if (!driver || driver != udc->driver) | 1613 | if (!driver || driver != udc->driver || !driver->unbind) |
1615 | return -EINVAL; | 1614 | return -EINVAL; |
1616 | 1615 | ||
1617 | local_irq_disable(); | 1616 | local_irq_disable(); |
@@ -1731,10 +1730,10 @@ static int __devexit at91udc_remove(struct platform_device *pdev) | |||
1731 | 1730 | ||
1732 | DBG("remove\n"); | 1731 | DBG("remove\n"); |
1733 | 1732 | ||
1734 | pullup(udc, 0); | 1733 | if (udc->driver) |
1734 | return -EBUSY; | ||
1735 | 1735 | ||
1736 | if (udc->driver != 0) | 1736 | pullup(udc, 0); |
1737 | usb_gadget_unregister_driver(udc->driver); | ||
1738 | 1737 | ||
1739 | device_init_wakeup(&pdev->dev, 0); | 1738 | device_init_wakeup(&pdev->dev, 0); |
1740 | remove_debug_file(udc); | 1739 | remove_debug_file(udc); |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index f1f32d7be5f9..3c2bc075ef4f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -779,7 +779,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
779 | return -EINVAL; | 779 | return -EINVAL; |
780 | if (dum->driver) | 780 | if (dum->driver) |
781 | return -EBUSY; | 781 | return -EBUSY; |
782 | if (!driver->bind || !driver->unbind || !driver->setup | 782 | if (!driver->bind || !driver->setup |
783 | || driver->speed == USB_SPEED_UNKNOWN) | 783 | || driver->speed == USB_SPEED_UNKNOWN) |
784 | return -EINVAL; | 784 | return -EINVAL; |
785 | 785 | ||
@@ -837,7 +837,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
837 | err_bind_driver: | 837 | err_bind_driver: |
838 | driver_unregister (&driver->driver); | 838 | driver_unregister (&driver->driver); |
839 | err_register: | 839 | err_register: |
840 | driver->unbind (&dum->gadget); | 840 | if (driver->unbind) |
841 | driver->unbind (&dum->gadget); | ||
841 | spin_lock_irq (&dum->lock); | 842 | spin_lock_irq (&dum->lock); |
842 | dum->pullup = 0; | 843 | dum->pullup = 0; |
843 | set_link_state (dum); | 844 | set_link_state (dum); |
@@ -857,7 +858,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
857 | 858 | ||
858 | if (!dum) | 859 | if (!dum) |
859 | return -ENODEV; | 860 | return -ENODEV; |
860 | if (!driver || driver != dum->driver) | 861 | if (!driver || driver != dum->driver || !driver->unbind) |
861 | return -EINVAL; | 862 | return -EINVAL; |
862 | 863 | ||
863 | dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n", | 864 | dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n", |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a265e262a2ee..72f2ae96fbf3 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -4100,7 +4100,7 @@ static struct usb_gadget_driver fsg_driver = { | |||
4100 | #endif | 4100 | #endif |
4101 | .function = (char *) longname, | 4101 | .function = (char *) longname, |
4102 | .bind = fsg_bind, | 4102 | .bind = fsg_bind, |
4103 | .unbind = __exit_p(fsg_unbind), | 4103 | .unbind = fsg_unbind, |
4104 | .disconnect = fsg_disconnect, | 4104 | .disconnect = fsg_disconnect, |
4105 | .setup = fsg_setup, | 4105 | .setup = fsg_setup, |
4106 | .suspend = fsg_suspend, | 4106 | .suspend = fsg_suspend, |
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 31351826f2ba..f1a679656c96 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c | |||
@@ -123,7 +123,7 @@ struct gmidi_device { | |||
123 | struct usb_request *req; /* for control responses */ | 123 | struct usb_request *req; /* for control responses */ |
124 | u8 config; | 124 | u8 config; |
125 | struct usb_ep *in_ep, *out_ep; | 125 | struct usb_ep *in_ep, *out_ep; |
126 | struct snd_card *card; | 126 | struct snd_card *card; |
127 | struct snd_rawmidi *rmidi; | 127 | struct snd_rawmidi *rmidi; |
128 | struct snd_rawmidi_substream *in_substream; | 128 | struct snd_rawmidi_substream *in_substream; |
129 | struct snd_rawmidi_substream *out_substream; | 129 | struct snd_rawmidi_substream *out_substream; |
@@ -490,7 +490,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req) | |||
490 | int status = req->status; | 490 | int status = req->status; |
491 | 491 | ||
492 | switch (status) { | 492 | switch (status) { |
493 | case 0: /* normal completion */ | 493 | case 0: /* normal completion */ |
494 | if (ep == dev->out_ep) { | 494 | if (ep == dev->out_ep) { |
495 | /* we received stuff. | 495 | /* we received stuff. |
496 | req is queued again, below */ | 496 | req is queued again, below */ |
@@ -505,7 +505,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req) | |||
505 | break; | 505 | break; |
506 | 506 | ||
507 | /* this endpoint is normally active while we're configured */ | 507 | /* this endpoint is normally active while we're configured */ |
508 | case -ECONNABORTED: /* hardware forced ep reset */ | 508 | case -ECONNABORTED: /* hardware forced ep reset */ |
509 | case -ECONNRESET: /* request dequeued */ | 509 | case -ECONNRESET: /* request dequeued */ |
510 | case -ESHUTDOWN: /* disconnect from host */ | 510 | case -ESHUTDOWN: /* disconnect from host */ |
511 | VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, | 511 | VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, |
@@ -656,7 +656,7 @@ gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags) | |||
656 | case USB_SPEED_LOW: speed = "low"; break; | 656 | case USB_SPEED_LOW: speed = "low"; break; |
657 | case USB_SPEED_FULL: speed = "full"; break; | 657 | case USB_SPEED_FULL: speed = "full"; break; |
658 | case USB_SPEED_HIGH: speed = "high"; break; | 658 | case USB_SPEED_HIGH: speed = "high"; break; |
659 | default: speed = "?"; break; | 659 | default: speed = "?"; break; |
660 | } | 660 | } |
661 | 661 | ||
662 | dev->config = number; | 662 | dev->config = number; |
@@ -1308,7 +1308,7 @@ static struct usb_gadget_driver gmidi_driver = { | |||
1308 | .speed = USB_SPEED_FULL, | 1308 | .speed = USB_SPEED_FULL, |
1309 | .function = (char *)longname, | 1309 | .function = (char *)longname, |
1310 | .bind = gmidi_bind, | 1310 | .bind = gmidi_bind, |
1311 | .unbind = __exit_p(gmidi_unbind), | 1311 | .unbind = gmidi_unbind, |
1312 | 1312 | ||
1313 | .setup = gmidi_setup, | 1313 | .setup = gmidi_setup, |
1314 | .disconnect = gmidi_disconnect, | 1314 | .disconnect = gmidi_disconnect, |
@@ -1316,7 +1316,7 @@ static struct usb_gadget_driver gmidi_driver = { | |||
1316 | .suspend = gmidi_suspend, | 1316 | .suspend = gmidi_suspend, |
1317 | .resume = gmidi_resume, | 1317 | .resume = gmidi_resume, |
1318 | 1318 | ||
1319 | .driver = { | 1319 | .driver = { |
1320 | .name = (char *)shortname, | 1320 | .name = (char *)shortname, |
1321 | .owner = THIS_MODULE, | 1321 | .owner = THIS_MODULE, |
1322 | }, | 1322 | }, |
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 805a9826842d..d0ef1d6b3fac 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
@@ -1432,7 +1432,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | |||
1432 | if (!driver | 1432 | if (!driver |
1433 | || driver->speed != USB_SPEED_FULL | 1433 | || driver->speed != USB_SPEED_FULL |
1434 | || !driver->bind | 1434 | || !driver->bind |
1435 | || !driver->unbind | ||
1436 | || !driver->disconnect | 1435 | || !driver->disconnect |
1437 | || !driver->setup) | 1436 | || !driver->setup) |
1438 | return -EINVAL; | 1437 | return -EINVAL; |
@@ -1495,7 +1494,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1495 | 1494 | ||
1496 | if (!dev) | 1495 | if (!dev) |
1497 | return -ENODEV; | 1496 | return -ENODEV; |
1498 | if (!driver || driver != dev->driver) | 1497 | if (!driver || driver != dev->driver || !driver->unbind) |
1499 | return -EINVAL; | 1498 | return -EINVAL; |
1500 | 1499 | ||
1501 | spin_lock_irqsave(&dev->lock, flags); | 1500 | spin_lock_irqsave(&dev->lock, flags); |
@@ -1808,13 +1807,8 @@ static void goku_remove(struct pci_dev *pdev) | |||
1808 | struct goku_udc *dev = pci_get_drvdata(pdev); | 1807 | struct goku_udc *dev = pci_get_drvdata(pdev); |
1809 | 1808 | ||
1810 | DBG(dev, "%s\n", __FUNCTION__); | 1809 | DBG(dev, "%s\n", __FUNCTION__); |
1811 | /* start with the driver above us */ | 1810 | |
1812 | if (dev->driver) { | 1811 | BUG_ON(dev->driver); |
1813 | /* should have been done already by driver model core */ | ||
1814 | WARN(dev, "pci remove, driver '%s' is still registered\n", | ||
1815 | dev->driver->driver.name); | ||
1816 | usb_gadget_unregister_driver(dev->driver); | ||
1817 | } | ||
1818 | 1812 | ||
1819 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | 1813 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES |
1820 | remove_proc_entry(proc_node_name, NULL); | 1814 | remove_proc_entry(proc_node_name, NULL); |
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index 4a991564a03e..a0a73c08a344 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c | |||
@@ -422,9 +422,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | |||
422 | DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name); | 422 | DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name); |
423 | 423 | ||
424 | if (!driver | 424 | if (!driver |
425 | || driver->speed != USB_SPEED_FULL | 425 | || driver->speed != USB_SPEED_FULL |
426 | || !driver->bind | 426 | || !driver->bind |
427 | || !driver->unbind || !driver->disconnect || !driver->setup) | 427 | || !driver->disconnect |
428 | || !driver->setup) | ||
428 | return -EINVAL; | 429 | return -EINVAL; |
429 | if (!dev) | 430 | if (!dev) |
430 | return -ENODEV; | 431 | return -ENODEV; |
@@ -471,7 +472,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
471 | 472 | ||
472 | if (!dev) | 473 | if (!dev) |
473 | return -ENODEV; | 474 | return -ENODEV; |
474 | if (!driver || driver != dev->driver) | 475 | if (!driver || driver != dev->driver || !driver->unbind) |
475 | return -EINVAL; | 476 | return -EINVAL; |
476 | 477 | ||
477 | spin_lock_irqsave(&dev->lock, flags); | 478 | spin_lock_irqsave(&dev->lock, flags); |
@@ -2125,9 +2126,11 @@ static int lh7a40x_udc_remove(struct platform_device *pdev) | |||
2125 | 2126 | ||
2126 | DEBUG("%s: %p\n", __FUNCTION__, pdev); | 2127 | DEBUG("%s: %p\n", __FUNCTION__, pdev); |
2127 | 2128 | ||
2129 | if (dev->driver) | ||
2130 | return -EBUSY; | ||
2131 | |||
2128 | udc_disable(dev); | 2132 | udc_disable(dev); |
2129 | remove_proc_files(); | 2133 | remove_proc_files(); |
2130 | usb_gadget_unregister_driver(dev->driver); | ||
2131 | 2134 | ||
2132 | free_irq(IRQ_USBINTR, dev); | 2135 | free_irq(IRQ_USBINTR, dev); |
2133 | 2136 | ||
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 3024c679e38e..569eb8ccf232 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -2020,7 +2020,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2020 | if (!driver | 2020 | if (!driver |
2021 | || driver->speed != USB_SPEED_HIGH | 2021 | || driver->speed != USB_SPEED_HIGH |
2022 | || !driver->bind | 2022 | || !driver->bind |
2023 | || !driver->unbind | ||
2024 | || !driver->setup) | 2023 | || !driver->setup) |
2025 | return -EINVAL; | 2024 | return -EINVAL; |
2026 | if (!dev) | 2025 | if (!dev) |
@@ -2107,7 +2106,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
2107 | 2106 | ||
2108 | if (!dev) | 2107 | if (!dev) |
2109 | return -ENODEV; | 2108 | return -ENODEV; |
2110 | if (!driver || driver != dev->driver) | 2109 | if (!driver || driver != dev->driver || !driver->unbind) |
2111 | return -EINVAL; | 2110 | return -EINVAL; |
2112 | 2111 | ||
2113 | spin_lock_irqsave (&dev->lock, flags); | 2112 | spin_lock_irqsave (&dev->lock, flags); |
@@ -2803,13 +2802,7 @@ static void net2280_remove (struct pci_dev *pdev) | |||
2803 | { | 2802 | { |
2804 | struct net2280 *dev = pci_get_drvdata (pdev); | 2803 | struct net2280 *dev = pci_get_drvdata (pdev); |
2805 | 2804 | ||
2806 | /* start with the driver above us */ | 2805 | BUG_ON(dev->driver); |
2807 | if (dev->driver) { | ||
2808 | /* should have been done already by driver model core */ | ||
2809 | WARN (dev, "pci remove, driver '%s' is still registered\n", | ||
2810 | dev->driver->driver.name); | ||
2811 | usb_gadget_unregister_driver (dev->driver); | ||
2812 | } | ||
2813 | 2806 | ||
2814 | /* then clean up the resources we allocated during probe() */ | 2807 | /* then clean up the resources we allocated during probe() */ |
2815 | net2280_led_shutdown (dev); | 2808 | net2280_led_shutdown (dev); |
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 030d87c28c2f..15d77c307930 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
@@ -2043,7 +2043,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2043 | // FIXME if otg, check: driver->is_otg | 2043 | // FIXME if otg, check: driver->is_otg |
2044 | || driver->speed < USB_SPEED_FULL | 2044 | || driver->speed < USB_SPEED_FULL |
2045 | || !driver->bind | 2045 | || !driver->bind |
2046 | || !driver->unbind | ||
2047 | || !driver->setup) | 2046 | || !driver->setup) |
2048 | return -EINVAL; | 2047 | return -EINVAL; |
2049 | 2048 | ||
@@ -2087,9 +2086,11 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2087 | status = otg_set_peripheral(udc->transceiver, &udc->gadget); | 2086 | status = otg_set_peripheral(udc->transceiver, &udc->gadget); |
2088 | if (status < 0) { | 2087 | if (status < 0) { |
2089 | ERR("can't bind to transceiver\n"); | 2088 | ERR("can't bind to transceiver\n"); |
2090 | driver->unbind (&udc->gadget); | 2089 | if (driver->unbind) { |
2091 | udc->gadget.dev.driver = NULL; | 2090 | driver->unbind (&udc->gadget); |
2092 | udc->driver = NULL; | 2091 | udc->gadget.dev.driver = NULL; |
2092 | udc->driver = NULL; | ||
2093 | } | ||
2093 | goto done; | 2094 | goto done; |
2094 | } | 2095 | } |
2095 | } else { | 2096 | } else { |
@@ -2117,7 +2118,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
2117 | 2118 | ||
2118 | if (!udc) | 2119 | if (!udc) |
2119 | return -ENODEV; | 2120 | return -ENODEV; |
2120 | if (!driver || driver != udc->driver) | 2121 | if (!driver || driver != udc->driver || !driver->unbind) |
2121 | return -EINVAL; | 2122 | return -EINVAL; |
2122 | 2123 | ||
2123 | if (machine_is_omap_innovator() || machine_is_omap_osk()) | 2124 | if (machine_is_omap_innovator() || machine_is_omap_osk()) |
@@ -2870,6 +2871,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev) | |||
2870 | 2871 | ||
2871 | if (!udc) | 2872 | if (!udc) |
2872 | return -ENODEV; | 2873 | return -ENODEV; |
2874 | if (udc->driver) | ||
2875 | return -EBUSY; | ||
2873 | 2876 | ||
2874 | udc->done = &done; | 2877 | udc->done = &done; |
2875 | 2878 | ||
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 1ed506e95985..b78de9694665 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
@@ -1623,7 +1623,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | |||
1623 | if (!driver | 1623 | if (!driver |
1624 | || driver->speed < USB_SPEED_FULL | 1624 | || driver->speed < USB_SPEED_FULL |
1625 | || !driver->bind | 1625 | || !driver->bind |
1626 | || !driver->unbind | ||
1627 | || !driver->disconnect | 1626 | || !driver->disconnect |
1628 | || !driver->setup) | 1627 | || !driver->setup) |
1629 | return -EINVAL; | 1628 | return -EINVAL; |
@@ -1694,7 +1693,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1694 | 1693 | ||
1695 | if (!dev) | 1694 | if (!dev) |
1696 | return -ENODEV; | 1695 | return -ENODEV; |
1697 | if (!driver || driver != dev->driver) | 1696 | if (!driver || driver != dev->driver || !driver->unbind) |
1698 | return -EINVAL; | 1697 | return -EINVAL; |
1699 | 1698 | ||
1700 | local_irq_disable(); | 1699 | local_irq_disable(); |
@@ -2638,9 +2637,11 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) | |||
2638 | { | 2637 | { |
2639 | struct pxa2xx_udc *dev = platform_get_drvdata(pdev); | 2638 | struct pxa2xx_udc *dev = platform_get_drvdata(pdev); |
2640 | 2639 | ||
2640 | if (dev->driver) | ||
2641 | return -EBUSY; | ||
2642 | |||
2641 | udc_disable(dev); | 2643 | udc_disable(dev); |
2642 | remove_proc_files(); | 2644 | remove_proc_files(); |
2643 | usb_gadget_unregister_driver(dev->driver); | ||
2644 | 2645 | ||
2645 | if (dev->got_irq) { | 2646 | if (dev->got_irq) { |
2646 | free_irq(IRQ_USB, dev); | 2647 | free_irq(IRQ_USB, dev); |
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 2d12bf9f19d6..f8a3ec64635d 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -296,7 +296,7 @@ static struct usb_gadget_driver gs_gadget_driver = { | |||
296 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ | 296 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ |
297 | .function = GS_LONG_NAME, | 297 | .function = GS_LONG_NAME, |
298 | .bind = gs_bind, | 298 | .bind = gs_bind, |
299 | .unbind = __exit_p(gs_unbind), | 299 | .unbind = gs_unbind, |
300 | .setup = gs_setup, | 300 | .setup = gs_setup, |
301 | .disconnect = gs_disconnect, | 301 | .disconnect = gs_disconnect, |
302 | .driver = { | 302 | .driver = { |