|
@@ -3335,6 +3335,65 @@ static void ipr_release_dump(struct kref *kref)
|
|
|
LEAVE;
|
|
|
}
|
|
|
|
|
|
+static void ipr_add_remove_thread(struct work_struct *work)
|
|
|
+{
|
|
|
+ unsigned long lock_flags;
|
|
|
+ struct ipr_resource_entry *res;
|
|
|
+ struct scsi_device *sdev;
|
|
|
+ struct ipr_ioa_cfg *ioa_cfg =
|
|
|
+ container_of(work, struct ipr_ioa_cfg, scsi_add_work_q);
|
|
|
+ u8 bus, target, lun;
|
|
|
+ int did_work;
|
|
|
+
|
|
|
+ ENTER;
|
|
|
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
|
|
+
|
|
|
+restart:
|
|
|
+ do {
|
|
|
+ did_work = 0;
|
|
|
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
|
|
|
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
|
|
|
+ if (res->del_from_ml && res->sdev) {
|
|
|
+ did_work = 1;
|
|
|
+ sdev = res->sdev;
|
|
|
+ if (!scsi_device_get(sdev)) {
|
|
|
+ if (!res->add_to_ml)
|
|
|
+ list_move_tail(&res->queue, &ioa_cfg->free_res_q);
|
|
|
+ else
|
|
|
+ res->del_from_ml = 0;
|
|
|
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
|
|
+ scsi_remove_device(sdev);
|
|
|
+ scsi_device_put(sdev);
|
|
|
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } while (did_work);
|
|
|
+
|
|
|
+ list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
|
|
|
+ if (res->add_to_ml) {
|
|
|
+ bus = res->bus;
|
|
|
+ target = res->target;
|
|
|
+ lun = res->lun;
|
|
|
+ res->add_to_ml = 0;
|
|
|
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
|
|
+ scsi_add_device(ioa_cfg->host, bus, target, lun);
|
|
|
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
|
|
+ goto restart;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ioa_cfg->scan_done = 1;
|
|
|
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
|
|
+ kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
|
|
|
+ LEAVE;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ipr_worker_thread - Worker thread
|
|
|
* @work: ioa config struct
|
|
@@ -3349,13 +3408,9 @@ static void ipr_release_dump(struct kref *kref)
|
|
|
static void ipr_worker_thread(struct work_struct *work)
|
|
|
{
|
|
|
unsigned long lock_flags;
|
|
|
- struct ipr_resource_entry *res;
|
|
|
- struct scsi_device *sdev;
|
|
|
struct ipr_dump *dump;
|
|
|
struct ipr_ioa_cfg *ioa_cfg =
|
|
|
container_of(work, struct ipr_ioa_cfg, work_q);
|
|
|
- u8 bus, target, lun;
|
|
|
- int did_work;
|
|
|
|
|
|
ENTER;
|
|
|
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
|
@@ -3393,49 +3448,9 @@ static void ipr_worker_thread(struct work_struct *work)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-restart:
|
|
|
- do {
|
|
|
- did_work = 0;
|
|
|
- if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
|
|
|
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
|
|
- return;
|
|
|
- }
|
|
|
+ schedule_work(&ioa_cfg->scsi_add_work_q);
|
|
|
|
|
|
- list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
|
|
|
- if (res->del_from_ml && res->sdev) {
|
|
|
- did_work = 1;
|
|
|
- sdev = res->sdev;
|
|
|
- if (!scsi_device_get(sdev)) {
|
|
|
- if (!res->add_to_ml)
|
|
|
- list_move_tail(&res->queue, &ioa_cfg->free_res_q);
|
|
|
- else
|
|
|
- res->del_from_ml = 0;
|
|
|
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
|
|
- scsi_remove_device(sdev);
|
|
|
- scsi_device_put(sdev);
|
|
|
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- } while (did_work);
|
|
|
-
|
|
|
- list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
|
|
|
- if (res->add_to_ml) {
|
|
|
- bus = res->bus;
|
|
|
- target = res->target;
|
|
|
- lun = res->lun;
|
|
|
- res->add_to_ml = 0;
|
|
|
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
|
|
- scsi_add_device(ioa_cfg->host, bus, target, lun);
|
|
|
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
|
|
- goto restart;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ioa_cfg->scan_done = 1;
|
|
|
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
|
|
- kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
|
|
|
LEAVE;
|
|
|
}
|
|
|
|
|
@@ -9933,6 +9948,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
|
|
|
INIT_LIST_HEAD(&ioa_cfg->free_res_q);
|
|
|
INIT_LIST_HEAD(&ioa_cfg->used_res_q);
|
|
|
INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread);
|
|
|
+ INIT_WORK(&ioa_cfg->scsi_add_work_q, ipr_add_remove_thread);
|
|
|
init_waitqueue_head(&ioa_cfg->reset_wait_q);
|
|
|
init_waitqueue_head(&ioa_cfg->msi_wait_q);
|
|
|
init_waitqueue_head(&ioa_cfg->eeh_wait_q);
|