aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-11-25 06:52:46 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-25 06:52:46 -0500
commitab153d84d9609b4e6f53632a6f14b882e866cb47 (patch)
tree690aacae988039390c8d29d50ed5c3e62569e925
parentcd90ee1799136bd74158b734cf71b72609244a91 (diff)
Revert "hso: Fix free of mutexes still in use."
This reverts commit 52429eb216385fdc6969c0112ba8b46cffefaaef. On request from Alan Cox. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/usb/hso.c110
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
233struct hso_mutex_t {
234 struct mutex mutex;
235 u8 allocated;
236};
237
238struct hso_device { 233struct 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];
369static spinlock_t serial_table_lock; 364static spinlock_t serial_table_lock;
370static struct ktermios *hso_serial_termios[HSO_SERIAL_TTY_MINORS]; 365static struct ktermios *hso_serial_termios[HSO_SERIAL_TTY_MINORS];
371static struct ktermios *hso_serial_termios_locked[HSO_SERIAL_TTY_MINORS]; 366static 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)
377static struct hso_mutex_t hso_mutex_table[HSO_NUM_MUTEXES];
378static spinlock_t hso_mutex_lock;
379 367
380static const s32 default_port_spec[] = { 368static 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
620static 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
640static 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 */
648static void log_usb_status(int status, const char *function) 608static void log_usb_status(int status, const char *function)
649{ 609{
@@ -1265,9 +1225,7 @@ void hso_unthrottle_workfunc(struct work_struct *work)
1265static int hso_serial_open(struct tty_struct *tty, struct file *filp) 1225static 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);
1321err_out: 1279err_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