diff options
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/hso.c | 110 |
1 files changed, 23 insertions, 87 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index af62f58ffcbf..39df44f99d65 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
@@ -230,11 +230,6 @@ struct hso_serial { | |||
230 | struct work_struct retry_unthrottle_workqueue; | 230 | struct work_struct retry_unthrottle_workqueue; |
231 | }; | 231 | }; |
232 | 232 | ||
233 | struct hso_mutex_t { | ||
234 | struct mutex mutex; | ||
235 | u8 allocated; | ||
236 | }; | ||
237 | |||
238 | struct hso_device { | 233 | struct hso_device { |
239 | union { | 234 | union { |
240 | struct hso_serial *dev_serial; | 235 | struct hso_serial *dev_serial; |
@@ -253,7 +248,7 @@ struct hso_device { | |||
253 | 248 | ||
254 | struct device *dev; | 249 | struct device *dev; |
255 | struct kref ref; | 250 | struct kref ref; |
256 | struct hso_mutex_t *mutex; | 251 | struct mutex mutex; |
257 | }; | 252 | }; |
258 | 253 | ||
259 | /* Type of interface */ | 254 | /* Type of interface */ |
@@ -369,13 +364,6 @@ static struct hso_device *network_table[HSO_MAX_NET_DEVICES]; | |||
369 | static spinlock_t serial_table_lock; | 364 | static spinlock_t serial_table_lock; |
370 | static struct ktermios *hso_serial_termios[HSO_SERIAL_TTY_MINORS]; | 365 | static struct ktermios *hso_serial_termios[HSO_SERIAL_TTY_MINORS]; |
371 | static struct ktermios *hso_serial_termios_locked[HSO_SERIAL_TTY_MINORS]; | 366 | static struct ktermios *hso_serial_termios_locked[HSO_SERIAL_TTY_MINORS]; |
372 | /* hso_mutex_table has to be declared statically as hso_device | ||
373 | * is freed in hso_serial_open & hso_serial_close while | ||
374 | * the mutex is still in use. | ||
375 | */ | ||
376 | #define HSO_NUM_MUTEXES (HSO_SERIAL_TTY_MINORS+HSO_MAX_NET_DEVICES) | ||
377 | static struct hso_mutex_t hso_mutex_table[HSO_NUM_MUTEXES]; | ||
378 | static spinlock_t hso_mutex_lock; | ||
379 | 367 | ||
380 | static const s32 default_port_spec[] = { | 368 | static const s32 default_port_spec[] = { |
381 | HSO_INTF_MUX | HSO_PORT_NETWORK, | 369 | HSO_INTF_MUX | HSO_PORT_NETWORK, |
@@ -616,34 +604,6 @@ static void set_serial_by_index(unsigned index, struct hso_serial *serial) | |||
616 | spin_unlock_irqrestore(&serial_table_lock, flags); | 604 | spin_unlock_irqrestore(&serial_table_lock, flags); |
617 | } | 605 | } |
618 | 606 | ||
619 | |||
620 | static struct hso_mutex_t *hso_get_free_mutex(void) | ||
621 | { | ||
622 | int index; | ||
623 | struct hso_mutex_t *curr_hso_mutex; | ||
624 | |||
625 | spin_lock(&hso_mutex_lock); | ||
626 | for (index = 0; index < HSO_NUM_MUTEXES; index++) { | ||
627 | curr_hso_mutex = &hso_mutex_table[index]; | ||
628 | if (!curr_hso_mutex->allocated) { | ||
629 | curr_hso_mutex->allocated = 1; | ||
630 | spin_unlock(&hso_mutex_lock); | ||
631 | return curr_hso_mutex; | ||
632 | } | ||
633 | } | ||
634 | printk(KERN_ERR "BUG %s: no free hso_mutexs devices in table\n" | ||
635 | , __func__); | ||
636 | spin_unlock(&hso_mutex_lock); | ||
637 | return NULL; | ||
638 | } | ||
639 | |||
640 | static void hso_free_mutex(struct hso_mutex_t *mutex) | ||
641 | { | ||
642 | spin_lock(&hso_mutex_lock); | ||
643 | mutex->allocated = 0; | ||
644 | spin_unlock(&hso_mutex_lock); | ||
645 | } | ||
646 | |||
647 | /* log a meaningful explanation of an USB status */ | 607 | /* log a meaningful explanation of an USB status */ |
648 | static void log_usb_status(int status, const char *function) | 608 | static void log_usb_status(int status, const char *function) |
649 | { | 609 | { |
@@ -1265,9 +1225,7 @@ void hso_unthrottle_workfunc(struct work_struct *work) | |||
1265 | static int hso_serial_open(struct tty_struct *tty, struct file *filp) | 1225 | static int hso_serial_open(struct tty_struct *tty, struct file *filp) |
1266 | { | 1226 | { |
1267 | struct hso_serial *serial = get_serial_by_index(tty->index); | 1227 | struct hso_serial *serial = get_serial_by_index(tty->index); |
1268 | int result1 = 0, result2 = 0; | 1228 | int result; |
1269 | struct mutex *hso_mutex = NULL; | ||
1270 | int refcnt = 1; | ||
1271 | 1229 | ||
1272 | /* sanity check */ | 1230 | /* sanity check */ |
1273 | if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { | 1231 | if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { |
@@ -1276,15 +1234,14 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) | |||
1276 | return -ENODEV; | 1234 | return -ENODEV; |
1277 | } | 1235 | } |
1278 | 1236 | ||
1279 | hso_mutex = &serial->parent->mutex->mutex; | 1237 | mutex_lock(&serial->parent->mutex); |
1280 | mutex_lock(hso_mutex); | ||
1281 | /* check for port already opened, if not set the termios */ | 1238 | /* check for port already opened, if not set the termios */ |
1282 | /* The serial->open count needs to be here as hso_serial_close | 1239 | /* The serial->open count needs to be here as hso_serial_close |
1283 | * will be called even if hso_serial_open returns -ENODEV. | 1240 | * will be called even if hso_serial_open returns -ENODEV. |
1284 | */ | 1241 | */ |
1285 | serial->open_count++; | 1242 | serial->open_count++; |
1286 | result1 = usb_autopm_get_interface(serial->parent->interface); | 1243 | result = usb_autopm_get_interface(serial->parent->interface); |
1287 | if (result1 < 0) | 1244 | if (result < 0) |
1288 | goto err_out; | 1245 | goto err_out; |
1289 | 1246 | ||
1290 | D1("Opening %d", serial->minor); | 1247 | D1("Opening %d", serial->minor); |
@@ -1304,10 +1261,11 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) | |||
1304 | (unsigned long)serial); | 1261 | (unsigned long)serial); |
1305 | INIT_WORK(&serial->retry_unthrottle_workqueue, | 1262 | INIT_WORK(&serial->retry_unthrottle_workqueue, |
1306 | hso_unthrottle_workfunc); | 1263 | hso_unthrottle_workfunc); |
1307 | result2 = hso_start_serial_device(serial->parent, GFP_KERNEL); | 1264 | result = hso_start_serial_device(serial->parent, GFP_KERNEL); |
1308 | if (result2) { | 1265 | if (result) { |
1309 | hso_stop_serial_device(serial->parent); | 1266 | hso_stop_serial_device(serial->parent); |
1310 | serial->open_count--; | 1267 | serial->open_count--; |
1268 | kref_put(&serial->parent->ref, hso_serial_ref_free); | ||
1311 | } | 1269 | } |
1312 | } else { | 1270 | } else { |
1313 | D1("Port was already open"); | 1271 | D1("Port was already open"); |
@@ -1316,16 +1274,11 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) | |||
1316 | usb_autopm_put_interface(serial->parent->interface); | 1274 | usb_autopm_put_interface(serial->parent->interface); |
1317 | 1275 | ||
1318 | /* done */ | 1276 | /* done */ |
1319 | if (result1) | 1277 | if (result) |
1320 | hso_serial_tiocmset(tty, NULL, TIOCM_RTS | TIOCM_DTR, 0); | 1278 | hso_serial_tiocmset(tty, NULL, TIOCM_RTS | TIOCM_DTR, 0); |
1321 | err_out: | 1279 | err_out: |
1322 | if (result2) | 1280 | mutex_unlock(&serial->parent->mutex); |
1323 | refcnt = kref_put(&serial->parent->ref, hso_serial_ref_free); | 1281 | return result; |
1324 | mutex_unlock(hso_mutex); | ||
1325 | if (refcnt == 0) | ||
1326 | hso_free_mutex(container_of(hso_mutex, | ||
1327 | struct hso_mutex_t, mutex)); | ||
1328 | return result1 == 0 ? result2 : result1; | ||
1329 | } | 1282 | } |
1330 | 1283 | ||
1331 | /* close the requested serial port */ | 1284 | /* close the requested serial port */ |
@@ -1333,8 +1286,6 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) | |||
1333 | { | 1286 | { |
1334 | struct hso_serial *serial = tty->driver_data; | 1287 | struct hso_serial *serial = tty->driver_data; |
1335 | u8 usb_gone; | 1288 | u8 usb_gone; |
1336 | struct mutex *hso_mutex; | ||
1337 | int refcnt; | ||
1338 | 1289 | ||
1339 | D1("Closing serial port"); | 1290 | D1("Closing serial port"); |
1340 | if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { | 1291 | if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { |
@@ -1342,9 +1293,8 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) | |||
1342 | return; | 1293 | return; |
1343 | } | 1294 | } |
1344 | 1295 | ||
1296 | mutex_lock(&serial->parent->mutex); | ||
1345 | usb_gone = serial->parent->usb_gone; | 1297 | usb_gone = serial->parent->usb_gone; |
1346 | hso_mutex = &serial->parent->mutex->mutex; | ||
1347 | mutex_lock(hso_mutex); | ||
1348 | 1298 | ||
1349 | if (!usb_gone) | 1299 | if (!usb_gone) |
1350 | usb_autopm_get_interface(serial->parent->interface); | 1300 | usb_autopm_get_interface(serial->parent->interface); |
@@ -1352,6 +1302,7 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) | |||
1352 | /* reset the rts and dtr */ | 1302 | /* reset the rts and dtr */ |
1353 | /* do the actual close */ | 1303 | /* do the actual close */ |
1354 | serial->open_count--; | 1304 | serial->open_count--; |
1305 | kref_put(&serial->parent->ref, hso_serial_ref_free); | ||
1355 | if (serial->open_count <= 0) { | 1306 | if (serial->open_count <= 0) { |
1356 | serial->open_count = 0; | 1307 | serial->open_count = 0; |
1357 | if (serial->tty) { | 1308 | if (serial->tty) { |
@@ -1366,11 +1317,8 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) | |||
1366 | 1317 | ||
1367 | if (!usb_gone) | 1318 | if (!usb_gone) |
1368 | usb_autopm_put_interface(serial->parent->interface); | 1319 | usb_autopm_put_interface(serial->parent->interface); |
1369 | refcnt = kref_put(&serial->parent->ref, hso_serial_ref_free); | 1320 | |
1370 | mutex_unlock(hso_mutex); | 1321 | mutex_unlock(&serial->parent->mutex); |
1371 | if (refcnt == 0) | ||
1372 | hso_free_mutex(container_of(hso_mutex, | ||
1373 | struct hso_mutex_t, mutex)); | ||
1374 | } | 1322 | } |
1375 | 1323 | ||
1376 | /* close the requested serial port */ | 1324 | /* close the requested serial port */ |
@@ -2136,12 +2084,8 @@ static struct hso_device *hso_create_device(struct usb_interface *intf, | |||
2136 | hso_dev->usb = interface_to_usbdev(intf); | 2084 | hso_dev->usb = interface_to_usbdev(intf); |
2137 | hso_dev->interface = intf; | 2085 | hso_dev->interface = intf; |
2138 | kref_init(&hso_dev->ref); | 2086 | kref_init(&hso_dev->ref); |
2139 | hso_dev->mutex = hso_get_free_mutex(); | 2087 | mutex_init(&hso_dev->mutex); |
2140 | if (!hso_dev->mutex) { | 2088 | |
2141 | kfree(hso_dev); | ||
2142 | return NULL; | ||
2143 | } | ||
2144 | mutex_init(&hso_dev->mutex->mutex); | ||
2145 | INIT_WORK(&hso_dev->async_get_intf, async_get_intf); | 2089 | INIT_WORK(&hso_dev->async_get_intf, async_get_intf); |
2146 | INIT_WORK(&hso_dev->async_put_intf, async_put_intf); | 2090 | INIT_WORK(&hso_dev->async_put_intf, async_put_intf); |
2147 | 2091 | ||
@@ -2187,7 +2131,7 @@ static void hso_free_net_device(struct hso_device *hso_dev) | |||
2187 | unregister_netdev(hso_net->net); | 2131 | unregister_netdev(hso_net->net); |
2188 | free_netdev(hso_net->net); | 2132 | free_netdev(hso_net->net); |
2189 | } | 2133 | } |
2190 | hso_free_mutex(hso_dev->mutex); | 2134 | |
2191 | hso_free_device(hso_dev); | 2135 | hso_free_device(hso_dev); |
2192 | } | 2136 | } |
2193 | 2137 | ||
@@ -2236,14 +2180,14 @@ static int hso_radio_toggle(void *data, enum rfkill_state state) | |||
2236 | int enabled = (state == RFKILL_STATE_ON); | 2180 | int enabled = (state == RFKILL_STATE_ON); |
2237 | int rv; | 2181 | int rv; |
2238 | 2182 | ||
2239 | mutex_lock(&hso_dev->mutex->mutex); | 2183 | mutex_lock(&hso_dev->mutex); |
2240 | if (hso_dev->usb_gone) | 2184 | if (hso_dev->usb_gone) |
2241 | rv = 0; | 2185 | rv = 0; |
2242 | else | 2186 | else |
2243 | rv = usb_control_msg(hso_dev->usb, usb_rcvctrlpipe(hso_dev->usb, 0), | 2187 | rv = usb_control_msg(hso_dev->usb, usb_rcvctrlpipe(hso_dev->usb, 0), |
2244 | enabled ? 0x82 : 0x81, 0x40, 0, 0, NULL, 0, | 2188 | enabled ? 0x82 : 0x81, 0x40, 0, 0, NULL, 0, |
2245 | USB_CTRL_SET_TIMEOUT); | 2189 | USB_CTRL_SET_TIMEOUT); |
2246 | mutex_unlock(&hso_dev->mutex->mutex); | 2190 | mutex_unlock(&hso_dev->mutex); |
2247 | return rv; | 2191 | return rv; |
2248 | } | 2192 | } |
2249 | 2193 | ||
@@ -2851,8 +2795,6 @@ static void hso_free_interface(struct usb_interface *interface) | |||
2851 | { | 2795 | { |
2852 | struct hso_serial *hso_dev; | 2796 | struct hso_serial *hso_dev; |
2853 | int i; | 2797 | int i; |
2854 | struct mutex *hso_mutex = NULL; | ||
2855 | int refcnt = 1; | ||
2856 | 2798 | ||
2857 | for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { | 2799 | for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { |
2858 | if (serial_table[i] | 2800 | if (serial_table[i] |
@@ -2860,12 +2802,10 @@ static void hso_free_interface(struct usb_interface *interface) | |||
2860 | hso_dev = dev2ser(serial_table[i]); | 2802 | hso_dev = dev2ser(serial_table[i]); |
2861 | if (hso_dev->tty) | 2803 | if (hso_dev->tty) |
2862 | tty_hangup(hso_dev->tty); | 2804 | tty_hangup(hso_dev->tty); |
2863 | hso_mutex = &hso_dev->parent->mutex->mutex; | 2805 | mutex_lock(&hso_dev->parent->mutex); |
2864 | mutex_lock(hso_mutex); | ||
2865 | hso_dev->parent->usb_gone = 1; | 2806 | hso_dev->parent->usb_gone = 1; |
2866 | refcnt = kref_put(&serial_table[i]->ref, | 2807 | mutex_unlock(&hso_dev->parent->mutex); |
2867 | hso_serial_ref_free); | 2808 | kref_put(&serial_table[i]->ref, hso_serial_ref_free); |
2868 | mutex_unlock(hso_mutex); | ||
2869 | } | 2809 | } |
2870 | } | 2810 | } |
2871 | 2811 | ||
@@ -2884,9 +2824,6 @@ static void hso_free_interface(struct usb_interface *interface) | |||
2884 | hso_free_net_device(network_table[i]); | 2824 | hso_free_net_device(network_table[i]); |
2885 | } | 2825 | } |
2886 | } | 2826 | } |
2887 | if (refcnt == 0) | ||
2888 | hso_free_mutex(container_of(hso_mutex, | ||
2889 | struct hso_mutex_t, mutex)); | ||
2890 | } | 2827 | } |
2891 | 2828 | ||
2892 | /* Helper functions */ | 2829 | /* Helper functions */ |
@@ -2986,7 +2923,6 @@ static int __init hso_init(void) | |||
2986 | 2923 | ||
2987 | /* Initialise the serial table semaphore and table */ | 2924 | /* Initialise the serial table semaphore and table */ |
2988 | spin_lock_init(&serial_table_lock); | 2925 | spin_lock_init(&serial_table_lock); |
2989 | spin_lock_init(&hso_mutex_lock); | ||
2990 | for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) | 2926 | for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) |
2991 | serial_table[i] = NULL; | 2927 | serial_table[i] = NULL; |
2992 | 2928 | ||