diff options
Diffstat (limited to 'drivers/scsi/device_handler/scsi_dh_rdac.c')
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_rdac.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 53a31c753cb..20c4557f5ab 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
@@ -364,10 +364,7 @@ static void release_controller(struct kref *kref) | |||
364 | struct rdac_controller *ctlr; | 364 | struct rdac_controller *ctlr; |
365 | ctlr = container_of(kref, struct rdac_controller, kref); | 365 | ctlr = container_of(kref, struct rdac_controller, kref); |
366 | 366 | ||
367 | flush_workqueue(kmpath_rdacd); | ||
368 | spin_lock(&list_lock); | ||
369 | list_del(&ctlr->node); | 367 | list_del(&ctlr->node); |
370 | spin_unlock(&list_lock); | ||
371 | kfree(ctlr); | 368 | kfree(ctlr); |
372 | } | 369 | } |
373 | 370 | ||
@@ -376,20 +373,17 @@ static struct rdac_controller *get_controller(int index, char *array_name, | |||
376 | { | 373 | { |
377 | struct rdac_controller *ctlr, *tmp; | 374 | struct rdac_controller *ctlr, *tmp; |
378 | 375 | ||
379 | spin_lock(&list_lock); | ||
380 | |||
381 | list_for_each_entry(tmp, &ctlr_list, node) { | 376 | list_for_each_entry(tmp, &ctlr_list, node) { |
382 | if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) && | 377 | if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) && |
383 | (tmp->index == index) && | 378 | (tmp->index == index) && |
384 | (tmp->host == sdev->host)) { | 379 | (tmp->host == sdev->host)) { |
385 | kref_get(&tmp->kref); | 380 | kref_get(&tmp->kref); |
386 | spin_unlock(&list_lock); | ||
387 | return tmp; | 381 | return tmp; |
388 | } | 382 | } |
389 | } | 383 | } |
390 | ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC); | 384 | ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC); |
391 | if (!ctlr) | 385 | if (!ctlr) |
392 | goto done; | 386 | return NULL; |
393 | 387 | ||
394 | /* initialize fields of controller */ | 388 | /* initialize fields of controller */ |
395 | memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN); | 389 | memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN); |
@@ -405,8 +399,7 @@ static struct rdac_controller *get_controller(int index, char *array_name, | |||
405 | INIT_WORK(&ctlr->ms_work, send_mode_select); | 399 | INIT_WORK(&ctlr->ms_work, send_mode_select); |
406 | INIT_LIST_HEAD(&ctlr->ms_head); | 400 | INIT_LIST_HEAD(&ctlr->ms_head); |
407 | list_add(&ctlr->node, &ctlr_list); | 401 | list_add(&ctlr->node, &ctlr_list); |
408 | done: | 402 | |
409 | spin_unlock(&list_lock); | ||
410 | return ctlr; | 403 | return ctlr; |
411 | } | 404 | } |
412 | 405 | ||
@@ -517,9 +510,12 @@ static int initialize_controller(struct scsi_device *sdev, | |||
517 | index = 0; | 510 | index = 0; |
518 | else | 511 | else |
519 | index = 1; | 512 | index = 1; |
513 | |||
514 | spin_lock(&list_lock); | ||
520 | h->ctlr = get_controller(index, array_name, array_id, sdev); | 515 | h->ctlr = get_controller(index, array_name, array_id, sdev); |
521 | if (!h->ctlr) | 516 | if (!h->ctlr) |
522 | err = SCSI_DH_RES_TEMP_UNAVAIL; | 517 | err = SCSI_DH_RES_TEMP_UNAVAIL; |
518 | spin_unlock(&list_lock); | ||
523 | } | 519 | } |
524 | return err; | 520 | return err; |
525 | } | 521 | } |
@@ -906,7 +902,9 @@ static int rdac_bus_attach(struct scsi_device *sdev) | |||
906 | return 0; | 902 | return 0; |
907 | 903 | ||
908 | clean_ctlr: | 904 | clean_ctlr: |
905 | spin_lock(&list_lock); | ||
909 | kref_put(&h->ctlr->kref, release_controller); | 906 | kref_put(&h->ctlr->kref, release_controller); |
907 | spin_unlock(&list_lock); | ||
910 | 908 | ||
911 | failed: | 909 | failed: |
912 | kfree(scsi_dh_data); | 910 | kfree(scsi_dh_data); |
@@ -921,14 +919,19 @@ static void rdac_bus_detach( struct scsi_device *sdev ) | |||
921 | struct rdac_dh_data *h; | 919 | struct rdac_dh_data *h; |
922 | unsigned long flags; | 920 | unsigned long flags; |
923 | 921 | ||
924 | spin_lock_irqsave(sdev->request_queue->queue_lock, flags); | ||
925 | scsi_dh_data = sdev->scsi_dh_data; | 922 | scsi_dh_data = sdev->scsi_dh_data; |
923 | h = (struct rdac_dh_data *) scsi_dh_data->buf; | ||
924 | if (h->ctlr && h->ctlr->ms_queued) | ||
925 | flush_workqueue(kmpath_rdacd); | ||
926 | |||
927 | spin_lock_irqsave(sdev->request_queue->queue_lock, flags); | ||
926 | sdev->scsi_dh_data = NULL; | 928 | sdev->scsi_dh_data = NULL; |
927 | spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); | 929 | spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); |
928 | 930 | ||
929 | h = (struct rdac_dh_data *) scsi_dh_data->buf; | 931 | spin_lock(&list_lock); |
930 | if (h->ctlr) | 932 | if (h->ctlr) |
931 | kref_put(&h->ctlr->kref, release_controller); | 933 | kref_put(&h->ctlr->kref, release_controller); |
934 | spin_unlock(&list_lock); | ||
932 | kfree(scsi_dh_data); | 935 | kfree(scsi_dh_data); |
933 | module_put(THIS_MODULE); | 936 | module_put(THIS_MODULE); |
934 | sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME); | 937 | sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME); |