From: Jeff Garzik The SCSI part of this change was ACK'd by James, and is needed anyway for anybody using the SCSI layer's ->eh_strategy_handler(). I was just the first to actually use ->eh_strategy_handler(), it looks like :) Long term probably better to kill ->eh_strategy_handler(), but I leave that up to James, Christoph, and the wiser heads of scsi land. [libata] Use scsi_finish_command as completion function, in our error handling thread callback. This also exports scsi_finish_command in the SCSI layer. Thanks much to James Bottomley and his patience, as this solution was figured out. --- drivers/scsi/libata-core.c | 8 ++++++++ drivers/scsi/scsi.c | 1 + drivers/scsi/scsi_priv.h | 1 - include/scsi/scsi_cmnd.h | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff -puN drivers/scsi/libata-core.c~libata-fix drivers/scsi/libata-core.c --- 25/drivers/scsi/libata-core.c~libata-fix 2004-02-28 16:55:51.000000000 -0800 +++ 25-akpm/drivers/scsi/libata-core.c 2004-02-28 16:55:51.000000000 -0800 @@ -2005,6 +2005,14 @@ void ata_eng_timeout(struct ata_port *ap goto out; } + /* hack alert! We cannot use the supplied completion + * function from inside the ->eh_strategy_handler() thread. + * libata is the only user of ->eh_strategy_handler() in + * any kernel, so the default scsi_done() assumes it is + * not being called from the SCSI EH. + */ + qc->scsidone = scsi_finish_command; + switch (qc->tf.protocol) { case ATA_PROT_DMA_READ: case ATA_PROT_DMA_WRITE: diff -puN drivers/scsi/scsi.c~libata-fix drivers/scsi/scsi.c --- 25/drivers/scsi/scsi.c~libata-fix 2004-02-28 16:55:51.000000000 -0800 +++ 25-akpm/drivers/scsi/scsi.c 2004-02-28 16:55:51.000000000 -0800 @@ -849,6 +849,7 @@ void scsi_finish_command(struct scsi_cmn cmd->done(cmd); } +EXPORT_SYMBOL(scsi_finish_command); /* * Function: scsi_adjust_queue_depth() diff -puN drivers/scsi/scsi_priv.h~libata-fix drivers/scsi/scsi_priv.h --- 25/drivers/scsi/scsi_priv.h~libata-fix 2004-02-28 16:55:51.000000000 -0800 +++ 25-akpm/drivers/scsi/scsi_priv.h 2004-02-28 16:55:51.000000000 -0800 @@ -77,7 +77,6 @@ extern int scsi_dispatch_cmd(struct scsi extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); extern void scsi_done(struct scsi_cmnd *cmd); -extern void scsi_finish_command(struct scsi_cmnd *cmd); extern int scsi_retry_command(struct scsi_cmnd *cmd); extern int scsi_insert_special_req(struct scsi_request *sreq, int); extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, diff -puN include/scsi/scsi_cmnd.h~libata-fix include/scsi/scsi_cmnd.h --- 25/include/scsi/scsi_cmnd.h~libata-fix 2004-02-28 16:55:51.000000000 -0800 +++ 25-akpm/include/scsi/scsi_cmnd.h 2004-02-28 16:55:51.000000000 -0800 @@ -159,5 +159,6 @@ struct scsi_cmnd { extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, int); extern void scsi_put_command(struct scsi_cmnd *); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int); +extern void scsi_finish_command(struct scsi_cmnd *cmd); #endif /* _SCSI_SCSI_CMND_H */ _