|
@@ -364,10 +364,7 @@ static void release_controller(struct kref *kref)
|
|
struct rdac_controller *ctlr;
|
|
struct rdac_controller *ctlr;
|
|
ctlr = container_of(kref, struct rdac_controller, kref);
|
|
ctlr = container_of(kref, struct rdac_controller, kref);
|
|
|
|
|
|
- flush_workqueue(kmpath_rdacd);
|
|
|
|
- spin_lock(&list_lock);
|
|
|
|
list_del(&ctlr->node);
|
|
list_del(&ctlr->node);
|
|
- spin_unlock(&list_lock);
|
|
|
|
kfree(ctlr);
|
|
kfree(ctlr);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -376,20 +373,17 @@ static struct rdac_controller *get_controller(int index, char *array_name,
|
|
{
|
|
{
|
|
struct rdac_controller *ctlr, *tmp;
|
|
struct rdac_controller *ctlr, *tmp;
|
|
|
|
|
|
- spin_lock(&list_lock);
|
|
|
|
-
|
|
|
|
list_for_each_entry(tmp, &ctlr_list, node) {
|
|
list_for_each_entry(tmp, &ctlr_list, node) {
|
|
if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) &&
|
|
if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) &&
|
|
(tmp->index == index) &&
|
|
(tmp->index == index) &&
|
|
(tmp->host == sdev->host)) {
|
|
(tmp->host == sdev->host)) {
|
|
kref_get(&tmp->kref);
|
|
kref_get(&tmp->kref);
|
|
- spin_unlock(&list_lock);
|
|
|
|
return tmp;
|
|
return tmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC);
|
|
ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC);
|
|
if (!ctlr)
|
|
if (!ctlr)
|
|
- goto done;
|
|
|
|
|
|
+ return NULL;
|
|
|
|
|
|
/* initialize fields of controller */
|
|
/* initialize fields of controller */
|
|
memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN);
|
|
memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN);
|
|
@@ -405,8 +399,7 @@ static struct rdac_controller *get_controller(int index, char *array_name,
|
|
INIT_WORK(&ctlr->ms_work, send_mode_select);
|
|
INIT_WORK(&ctlr->ms_work, send_mode_select);
|
|
INIT_LIST_HEAD(&ctlr->ms_head);
|
|
INIT_LIST_HEAD(&ctlr->ms_head);
|
|
list_add(&ctlr->node, &ctlr_list);
|
|
list_add(&ctlr->node, &ctlr_list);
|
|
-done:
|
|
|
|
- spin_unlock(&list_lock);
|
|
|
|
|
|
+
|
|
return ctlr;
|
|
return ctlr;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -517,9 +510,12 @@ static int initialize_controller(struct scsi_device *sdev,
|
|
index = 0;
|
|
index = 0;
|
|
else
|
|
else
|
|
index = 1;
|
|
index = 1;
|
|
|
|
+
|
|
|
|
+ spin_lock(&list_lock);
|
|
h->ctlr = get_controller(index, array_name, array_id, sdev);
|
|
h->ctlr = get_controller(index, array_name, array_id, sdev);
|
|
if (!h->ctlr)
|
|
if (!h->ctlr)
|
|
err = SCSI_DH_RES_TEMP_UNAVAIL;
|
|
err = SCSI_DH_RES_TEMP_UNAVAIL;
|
|
|
|
+ spin_unlock(&list_lock);
|
|
}
|
|
}
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
@@ -906,7 +902,9 @@ static int rdac_bus_attach(struct scsi_device *sdev)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
clean_ctlr:
|
|
clean_ctlr:
|
|
|
|
+ spin_lock(&list_lock);
|
|
kref_put(&h->ctlr->kref, release_controller);
|
|
kref_put(&h->ctlr->kref, release_controller);
|
|
|
|
+ spin_unlock(&list_lock);
|
|
|
|
|
|
failed:
|
|
failed:
|
|
kfree(scsi_dh_data);
|
|
kfree(scsi_dh_data);
|
|
@@ -921,14 +919,19 @@ static void rdac_bus_detach( struct scsi_device *sdev )
|
|
struct rdac_dh_data *h;
|
|
struct rdac_dh_data *h;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
- spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
|
|
|
|
scsi_dh_data = sdev->scsi_dh_data;
|
|
scsi_dh_data = sdev->scsi_dh_data;
|
|
|
|
+ h = (struct rdac_dh_data *) scsi_dh_data->buf;
|
|
|
|
+ if (h->ctlr && h->ctlr->ms_queued)
|
|
|
|
+ flush_workqueue(kmpath_rdacd);
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
|
|
sdev->scsi_dh_data = NULL;
|
|
sdev->scsi_dh_data = NULL;
|
|
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
|
|
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
|
|
|
|
|
|
- h = (struct rdac_dh_data *) scsi_dh_data->buf;
|
|
|
|
|
|
+ spin_lock(&list_lock);
|
|
if (h->ctlr)
|
|
if (h->ctlr)
|
|
kref_put(&h->ctlr->kref, release_controller);
|
|
kref_put(&h->ctlr->kref, release_controller);
|
|
|
|
+ spin_unlock(&list_lock);
|
|
kfree(scsi_dh_data);
|
|
kfree(scsi_dh_data);
|
|
module_put(THIS_MODULE);
|
|
module_put(THIS_MODULE);
|
|
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
|
|
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
|