Commit 8e45ebcc authored by James Bottomley's avatar James Bottomley Committed by James Bottomley

[SCSI] aic7xxx: remove the completeq

This should finish the spurious queue removal from aic7xxx (there are
other queues that are probably unnecessary, but at least the major and
obviously unnecessary ones are done with).
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 38c29ce0
...@@ -433,7 +433,6 @@ static void ahc_linux_release_simq(u_long arg); ...@@ -433,7 +433,6 @@ static void ahc_linux_release_simq(u_long arg);
static void ahc_linux_dev_timed_unfreeze(u_long arg); static void ahc_linux_dev_timed_unfreeze(u_long arg);
static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc);
static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo); struct ahc_devinfo *devinfo);
static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
...@@ -454,29 +453,17 @@ static void ahc_linux_setup_tag_info_global(char *p); ...@@ -454,29 +453,17 @@ static void ahc_linux_setup_tag_info_global(char *p);
static aic_option_callback_t ahc_linux_setup_tag_info; static aic_option_callback_t ahc_linux_setup_tag_info;
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 struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
/********************************* Inlines ************************************/ /********************************* Inlines ************************************/
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 __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
struct ahc_dma_seg *sg, struct ahc_dma_seg *sg,
dma_addr_t addr, bus_size_t len); dma_addr_t addr, bus_size_t len);
static __inline void
ahc_schedule_completeq(struct ahc_softc *ahc)
{
if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) {
ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER;
ahc->platform_data->completeq_timer.expires = jiffies;
add_timer(&ahc->platform_data->completeq_timer);
}
}
static __inline struct ahc_linux_device* static __inline struct ahc_linux_device*
ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
u_int lun, int alloc) u_int lun, int alloc)
...@@ -503,42 +490,6 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, ...@@ -503,42 +490,6 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
return (dev); return (dev);
} }
#define AHC_LINUX_MAX_RETURNED_ERRORS 4
static struct ahc_cmd *
ahc_linux_run_complete_queue(struct ahc_softc *ahc)
{
struct ahc_cmd *acmd;
int with_errors;
with_errors = 0;
while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) {
struct scsi_cmnd *cmd;
if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) {
/*
* Linux uses stack recursion to requeue
* commands that need to be retried. Avoid
* blowing out the stack by "spoon feeding"
* commands that completed with error back
* the operating system in case they are going
* to be retried. "ick"
*/
ahc_schedule_completeq(ahc);
break;
}
TAILQ_REMOVE(&ahc->platform_data->completeq,
acmd, acmd_links.tqe);
cmd = &acmd_scsi_cmd(acmd);
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);
}
return (acmd);
}
static __inline void static __inline void
ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
{ {
...@@ -856,7 +807,6 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd) ...@@ -856,7 +807,6 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd)
ahc = *(struct ahc_softc **)cmd->device->host->hostdata; ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
found = ahc_reset_channel(ahc, cmd->device->channel + 'A', found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
/*initiate reset*/TRUE); /*initiate reset*/TRUE);
ahc_linux_run_complete_queue(ahc);
if (bootverbose) if (bootverbose)
printf("%s: SCSI bus reset delivered. " printf("%s: SCSI bus reset delivered. "
...@@ -1331,13 +1281,8 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) ...@@ -1331,13 +1281,8 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
if (ahc->platform_data == NULL) if (ahc->platform_data == NULL)
return (ENOMEM); return (ENOMEM);
memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data));
TAILQ_INIT(&ahc->platform_data->completeq);
ahc->platform_data->irq = AHC_LINUX_NOIRQ; ahc->platform_data->irq = AHC_LINUX_NOIRQ;
ahc_lockinit(ahc); ahc_lockinit(ahc);
init_timer(&ahc->platform_data->completeq_timer);
ahc->platform_data->completeq_timer.data = (u_long)ahc;
ahc->platform_data->completeq_timer.function =
(ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue;
init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;
...@@ -1355,7 +1300,6 @@ ahc_platform_free(struct ahc_softc *ahc) ...@@ -1355,7 +1300,6 @@ ahc_platform_free(struct ahc_softc *ahc)
int i, j; int i, j;
if (ahc->platform_data != NULL) { if (ahc->platform_data != NULL) {
del_timer_sync(&ahc->platform_data->completeq_timer);
if (ahc->platform_data->host != NULL) { if (ahc->platform_data->host != NULL) {
scsi_remove_host(ahc->platform_data->host); scsi_remove_host(ahc->platform_data->host);
scsi_host_put(ahc->platform_data->host); scsi_host_put(ahc->platform_data->host);
...@@ -1504,18 +1448,6 @@ ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, ...@@ -1504,18 +1448,6 @@ ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel,
return 0; return 0;
} }
static void
ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc)
{
u_long flags;
ahc_lock(ahc, &flags);
del_timer(&ahc->platform_data->completeq_timer);
ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER;
ahc_linux_run_complete_queue(ahc);
ahc_unlock(ahc, &flags);
}
static u_int static u_int
ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
{ {
...@@ -1785,7 +1717,6 @@ ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1785,7 +1717,6 @@ ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
ahc = (struct ahc_softc *) dev_id; ahc = (struct ahc_softc *) dev_id;
ahc_lock(ahc, &flags); ahc_lock(ahc, &flags);
ours = ahc_intr(ahc); ours = ahc_intr(ahc);
ahc_linux_run_complete_queue(ahc);
ahc_unlock(ahc, &flags); ahc_unlock(ahc, &flags);
return IRQ_RETVAL(ours); return IRQ_RETVAL(ours);
} }
...@@ -1794,8 +1725,6 @@ void ...@@ -1794,8 +1725,6 @@ void
ahc_platform_flushwork(struct ahc_softc *ahc) ahc_platform_flushwork(struct ahc_softc *ahc)
{ {
while (ahc_linux_run_complete_queue(ahc) != NULL)
;
} }
static struct ahc_linux_target* static struct ahc_linux_target*
...@@ -2274,22 +2203,6 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, ...@@ -2274,22 +2203,6 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
static void static void
ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd)
{ {
/*
* Typically, the complete queue has very few entries
* queued to it before the queue is emptied by
* ahc_linux_run_complete_queue, so sorting the entries
* by generation number should be inexpensive.
* We perform the sort so that commands that complete
* with an error are retuned in the order origionally
* queued to the controller so that any subsequent retries
* are performed in order. The underlying ahc routines do
* not guarantee the order that aborted commands will be
* returned to us.
*/
struct ahc_completeq *completeq;
struct ahc_cmd *list_cmd;
struct ahc_cmd *acmd;
/* /*
* Map CAM error codes into Linux Error codes. We * Map CAM error codes into Linux Error codes. We
* avoid the conversion so that the DV code has the * avoid the conversion so that the DV code has the
...@@ -2343,26 +2256,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) ...@@ -2343,26 +2256,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd)
new_status = DID_ERROR; new_status = DID_ERROR;
break; break;
case CAM_REQUEUE_REQ: case CAM_REQUEUE_REQ:
/* new_status = DID_REQUEUE;
* If we want the request requeued, make sure there
* are sufficent retries. In the old scsi error code,
* we used to be able to specify a result code that
* bypassed the retry count. Now we must use this
* hack. We also "fake" a check condition with
* a sense code of ABORTED COMMAND. This seems to
* evoke a retry even if this command is being sent
* via the eh thread. Ick! Ick! Ick!
*/
if (cmd->retries > 0)
cmd->retries--;
new_status = DID_OK;
ahc_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
cmd->result |= (DRIVER_SENSE << 24);
memset(cmd->sense_buffer, 0,
sizeof(cmd->sense_buffer));
cmd->sense_buffer[0] = SSD_ERRCODE_VALID
| SSD_CURRENT_ERROR;
cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND;
break; break;
default: default:
/* We should never get here */ /* We should never get here */
...@@ -2373,17 +2267,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) ...@@ -2373,17 +2267,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd)
ahc_cmd_set_transaction_status(cmd, new_status); ahc_cmd_set_transaction_status(cmd, new_status);
} }
completeq = &ahc->platform_data->completeq; cmd->scsi_done(cmd);
list_cmd = TAILQ_FIRST(completeq);
acmd = (struct ahc_cmd *)cmd;
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);
} }
static void static void
...@@ -2747,7 +2631,6 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) ...@@ -2747,7 +2631,6 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
} }
spin_lock_irq(&ahc->platform_data->spin_lock); spin_lock_irq(&ahc->platform_data->spin_lock);
} }
ahc_linux_run_complete_queue(ahc);
return (retval); return (retval);
} }
......
...@@ -436,16 +436,11 @@ struct ahc_linux_target { ...@@ -436,16 +436,11 @@ struct ahc_linux_target {
/* /*
* Per-SCB OSM storage. * Per-SCB OSM storage.
*/ */
typedef enum {
AHC_UP_EH_SEMAPHORE = 0x1
} ahc_linux_scb_flags;
struct scb_platform_data { struct scb_platform_data {
struct ahc_linux_device *dev; struct ahc_linux_device *dev;
dma_addr_t buf_busaddr; dma_addr_t buf_busaddr;
uint32_t xfer_len; uint32_t xfer_len;
uint32_t sense_resid; /* Auto-Sense residual */ uint32_t sense_resid; /* Auto-Sense residual */
ahc_linux_scb_flags flags;
}; };
/* /*
...@@ -454,22 +449,14 @@ struct scb_platform_data { ...@@ -454,22 +449,14 @@ struct scb_platform_data {
* alignment restrictions of the various platforms supported by * alignment restrictions of the various platforms supported by
* this driver. * this driver.
*/ */
typedef enum {
AHC_RUN_CMPLT_Q_TIMER = 0x10
} ahc_linux_softc_flags;
TAILQ_HEAD(ahc_completeq, ahc_cmd);
struct ahc_platform_data { struct ahc_platform_data {
/* /*
* Fields accessed from interrupt context. * Fields accessed from interrupt context.
*/ */
struct ahc_linux_target *targets[AHC_NUM_TARGETS]; struct ahc_linux_target *targets[AHC_NUM_TARGETS];
struct ahc_completeq completeq;
spinlock_t spin_lock; spinlock_t spin_lock;
u_int qfrozen; u_int qfrozen;
struct timer_list completeq_timer;
struct timer_list reset_timer; struct timer_list reset_timer;
struct semaphore eh_sem; struct semaphore eh_sem;
struct Scsi_Host *host; /* pointer to scsi host */ struct Scsi_Host *host; /* pointer to scsi host */
...@@ -477,7 +464,9 @@ struct ahc_platform_data { ...@@ -477,7 +464,9 @@ struct ahc_platform_data {
uint32_t irq; /* IRQ for this adapter */ uint32_t irq; /* IRQ for this adapter */
uint32_t bios_address; uint32_t bios_address;
uint32_t mem_busaddr; /* Mem Base Addr */ uint32_t mem_busaddr; /* Mem Base Addr */
ahc_linux_softc_flags flags;
#define AHC_UP_EH_SEMAPHORE 0x1
uint32_t flags;
}; };
/************************** OS Utility Wrappers *******************************/ /************************** OS Utility Wrappers *******************************/
......
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