>From 2d0851bea02e3d15bf403e6800cc7164f2e211f2 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 12 Jul 2013 12:06:19 +0200 Subject: [PATCH] scsi: use delayed_work to trigger aborts Command aborts are invoked from an interrupt, so we cannot use cancel_work_sync() when an outstanding abort needs to be cancelled. So convert the mechanism to delayed_work, which can be cancelled even from an interrupt context. Signed-off-by: Hannes Reinecke diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a62ae84..13a3418 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -297,7 +297,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) cmd->device = dev; INIT_LIST_HEAD(&cmd->list); - INIT_WORK(&cmd->abort_work, scmd_eh_abort_handler); + INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler); spin_lock_irqsave(&dev->list_lock, flags); list_add_tail(&cmd->list, &dev->cmd_list); spin_unlock_irqrestore(&dev->list_lock, flags); @@ -354,6 +354,8 @@ void scsi_put_command(struct scsi_cmnd *cmd) list_del_init(&cmd->list); spin_unlock_irqrestore(&cmd->device->list_lock, flags); + cancel_delayed_work_sync(&cmd->abort_work); + __scsi_put_command(cmd->device->host, cmd, &sdev->sdev_gendev); } EXPORT_SYMBOL(scsi_put_command); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 28c272f..cd443b2 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -187,7 +187,7 @@ void scmd_eh_abort_handler(struct work_struct *work) { struct scsi_cmnd *scmd = - container_of(work, struct scsi_cmnd, abort_work); + container_of(work, struct scsi_cmnd, abort_work.work); struct scsi_device *sdev = scmd->device; unsigned long flags; int rtn; @@ -254,7 +254,7 @@ scsi_abort_command(struct scsi_cmnd *scmd) SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, "scmd %p abort timeout\n", scmd)); - cancel_work_sync(&scmd->abort_work); + cancel_delayed_work(&scmd->abort_work); return BLK_EH_NOT_HANDLED; } @@ -279,7 +279,7 @@ scsi_abort_command(struct scsi_cmnd *scmd) SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, "scmd %p abort scheduled\n", scmd)); - schedule_work(&scmd->abort_work); + schedule_delayed_work(&scmd->abort_work, HZ / 100); return BLK_EH_SCHEDULED; } EXPORT_SYMBOL_GPL(scsi_abort_command); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index a2f062e..e3137e3 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -55,7 +55,7 @@ struct scsi_cmnd { struct scsi_device *device; struct list_head list; /* scsi_cmnd participates in queue lists */ struct list_head eh_entry; /* entry for the host eh_cmd_q */ - struct work_struct abort_work; + struct delayed_work abort_work; int eh_eflags; /* Used by error handlr */ /*