diff options
| -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 53a31c753cb1..20c4557f5abd 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); |
