aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/ds.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-15 19:34:06 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-02-17 11:48:18 -0500
commite6e4f397e5d0970ee1bb7a5591ac93b37cfa524a (patch)
tree8e20dc8b8281ee4a6e7782554825212d93983de7 /drivers/pcmcia/ds.c
parent64d8d46f5f501a19aec4db7ff93faf1b831d05ed (diff)
pcmcia: protect s->device_count
Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia/ds.c')
-rw-r--r--drivers/pcmcia/ds.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 4f7308df22c8..bcb9ef103427 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -265,6 +265,7 @@ static int pcmcia_device_probe(struct device *dev)
265 struct pcmcia_device_id *did; 265 struct pcmcia_device_id *did;
266 struct pcmcia_socket *s; 266 struct pcmcia_socket *s;
267 cistpl_config_t cis_config; 267 cistpl_config_t cis_config;
268 unsigned long flags;
268 int ret = 0; 269 int ret = 0;
269 270
270 dev = get_device(dev); 271 dev = get_device(dev);
@@ -315,9 +316,11 @@ static int pcmcia_device_probe(struct device *dev)
315 goto put_module; 316 goto put_module;
316 } 317 }
317 318
319 spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
318 if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && 320 if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
319 (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) 321 (p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
320 pcmcia_add_device_later(p_dev->socket, 0); 322 pcmcia_add_device_later(p_dev->socket, 0);
323 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
321 324
322put_module: 325put_module:
323 if (ret) 326 if (ret)
@@ -342,10 +345,12 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
342 "pcmcia_card_remove(%d) %s\n", s->sock, 345 "pcmcia_card_remove(%d) %s\n", s->sock,
343 leftover ? leftover->devname : ""); 346 leftover ? leftover->devname : "");
344 347
348 spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
345 if (!leftover) 349 if (!leftover)
346 s->device_count = 0; 350 s->device_count = 0;
347 else 351 else
348 s->device_count = 1; 352 s->device_count = 1;
353 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
349 354
350 /* unregister all pcmcia_devices registered with this socket, except leftover */ 355 /* unregister all pcmcia_devices registered with this socket, except leftover */
351 list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) { 356 list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) {
@@ -382,7 +387,7 @@ static int pcmcia_device_remove(struct device *dev)
382 */ 387 */
383 did = dev_get_drvdata(&p_dev->dev); 388 did = dev_get_drvdata(&p_dev->dev);
384 if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && 389 if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
385 (p_dev->socket->device_count != 0) && 390 (p_dev->socket->device_count > 0) &&
386 (p_dev->device_no == 0)) 391 (p_dev->device_no == 0))
387 pcmcia_card_remove(p_dev->socket, p_dev); 392 pcmcia_card_remove(p_dev->socket, p_dev);
388 393
@@ -512,16 +517,19 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu
512 517
513 pr_debug("adding device to %d, function %d\n", s->sock, function); 518 pr_debug("adding device to %d, function %d\n", s->sock, function);
514 519
515 /* max of 4 devices per card */
516 if (s->device_count == 4)
517 goto err_put;
518
519 p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL); 520 p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
520 if (!p_dev) 521 if (!p_dev)
521 goto err_put; 522 goto err_put;
522 523
523 p_dev->socket = s; 524 spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
524 p_dev->device_no = (s->device_count++); 525 p_dev->device_no = (s->device_count++);
526 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
527
528 /* max of 4 devices per card */
529 if (p_dev->device_no >= 4)
530 goto err_free;
531
532 p_dev->socket = s;
525 p_dev->func = function; 533 p_dev->func = function;
526 534
527 p_dev->dev.bus = &pcmcia_bus_type; 535 p_dev->dev.bus = &pcmcia_bus_type;
@@ -586,9 +594,12 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu
586 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); 594 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
587 595
588 err_free: 596 err_free:
597 spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
598 s->device_count--;
599 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
600
589 kfree(p_dev->devname); 601 kfree(p_dev->devname);
590 kfree(p_dev); 602 kfree(p_dev);
591 s->device_count--;
592 err_put: 603 err_put:
593 mutex_unlock(&device_add_lock); 604 mutex_unlock(&device_add_lock);
594 pcmcia_put_socket(s); 605 pcmcia_put_socket(s);