summaryrefslogtreecommitdiff
path: root/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
diff options
context:
space:
mode:
authorMichael Cyr <mikecyr@us.ibm.com>2016-10-13 19:02:40 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2016-11-09 01:29:54 +0300
commit8bf11557d44d00562360d370de8aa70ba89aa0d5 (patch)
tree1960c3aecb9f52c206c72c212659281fc4bf2fff /drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
parentc9b3379f60a83288a5e2f8ea75476460978689b0 (diff)
downloadlinux-8bf11557d44d00562360d370de8aa70ba89aa0d5.tar.xz
scsi: ibmvscsis: Synchronize cmds at remove time
This patch adds code to disconnect from the client, which will make sure any outstanding commands have been completed, before continuing on with the remove operation. Signed-off-by: Michael Cyr <mikecyr@us.ibm.com> Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com> Tested-by: Steven Royer <seroyer@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c')
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index 2ce1d73033b2..41af435a8943 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -469,6 +469,18 @@ static void ibmvscsis_disconnect(struct work_struct *work)
case WAIT_ENABLED:
switch (new_state) {
+ case UNCONFIGURING:
+ vscsi->state = new_state;
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ vscsi->flags &= ~(SCHEDULE_DISCONNECT |
+ DISCONNECT_SCHEDULED);
+ dma_rmb();
+ if (vscsi->flags & CFG_SLEEPING) {
+ vscsi->flags &= ~CFG_SLEEPING;
+ complete(&vscsi->unconfig);
+ }
+ break;
+
/* should never happen */
case ERR_DISCONNECT:
case ERR_DISCONNECT_RECONNECT:
@@ -481,6 +493,13 @@ static void ibmvscsis_disconnect(struct work_struct *work)
case WAIT_IDLE:
switch (new_state) {
+ case UNCONFIGURING:
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ vscsi->state = new_state;
+ vscsi->flags &= ~(SCHEDULE_DISCONNECT |
+ DISCONNECT_SCHEDULED);
+ ibmvscsis_free_command_q(vscsi);
+ break;
case ERR_DISCONNECT:
case ERR_DISCONNECT_RECONNECT:
vscsi->state = new_state;
@@ -1186,6 +1205,15 @@ static void ibmvscsis_adapter_idle(struct scsi_info *vscsi)
free_qs = true;
switch (vscsi->state) {
+ case UNCONFIGURING:
+ ibmvscsis_free_command_q(vscsi);
+ dma_rmb();
+ isync();
+ if (vscsi->flags & CFG_SLEEPING) {
+ vscsi->flags &= ~CFG_SLEEPING;
+ complete(&vscsi->unconfig);
+ }
+ break;
case ERR_DISCONNECT_RECONNECT:
ibmvscsis_reset_queue(vscsi);
pr_debug("adapter_idle, disc_rec: flags 0x%x\n", vscsi->flags);
@@ -3338,6 +3366,7 @@ static int ibmvscsis_probe(struct vio_dev *vdev,
(unsigned long)vscsi);
init_completion(&vscsi->wait_idle);
+ init_completion(&vscsi->unconfig);
snprintf(wq_name, 24, "ibmvscsis%s", dev_name(&vdev->dev));
vscsi->work_q = create_workqueue(wq_name);
@@ -3393,10 +3422,11 @@ static int ibmvscsis_remove(struct vio_dev *vdev)
pr_debug("remove (%s)\n", dev_name(&vscsi->dma_dev->dev));
- /*
- * TBD: Need to handle if there are commands on the waiting_rsp q
- * Actually, can there still be cmds outstanding to tcm?
- */
+ spin_lock_bh(&vscsi->intr_lock);
+ ibmvscsis_post_disconnect(vscsi, UNCONFIGURING, 0);
+ vscsi->flags |= CFG_SLEEPING;
+ spin_unlock_bh(&vscsi->intr_lock);
+ wait_for_completion(&vscsi->unconfig);
vio_disable_interrupts(vdev);
free_irq(vdev->irq, vscsi);
@@ -3405,7 +3435,6 @@ static int ibmvscsis_remove(struct vio_dev *vdev)
DMA_BIDIRECTIONAL);
kfree(vscsi->map_buf);
tasklet_kill(&vscsi->work_task);
- ibmvscsis_unregister_command_q(vscsi);
ibmvscsis_destroy_command_q(vscsi);
ibmvscsis_freetimer(vscsi);
ibmvscsis_free_cmds(vscsi);