Commit f02103cc authored by Justin T. Gibbs's avatar Justin T. Gibbs

Aic7xxx and Aic79xx driver updates

 o Remove extra complexity and code duplication in processing
   the completeq now that the completeq can be run while holding
   both the ah?_lock and the done_lock.
parent 57af4d8f
/* /*
* Adaptec AIC79xx device driver for Linux. * Adaptec AIC79xx device driver for Linux.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#149 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#150 $
* *
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs. * Copyright (c) 1994-2000 Justin T. Gibbs.
...@@ -557,16 +557,14 @@ static void ahd_runq_tasklet(unsigned long data); ...@@ -557,16 +557,14 @@ static void ahd_runq_tasklet(unsigned long data);
static int aic79xx_setup(char *c); static int aic79xx_setup(char *c);
/****************************** Inlines ***************************************/ /****************************** Inlines ***************************************/
static __inline void ahd_schedule_completeq(struct ahd_softc *ahd, static __inline void ahd_schedule_completeq(struct ahd_softc *ahd);
struct ahd_cmd *acmd);
static __inline void ahd_schedule_runq(struct ahd_softc *ahd); static __inline void ahd_schedule_runq(struct ahd_softc *ahd);
static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd); static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd);
static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd); static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd);
static __inline struct ahd_linux_device* static __inline struct ahd_linux_device*
ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, ahd_linux_get_device(struct ahd_softc *ahd, u_int channel,
u_int target, u_int lun, int alloc); u_int target, u_int lun, int alloc);
static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd, static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd);
struct ahd_cmd *acmd);
static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd, static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd,
struct ahd_linux_device *dev); struct ahd_linux_device *dev);
static __inline struct ahd_linux_device * static __inline struct ahd_linux_device *
...@@ -579,26 +577,8 @@ static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, ...@@ -579,26 +577,8 @@ static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb,
bus_addr_t addr, bus_size_t len); bus_addr_t addr, bus_size_t len);
static __inline void static __inline void
ahd_schedule_completeq(struct ahd_softc *ahd, struct ahd_cmd *acmd) ahd_schedule_completeq(struct ahd_softc *ahd)
{ {
while (acmd != NULL) {
struct ahd_completeq *completeq;
struct ahd_cmd *list_cmd;
struct ahd_cmd *next_cmd;
next_cmd = TAILQ_NEXT(acmd, acmd_links.tqe);
completeq = &ahd->platform_data->completeq;
list_cmd = TAILQ_FIRST(completeq);
while (list_cmd != NULL
&& acmd_scsi_cmd(list_cmd).serial_number
< acmd_scsi_cmd(acmd).serial_number)
list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
if (list_cmd != NULL)
TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
else
TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
acmd = next_cmd;
}
if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) { if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) {
ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER; ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER;
ahd->platform_data->completeq_timer.expires = jiffies; ahd->platform_data->completeq_timer.expires = jiffies;
...@@ -667,25 +647,17 @@ ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target, ...@@ -667,25 +647,17 @@ ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target,
#define AHD_LINUX_MAX_RETURNED_ERRORS 4 #define AHD_LINUX_MAX_RETURNED_ERRORS 4
static struct ahd_cmd * static struct ahd_cmd *
ahd_linux_run_complete_queue(struct ahd_softc *ahd, struct ahd_cmd *acmd) ahd_linux_run_complete_queue(struct ahd_softc *ahd)
{ {
struct ahd_cmd *acmd;
u_long done_flags; u_long done_flags;
int with_errors; int with_errors;
with_errors = 0; with_errors = 0;
ahd_done_lock(ahd, &done_flags); ahd_done_lock(ahd, &done_flags);
while (acmd != NULL) { while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) {
Scsi_Cmnd *cmd; Scsi_Cmnd *cmd;
cmd = &acmd_scsi_cmd(acmd);
acmd = TAILQ_NEXT(acmd, acmd_links.tqe);
cmd->host_scribble = NULL;
if (ahd_cmd_get_transaction_status(cmd) != DID_OK
|| (cmd->result & 0xFF) != SCSI_STATUS_OK)
with_errors++;
cmd->scsi_done(cmd);
if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) { if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) {
/* /*
* Linux uses stack recursion to requeue * Linux uses stack recursion to requeue
...@@ -695,8 +667,20 @@ ahd_linux_run_complete_queue(struct ahd_softc *ahd, struct ahd_cmd *acmd) ...@@ -695,8 +667,20 @@ ahd_linux_run_complete_queue(struct ahd_softc *ahd, struct ahd_cmd *acmd)
* the operating system in case they are going * the operating system in case they are going
* to be retried. "ick" * to be retried. "ick"
*/ */
ahd_schedule_completeq(ahd);
break; break;
} }
TAILQ_REMOVE(&ahd->platform_data->completeq,
acmd, acmd_links.tqe);
cmd = &acmd_scsi_cmd(acmd);
acmd = TAILQ_NEXT(acmd, acmd_links.tqe);
cmd->host_scribble = NULL;
if (ahd_cmd_get_transaction_status(cmd) != DID_OK
|| (cmd->result & 0xFF) != SCSI_STATUS_OK)
with_errors++;
cmd->scsi_done(cmd);
} }
ahd_done_unlock(ahd, &done_flags); ahd_done_unlock(ahd, &done_flags);
return (acmd); return (acmd);
...@@ -1061,7 +1045,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) ...@@ -1061,7 +1045,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
ahd_linux_queue_cmd_complete(ahd, cmd); ahd_linux_queue_cmd_complete(ahd, cmd);
ahd_schedule_completeq(ahd, NULL); ahd_schedule_completeq(ahd);
ahd_midlayer_entrypoint_unlock(ahd, &flags); ahd_midlayer_entrypoint_unlock(ahd, &flags);
return (0); return (0);
} }
...@@ -1071,7 +1055,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) ...@@ -1071,7 +1055,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
if (dev == NULL) { if (dev == NULL) {
ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
ahd_linux_queue_cmd_complete(ahd, cmd); ahd_linux_queue_cmd_complete(ahd, cmd);
ahd_schedule_completeq(ahd, NULL); ahd_schedule_completeq(ahd);
ahd_midlayer_entrypoint_unlock(ahd, &flags); ahd_midlayer_entrypoint_unlock(ahd, &flags);
printf("%s: aic79xx_linux_queue - Unable to allocate device!\n", printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
ahd_name(ahd)); ahd_name(ahd));
...@@ -1569,14 +1553,8 @@ ahd_linux_abort(Scsi_Cmnd *cmd) ...@@ -1569,14 +1553,8 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
} }
spin_lock_irq(&ahd->platform_data->spin_lock); spin_lock_irq(&ahd->platform_data->spin_lock);
} }
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
ahd_schedule_runq(ahd); ahd_schedule_runq(ahd);
if (acmd != NULL) { ahd_linux_run_complete_queue(ahd);
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL)
ahd_schedule_completeq(ahd, acmd);
}
ahd_midlayer_entrypoint_unlock(ahd, &s); ahd_midlayer_entrypoint_unlock(ahd, &s);
return (retval); return (retval);
} }
...@@ -1601,7 +1579,6 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) ...@@ -1601,7 +1579,6 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
struct ahd_tmode_tstate *tstate; struct ahd_tmode_tstate *tstate;
struct scb *scb; struct scb *scb;
struct hardware_scb *hscb; struct hardware_scb *hscb;
struct ahd_cmd *acmd;
u_long s; u_long s;
struct timer_list timer; struct timer_list timer;
int retval; int retval;
...@@ -1672,14 +1649,8 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) ...@@ -1672,14 +1649,8 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
retval = FAILED; retval = FAILED;
} }
spin_lock_irq(&ahd->platform_data->spin_lock); spin_lock_irq(&ahd->platform_data->spin_lock);
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
ahd_schedule_runq(ahd); ahd_schedule_runq(ahd);
if (acmd != NULL) { ahd_linux_run_complete_queue(ahd);
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL)
ahd_schedule_completeq(ahd, acmd);
}
ahd_midlayer_entrypoint_unlock(ahd, &s); ahd_midlayer_entrypoint_unlock(ahd, &s);
printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
return (retval); return (retval);
...@@ -1692,7 +1663,6 @@ static int ...@@ -1692,7 +1663,6 @@ static int
ahd_linux_bus_reset(Scsi_Cmnd *cmd) ahd_linux_bus_reset(Scsi_Cmnd *cmd)
{ {
struct ahd_softc *ahd; struct ahd_softc *ahd;
struct ahd_cmd *acmd;
u_long s; u_long s;
int found; int found;
...@@ -1705,14 +1675,7 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) ...@@ -1705,14 +1675,7 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
ahd_midlayer_entrypoint_lock(ahd, &s); ahd_midlayer_entrypoint_lock(ahd, &s);
found = ahd_reset_channel(ahd, cmd->device->channel + 'A', found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
/*initiate reset*/TRUE); /*initiate reset*/TRUE);
acmd = TAILQ_FIRST(&ahd->platform_data->completeq); ahd_linux_run_complete_queue(ahd);
TAILQ_INIT(&ahd->platform_data->completeq);
if (acmd != NULL) {
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL)
ahd_schedule_completeq(ahd, acmd);
}
ahd_midlayer_entrypoint_unlock(ahd, &s); ahd_midlayer_entrypoint_unlock(ahd, &s);
if (bootverbose) if (bootverbose)
...@@ -2605,19 +2568,12 @@ ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel, ...@@ -2605,19 +2568,12 @@ ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
static void static void
ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd) ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd)
{ {
struct ahd_cmd *acmd;
u_long flags; u_long flags;
ahd_lock(ahd, &flags); ahd_lock(ahd, &flags);
del_timer(&ahd->platform_data->completeq_timer); del_timer(&ahd->platform_data->completeq_timer);
ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER; ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER;
acmd = TAILQ_FIRST(&ahd->platform_data->completeq); ahd_linux_run_complete_queue(ahd);
TAILQ_INIT(&ahd->platform_data->completeq);
if (acmd != NULL) {
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL)
ahd_schedule_completeq(ahd, acmd);
}
ahd_unlock(ahd, &flags); ahd_unlock(ahd, &flags);
} }
...@@ -3823,7 +3779,6 @@ static void ...@@ -3823,7 +3779,6 @@ static void
ahd_linux_dv_timeout(struct scsi_cmnd *cmd) ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
{ {
struct ahd_softc *ahd; struct ahd_softc *ahd;
struct ahd_cmd *acmd;
struct scb *scb; struct scb *scb;
u_long flags; u_long flags;
...@@ -3870,16 +3825,9 @@ ahd_linux_dv_timeout(struct scsi_cmnd *cmd) ...@@ -3870,16 +3825,9 @@ ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
ahd->platform_data->reset_timer.function = ahd->platform_data->reset_timer.function =
(ahd_linux_callback_t *)ahd_release_simq; (ahd_linux_callback_t *)ahd_release_simq;
add_timer(&ahd->platform_data->reset_timer); add_timer(&ahd->platform_data->reset_timer);
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
if (ahd_linux_next_device_to_run(ahd) != NULL) if (ahd_linux_next_device_to_run(ahd) != NULL)
ahd_schedule_runq(ahd); ahd_schedule_runq(ahd);
if (acmd != NULL) { ahd_linux_run_complete_queue(ahd);
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL) {
ahd_schedule_completeq(ahd, acmd);
}
}
ahd_unlock(ahd, &flags); ahd_unlock(ahd, &flags);
} }
...@@ -4268,34 +4216,23 @@ void ...@@ -4268,34 +4216,23 @@ void
ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs) ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
{ {
struct ahd_softc *ahd; struct ahd_softc *ahd;
struct ahd_cmd *acmd;
u_long flags; u_long flags;
ahd = (struct ahd_softc *) dev_id; ahd = (struct ahd_softc *) dev_id;
ahd_lock(ahd, &flags); ahd_lock(ahd, &flags);
ahd_intr(ahd); ahd_intr(ahd);
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
if (ahd_linux_next_device_to_run(ahd) != NULL) if (ahd_linux_next_device_to_run(ahd) != NULL)
ahd_schedule_runq(ahd); ahd_schedule_runq(ahd);
if (acmd != NULL) { ahd_linux_run_complete_queue(ahd);
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL) {
ahd_schedule_completeq(ahd, acmd);
}
}
ahd_unlock(ahd, &flags); ahd_unlock(ahd, &flags);
} }
void void
ahd_platform_flushwork(struct ahd_softc *ahd) ahd_platform_flushwork(struct ahd_softc *ahd)
{ {
struct ahd_cmd *acmd;
acmd = TAILQ_FIRST(&ahd->platform_data->completeq); while (ahd_linux_run_complete_queue(ahd) != 0)
TAILQ_INIT(&ahd->platform_data->completeq); ;
while (acmd != NULL)
acmd = ahd_linux_run_complete_queue(ahd, acmd);
} }
static struct ahd_linux_target* static struct ahd_linux_target*
......
/* /*
* Adaptec AIC7xxx device driver for Linux. * Adaptec AIC7xxx device driver for Linux.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#212 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#213 $
* *
* Copyright (c) 1994 John Aycock * Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science. * The University of Calgary Department of Computer Science.
...@@ -571,16 +571,14 @@ static aic_option_callback_t ahc_linux_setup_dv; ...@@ -571,16 +571,14 @@ static aic_option_callback_t ahc_linux_setup_dv;
static int aic7xxx_setup(char *s); static int aic7xxx_setup(char *s);
static int ahc_linux_next_unit(void); static int ahc_linux_next_unit(void);
static void ahc_runq_tasklet(unsigned long data); static void ahc_runq_tasklet(unsigned long data);
static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf); static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
static void ahc_schedule_completeq(struct ahc_softc *ahc, struct ahc_cmd *acmd);
/********************************* Inlines ************************************/ /********************************* Inlines ************************************/
static __inline void ahc_schedule_runq(struct ahc_softc *ahc); static __inline void ahc_schedule_runq(struct ahc_softc *ahc);
static __inline struct ahc_linux_device* static __inline struct ahc_linux_device*
ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,
u_int target, u_int lun, int alloc); u_int target, u_int lun, int alloc);
static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc, static __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
struct ahc_cmd *acmd);
static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc, static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc,
struct ahc_linux_device *dev); struct ahc_linux_device *dev);
static __inline struct ahc_linux_device * static __inline struct ahc_linux_device *
...@@ -592,27 +590,9 @@ static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, ...@@ -592,27 +590,9 @@ static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
struct ahc_dma_seg *sg, struct ahc_dma_seg *sg,
bus_addr_t addr, bus_size_t len); bus_addr_t addr, bus_size_t len);
static void static __inline void
ahc_schedule_completeq(struct ahc_softc *ahc, struct ahc_cmd *acmd) ahc_schedule_completeq(struct ahc_softc *ahc)
{ {
while (acmd != NULL) {
struct ahc_completeq *completeq;
struct ahc_cmd *list_cmd;
struct ahc_cmd *next_cmd;
next_cmd = TAILQ_NEXT(acmd, acmd_links.tqe);
completeq = &ahc->platform_data->completeq;
list_cmd = TAILQ_FIRST(completeq);
while (list_cmd != NULL
&& acmd_scsi_cmd(list_cmd).serial_number
< acmd_scsi_cmd(acmd).serial_number)
list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
if (list_cmd != NULL)
TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
else
TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
acmd = next_cmd;
}
if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) { if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) {
ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER; ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER;
ahc->platform_data->completeq_timer.expires = jiffies; ahc->platform_data->completeq_timer.expires = jiffies;
...@@ -664,25 +644,17 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, ...@@ -664,25 +644,17 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
#define AHC_LINUX_MAX_RETURNED_ERRORS 4 #define AHC_LINUX_MAX_RETURNED_ERRORS 4
static struct ahc_cmd * static struct ahc_cmd *
ahc_linux_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd) ahc_linux_run_complete_queue(struct ahc_softc *ahc)
{ {
struct ahc_cmd *acmd;
u_long done_flags; u_long done_flags;
int with_errors; int with_errors;
with_errors = 0; with_errors = 0;
ahc_done_lock(ahc, &done_flags); ahc_done_lock(ahc, &done_flags);
while (acmd != NULL) { while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) {
Scsi_Cmnd *cmd; Scsi_Cmnd *cmd;
cmd = &acmd_scsi_cmd(acmd);
acmd = TAILQ_NEXT(acmd, acmd_links.tqe);
cmd->host_scribble = NULL;
if (ahc_cmd_get_transaction_status(cmd) != DID_OK
|| (cmd->result & 0xFF) != SCSI_STATUS_OK)
with_errors++;
cmd->scsi_done(cmd);
if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) { if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) {
/* /*
* Linux uses stack recursion to requeue * Linux uses stack recursion to requeue
...@@ -692,8 +664,19 @@ ahc_linux_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd) ...@@ -692,8 +664,19 @@ ahc_linux_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd)
* the operating system in case they are going * the operating system in case they are going
* to be retried. "ick" * to be retried. "ick"
*/ */
ahc_schedule_completeq(ahc);
break; break;
} }
TAILQ_REMOVE(&ahc->platform_data->completeq,
acmd, acmd_links.tqe);
cmd = &acmd_scsi_cmd(acmd);
acmd = TAILQ_NEXT(acmd, acmd_links.tqe);
cmd->host_scribble = NULL;
if (ahc_cmd_get_transaction_status(cmd) != DID_OK
|| (cmd->result & 0xFF) != SCSI_STATUS_OK)
with_errors++;
cmd->scsi_done(cmd);
} }
ahc_done_unlock(ahc, &done_flags); ahc_done_unlock(ahc, &done_flags);
return (acmd); return (acmd);
...@@ -1053,7 +1036,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) ...@@ -1053,7 +1036,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
ahc_linux_queue_cmd_complete(ahc, cmd); ahc_linux_queue_cmd_complete(ahc, cmd);
ahc_schedule_completeq(ahc, NULL); ahc_schedule_completeq(ahc);
ahc_midlayer_entrypoint_unlock(ahc, &flags); ahc_midlayer_entrypoint_unlock(ahc, &flags);
return (0); return (0);
} }
...@@ -1062,7 +1045,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) ...@@ -1062,7 +1045,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
if (dev == NULL) { if (dev == NULL) {
ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
ahc_linux_queue_cmd_complete(ahc, cmd); ahc_linux_queue_cmd_complete(ahc, cmd);
ahc_schedule_completeq(ahc, NULL); ahc_schedule_completeq(ahc);
ahc_midlayer_entrypoint_unlock(ahc, &flags); ahc_midlayer_entrypoint_unlock(ahc, &flags);
printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n", printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n",
ahc_name(ahc)); ahc_name(ahc));
...@@ -1320,7 +1303,6 @@ static int ...@@ -1320,7 +1303,6 @@ static int
ahc_linux_bus_reset(Scsi_Cmnd *cmd) ahc_linux_bus_reset(Scsi_Cmnd *cmd)
{ {
struct ahc_softc *ahc; struct ahc_softc *ahc;
struct ahc_cmd *acmd;
u_long s; u_long s;
int found; int found;
...@@ -1328,14 +1310,7 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd) ...@@ -1328,14 +1310,7 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd)
ahc_midlayer_entrypoint_lock(ahc, &s); ahc_midlayer_entrypoint_lock(ahc, &s);
found = ahc_reset_channel(ahc, cmd->device->channel + 'A', found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
/*initiate reset*/TRUE); /*initiate reset*/TRUE);
acmd = TAILQ_FIRST(&ahc->platform_data->completeq); ahc_linux_run_complete_queue(ahc);
TAILQ_INIT(&ahc->platform_data->completeq);
if (acmd != NULL) {
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_midlayer_entrypoint_unlock(ahc, &s); ahc_midlayer_entrypoint_unlock(ahc, &s);
if (bootverbose) if (bootverbose)
...@@ -2255,19 +2230,12 @@ ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, ...@@ -2255,19 +2230,12 @@ ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel,
static void static void
ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc) ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc)
{ {
struct ahc_cmd *acmd;
u_long flags; u_long flags;
ahc_lock(ahc, &flags); ahc_lock(ahc, &flags);
del_timer(&ahc->platform_data->completeq_timer); del_timer(&ahc->platform_data->completeq_timer);
ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER; ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER;
acmd = TAILQ_FIRST(&ahc->platform_data->completeq); ahc_linux_run_complete_queue(ahc);
TAILQ_INIT(&ahc->platform_data->completeq);
if (acmd != NULL) {
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_unlock(ahc, &flags); ahc_unlock(ahc, &flags);
} }
...@@ -3467,7 +3435,6 @@ static void ...@@ -3467,7 +3435,6 @@ static void
ahc_linux_dv_timeout(struct scsi_cmnd *cmd) ahc_linux_dv_timeout(struct scsi_cmnd *cmd)
{ {
struct ahc_softc *ahc; struct ahc_softc *ahc;
struct ahc_cmd *acmd;
struct scb *scb; struct scb *scb;
u_long flags; u_long flags;
...@@ -3514,15 +3481,9 @@ ahc_linux_dv_timeout(struct scsi_cmnd *cmd) ...@@ -3514,15 +3481,9 @@ ahc_linux_dv_timeout(struct scsi_cmnd *cmd)
ahc->platform_data->reset_timer.function = ahc->platform_data->reset_timer.function =
(ahc_linux_callback_t *)ahc_linux_release_simq; (ahc_linux_callback_t *)ahc_linux_release_simq;
add_timer(&ahc->platform_data->reset_timer); add_timer(&ahc->platform_data->reset_timer);
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
if (ahc_linux_next_device_to_run(ahc) != NULL) if (ahc_linux_next_device_to_run(ahc) != NULL)
ahc_schedule_runq(ahc); ahc_schedule_runq(ahc);
if (acmd != NULL) { ahc_linux_run_complete_queue(ahc);
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_unlock(ahc, &flags); ahc_unlock(ahc, &flags);
} }
...@@ -3926,33 +3887,23 @@ void ...@@ -3926,33 +3887,23 @@ void
ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
{ {
struct ahc_softc *ahc; struct ahc_softc *ahc;
struct ahc_cmd *acmd;
u_long flags; u_long flags;
ahc = (struct ahc_softc *) dev_id; ahc = (struct ahc_softc *) dev_id;
ahc_lock(ahc, &flags); ahc_lock(ahc, &flags);
ahc_intr(ahc); ahc_intr(ahc);
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
if (ahc_linux_next_device_to_run(ahc) != NULL) if (ahc_linux_next_device_to_run(ahc) != NULL)
ahc_schedule_runq(ahc); ahc_schedule_runq(ahc);
if (acmd != NULL) { ahc_linux_run_complete_queue(ahc);
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_unlock(ahc, &flags); ahc_unlock(ahc, &flags);
} }
void void
ahc_platform_flushwork(struct ahc_softc *ahc) ahc_platform_flushwork(struct ahc_softc *ahc)
{ {
struct ahc_cmd *acmd;
acmd = TAILQ_FIRST(&ahc->platform_data->completeq); while (ahc_linux_run_complete_queue(ahc) != NULL)
TAILQ_INIT(&ahc->platform_data->completeq); ;
while (acmd != NULL)
acmd = ahc_linux_run_complete_queue(ahc, acmd);
} }
static struct ahc_linux_target* static struct ahc_linux_target*
...@@ -5094,14 +5045,8 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) ...@@ -5094,14 +5045,8 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
} }
spin_lock_irq(&ahc->platform_data->spin_lock); spin_lock_irq(&ahc->platform_data->spin_lock);
} }
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
ahc_schedule_runq(ahc); ahc_schedule_runq(ahc);
if (acmd != NULL) { ahc_linux_run_complete_queue(ahc);
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_midlayer_entrypoint_unlock(ahc, &s); ahc_midlayer_entrypoint_unlock(ahc, &s);
return (retval); return (retval);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment