diff options
Diffstat (limited to 'drivers/usb/serial/bus.c')
-rw-r--r-- | drivers/usb/serial/bus.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 6542f220468f..c08a38402b93 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
@@ -103,11 +103,52 @@ exit: | |||
103 | return retval; | 103 | return retval; |
104 | } | 104 | } |
105 | 105 | ||
106 | #ifdef CONFIG_HOTPLUG | ||
107 | static ssize_t store_new_id(struct device_driver *driver, | ||
108 | const char *buf, size_t count) | ||
109 | { | ||
110 | struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver); | ||
111 | ssize_t retval = usb_store_new_id(&usb_drv->dynids, driver, buf, count); | ||
112 | |||
113 | if (retval >= 0 && usb_drv->usb_driver != NULL) | ||
114 | retval = usb_store_new_id(&usb_drv->usb_driver->dynids, | ||
115 | &usb_drv->usb_driver->drvwrap.driver, | ||
116 | buf, count); | ||
117 | return retval; | ||
118 | } | ||
119 | |||
120 | static struct driver_attribute drv_attrs[] = { | ||
121 | __ATTR(new_id, S_IWUSR, NULL, store_new_id), | ||
122 | __ATTR_NULL, | ||
123 | }; | ||
124 | |||
125 | static void free_dynids(struct usb_serial_driver *drv) | ||
126 | { | ||
127 | struct usb_dynid *dynid, *n; | ||
128 | |||
129 | spin_lock(&drv->dynids.lock); | ||
130 | list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { | ||
131 | list_del(&dynid->node); | ||
132 | kfree(dynid); | ||
133 | } | ||
134 | spin_unlock(&drv->dynids.lock); | ||
135 | } | ||
136 | |||
137 | #else | ||
138 | static struct driver_attribute drv_attrs[] = { | ||
139 | __ATTR_NULL, | ||
140 | }; | ||
141 | static inline void free_dynids(struct usb_driver *drv) | ||
142 | { | ||
143 | } | ||
144 | #endif | ||
145 | |||
106 | struct bus_type usb_serial_bus_type = { | 146 | struct bus_type usb_serial_bus_type = { |
107 | .name = "usb-serial", | 147 | .name = "usb-serial", |
108 | .match = usb_serial_device_match, | 148 | .match = usb_serial_device_match, |
109 | .probe = usb_serial_device_probe, | 149 | .probe = usb_serial_device_probe, |
110 | .remove = usb_serial_device_remove, | 150 | .remove = usb_serial_device_remove, |
151 | .drv_attrs = drv_attrs, | ||
111 | }; | 152 | }; |
112 | 153 | ||
113 | int usb_serial_bus_register(struct usb_serial_driver *driver) | 154 | int usb_serial_bus_register(struct usb_serial_driver *driver) |
@@ -115,6 +156,9 @@ int usb_serial_bus_register(struct usb_serial_driver *driver) | |||
115 | int retval; | 156 | int retval; |
116 | 157 | ||
117 | driver->driver.bus = &usb_serial_bus_type; | 158 | driver->driver.bus = &usb_serial_bus_type; |
159 | spin_lock_init(&driver->dynids.lock); | ||
160 | INIT_LIST_HEAD(&driver->dynids.list); | ||
161 | |||
118 | retval = driver_register(&driver->driver); | 162 | retval = driver_register(&driver->driver); |
119 | 163 | ||
120 | return retval; | 164 | return retval; |
@@ -122,6 +166,7 @@ int usb_serial_bus_register(struct usb_serial_driver *driver) | |||
122 | 166 | ||
123 | void usb_serial_bus_deregister(struct usb_serial_driver *driver) | 167 | void usb_serial_bus_deregister(struct usb_serial_driver *driver) |
124 | { | 168 | { |
169 | free_dynids(driver); | ||
125 | driver_unregister(&driver->driver); | 170 | driver_unregister(&driver->driver); |
126 | } | 171 | } |
127 | 172 | ||