mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 09:11:49 +00:00
[SCSI] remove aic7xxx busyq
The aic7xxx driver has two spurious queues in it's linux glue code: the busyq which queues incoming commands to the driver and the completeq which queues finished commands before sending them back to the mid-layer This patch just removes the busyq and makes the aic finally return the correct status to get the mid-layer to manage its queueing, so a command is either committed to the sequencer or returned to the midlayer for requeue. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
fad01ef88d
commit
e4e360c325
@ -458,26 +458,20 @@ static struct ahc_linux_device* ahc_linux_alloc_device(struct ahc_softc*,
|
|||||||
u_int);
|
u_int);
|
||||||
static void ahc_linux_free_device(struct ahc_softc*,
|
static void ahc_linux_free_device(struct ahc_softc*,
|
||||||
struct ahc_linux_device*);
|
struct ahc_linux_device*);
|
||||||
static void ahc_linux_run_device_queue(struct ahc_softc*,
|
static int ahc_linux_run_command(struct ahc_softc*,
|
||||||
struct ahc_linux_device*);
|
struct ahc_linux_device *,
|
||||||
|
struct scsi_cmnd *);
|
||||||
static void ahc_linux_setup_tag_info_global(char *p);
|
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 void ahc_runq_tasklet(unsigned long data);
|
|
||||||
static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
|
static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
|
||||||
|
|
||||||
/********************************* Inlines ************************************/
|
/********************************* Inlines ************************************/
|
||||||
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 __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
|
static __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
|
||||||
static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc,
|
|
||||||
struct ahc_linux_device *dev);
|
|
||||||
static __inline struct ahc_linux_device *
|
|
||||||
ahc_linux_next_device_to_run(struct ahc_softc *ahc);
|
|
||||||
static __inline void ahc_linux_run_device_queues(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,
|
||||||
@ -494,15 +488,6 @@ ahc_schedule_completeq(struct ahc_softc *ahc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Must be called with our lock held.
|
|
||||||
*/
|
|
||||||
static __inline void
|
|
||||||
ahc_schedule_runq(struct ahc_softc *ahc)
|
|
||||||
{
|
|
||||||
tasklet_schedule(&ahc->platform_data->runq_tasklet);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
@ -568,45 +553,6 @@ ahc_linux_run_complete_queue(struct ahc_softc *ahc)
|
|||||||
return (acmd);
|
return (acmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline void
|
|
||||||
ahc_linux_check_device_queue(struct ahc_softc *ahc,
|
|
||||||
struct ahc_linux_device *dev)
|
|
||||||
{
|
|
||||||
if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0
|
|
||||||
&& dev->active == 0) {
|
|
||||||
dev->flags &= ~AHC_DEV_FREEZE_TIL_EMPTY;
|
|
||||||
dev->qfrozen--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TAILQ_FIRST(&dev->busyq) == NULL
|
|
||||||
|| dev->openings == 0 || dev->qfrozen != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ahc_linux_run_device_queue(ahc, dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline struct ahc_linux_device *
|
|
||||||
ahc_linux_next_device_to_run(struct ahc_softc *ahc)
|
|
||||||
{
|
|
||||||
|
|
||||||
if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
|
|
||||||
|| (ahc->platform_data->qfrozen != 0))
|
|
||||||
return (NULL);
|
|
||||||
return (TAILQ_FIRST(&ahc->platform_data->device_runq));
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline void
|
|
||||||
ahc_linux_run_device_queues(struct ahc_softc *ahc)
|
|
||||||
{
|
|
||||||
struct ahc_linux_device *dev;
|
|
||||||
|
|
||||||
while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) {
|
|
||||||
TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links);
|
|
||||||
dev->flags &= ~AHC_DEV_ON_RUN_LIST;
|
|
||||||
ahc_linux_check_device_queue(ahc, dev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@ -871,7 +817,6 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
|
|||||||
{
|
{
|
||||||
struct ahc_softc *ahc;
|
struct ahc_softc *ahc;
|
||||||
struct ahc_linux_device *dev;
|
struct ahc_linux_device *dev;
|
||||||
u_long flags;
|
|
||||||
|
|
||||||
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
|
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
|
||||||
|
|
||||||
@ -880,42 +825,22 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
|
|||||||
*/
|
*/
|
||||||
cmd->scsi_done = scsi_done;
|
cmd->scsi_done = scsi_done;
|
||||||
|
|
||||||
ahc_midlayer_entrypoint_lock(ahc, &flags);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close the race of a command that was in the process of
|
* Close the race of a command that was in the process of
|
||||||
* being queued to us just as our simq was frozen. Let
|
* being queued to us just as our simq was frozen. Let
|
||||||
* DV commands through so long as we are only frozen to
|
* DV commands through so long as we are only frozen to
|
||||||
* perform DV.
|
* perform DV.
|
||||||
*/
|
*/
|
||||||
if (ahc->platform_data->qfrozen != 0) {
|
if (ahc->platform_data->qfrozen != 0)
|
||||||
|
return SCSI_MLQUEUE_HOST_BUSY;
|
||||||
|
|
||||||
ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
|
|
||||||
ahc_linux_queue_cmd_complete(ahc, cmd);
|
|
||||||
ahc_schedule_completeq(ahc);
|
|
||||||
ahc_midlayer_entrypoint_unlock(ahc, &flags);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
|
dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
|
||||||
cmd->device->lun, /*alloc*/TRUE);
|
cmd->device->lun, /*alloc*/TRUE);
|
||||||
if (dev == NULL) {
|
BUG_ON(dev == NULL);
|
||||||
ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
|
|
||||||
ahc_linux_queue_cmd_complete(ahc, cmd);
|
|
||||||
ahc_schedule_completeq(ahc);
|
|
||||||
ahc_midlayer_entrypoint_unlock(ahc, &flags);
|
|
||||||
printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n",
|
|
||||||
ahc_name(ahc));
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
cmd->result = CAM_REQ_INPROG << 16;
|
cmd->result = CAM_REQ_INPROG << 16;
|
||||||
TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe);
|
|
||||||
if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
|
return ahc_linux_run_command(ahc, dev, cmd);
|
||||||
TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
|
|
||||||
dev->flags |= AHC_DEV_ON_RUN_LIST;
|
|
||||||
ahc_linux_run_device_queues(ahc);
|
|
||||||
}
|
|
||||||
ahc_midlayer_entrypoint_unlock(ahc, &flags);
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
|
||||||
@ -987,8 +912,7 @@ ahc_linux_slave_destroy(Scsi_Device *device)
|
|||||||
if (dev != NULL
|
if (dev != NULL
|
||||||
&& (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {
|
&& (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {
|
||||||
dev->flags |= AHC_DEV_UNCONFIGURED;
|
dev->flags |= AHC_DEV_UNCONFIGURED;
|
||||||
if (TAILQ_EMPTY(&dev->busyq)
|
if (dev->active == 0
|
||||||
&& dev->active == 0
|
|
||||||
&& (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
|
&& (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
|
||||||
ahc_linux_free_device(ahc, dev);
|
ahc_linux_free_device(ahc, dev);
|
||||||
}
|
}
|
||||||
@ -1206,33 +1130,6 @@ Scsi_Host_Template aic7xxx_driver_template = {
|
|||||||
|
|
||||||
/**************************** Tasklet Handler *********************************/
|
/**************************** Tasklet Handler *********************************/
|
||||||
|
|
||||||
/*
|
|
||||||
* In 2.4.X and above, this routine is called from a tasklet,
|
|
||||||
* so we must re-acquire our lock prior to executing this code.
|
|
||||||
* In all prior kernels, ahc_schedule_runq() calls this routine
|
|
||||||
* directly and ahc_schedule_runq() is called with our lock held.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ahc_runq_tasklet(unsigned long data)
|
|
||||||
{
|
|
||||||
struct ahc_softc* ahc;
|
|
||||||
struct ahc_linux_device *dev;
|
|
||||||
u_long flags;
|
|
||||||
|
|
||||||
ahc = (struct ahc_softc *)data;
|
|
||||||
ahc_lock(ahc, &flags);
|
|
||||||
while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) {
|
|
||||||
|
|
||||||
TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links);
|
|
||||||
dev->flags &= ~AHC_DEV_ON_RUN_LIST;
|
|
||||||
ahc_linux_check_device_queue(ahc, dev);
|
|
||||||
/* Yeild to our interrupt handler */
|
|
||||||
ahc_unlock(ahc, &flags);
|
|
||||||
ahc_lock(ahc, &flags);
|
|
||||||
}
|
|
||||||
ahc_unlock(ahc, &flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************** Macros **************************************/
|
/******************************** Macros **************************************/
|
||||||
#define BUILD_SCSIID(ahc, cmd) \
|
#define BUILD_SCSIID(ahc, cmd) \
|
||||||
((((cmd)->device->id << TID_SHIFT) & TID) \
|
((((cmd)->device->id << TID_SHIFT) & TID) \
|
||||||
@ -1728,8 +1625,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
|
|||||||
ahc->platform_data->completeq_timer.function =
|
ahc->platform_data->completeq_timer.function =
|
||||||
(ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue;
|
(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);
|
||||||
tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet,
|
|
||||||
(unsigned long)ahc);
|
|
||||||
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;
|
||||||
if (aic7xxx_pci_parity == 0)
|
if (aic7xxx_pci_parity == 0)
|
||||||
@ -1747,7 +1642,6 @@ ahc_platform_free(struct ahc_softc *ahc)
|
|||||||
|
|
||||||
if (ahc->platform_data != NULL) {
|
if (ahc->platform_data != NULL) {
|
||||||
del_timer_sync(&ahc->platform_data->completeq_timer);
|
del_timer_sync(&ahc->platform_data->completeq_timer);
|
||||||
tasklet_kill(&ahc->platform_data->runq_tasklet);
|
|
||||||
if (ahc->platform_data->host != NULL) {
|
if (ahc->platform_data->host != NULL) {
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
|
||||||
scsi_remove_host(ahc->platform_data->host);
|
scsi_remove_host(ahc->platform_data->host);
|
||||||
@ -1906,71 +1800,7 @@ int
|
|||||||
ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel,
|
ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel,
|
||||||
int lun, u_int tag, role_t role, uint32_t status)
|
int lun, u_int tag, role_t role, uint32_t status)
|
||||||
{
|
{
|
||||||
int chan;
|
return 0;
|
||||||
int maxchan;
|
|
||||||
int targ;
|
|
||||||
int maxtarg;
|
|
||||||
int clun;
|
|
||||||
int maxlun;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
if (tag != SCB_LIST_NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
chan = 0;
|
|
||||||
if (channel != ALL_CHANNELS) {
|
|
||||||
chan = channel - 'A';
|
|
||||||
maxchan = chan + 1;
|
|
||||||
} else {
|
|
||||||
maxchan = (ahc->features & AHC_TWIN) ? 2 : 1;
|
|
||||||
}
|
|
||||||
targ = 0;
|
|
||||||
if (target != CAM_TARGET_WILDCARD) {
|
|
||||||
targ = target;
|
|
||||||
maxtarg = targ + 1;
|
|
||||||
} else {
|
|
||||||
maxtarg = (ahc->features & AHC_WIDE) ? 16 : 8;
|
|
||||||
}
|
|
||||||
clun = 0;
|
|
||||||
if (lun != CAM_LUN_WILDCARD) {
|
|
||||||
clun = lun;
|
|
||||||
maxlun = clun + 1;
|
|
||||||
} else {
|
|
||||||
maxlun = AHC_NUM_LUNS;
|
|
||||||
}
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
for (; chan < maxchan; chan++) {
|
|
||||||
|
|
||||||
for (; targ < maxtarg; targ++) {
|
|
||||||
|
|
||||||
for (; clun < maxlun; clun++) {
|
|
||||||
struct ahc_linux_device *dev;
|
|
||||||
struct ahc_busyq *busyq;
|
|
||||||
struct ahc_cmd *acmd;
|
|
||||||
|
|
||||||
dev = ahc_linux_get_device(ahc, chan,
|
|
||||||
targ, clun,
|
|
||||||
/*alloc*/FALSE);
|
|
||||||
if (dev == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
busyq = &dev->busyq;
|
|
||||||
while ((acmd = TAILQ_FIRST(busyq)) != NULL) {
|
|
||||||
Scsi_Cmnd *cmd;
|
|
||||||
|
|
||||||
cmd = &acmd_scsi_cmd(acmd);
|
|
||||||
TAILQ_REMOVE(busyq, acmd,
|
|
||||||
acmd_links.tqe);
|
|
||||||
count++;
|
|
||||||
cmd->result = status << 16;
|
|
||||||
ahc_linux_queue_cmd_complete(ahc, cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2045,213 +1875,203 @@ ahc_linux_device_queue_depth(struct ahc_softc *ahc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
|
ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
|
||||||
|
struct scsi_cmnd *cmd)
|
||||||
{
|
{
|
||||||
struct ahc_cmd *acmd;
|
|
||||||
struct scsi_cmnd *cmd;
|
|
||||||
struct scb *scb;
|
struct scb *scb;
|
||||||
struct hardware_scb *hscb;
|
struct hardware_scb *hscb;
|
||||||
struct ahc_initiator_tinfo *tinfo;
|
struct ahc_initiator_tinfo *tinfo;
|
||||||
struct ahc_tmode_tstate *tstate;
|
struct ahc_tmode_tstate *tstate;
|
||||||
uint16_t mask;
|
uint16_t mask;
|
||||||
|
struct scb_tailq *untagged_q = NULL;
|
||||||
|
|
||||||
if ((dev->flags & AHC_DEV_ON_RUN_LIST) != 0)
|
/*
|
||||||
panic("running device on run list");
|
* Schedule us to run later. The only reason we are not
|
||||||
|
* running is because the whole controller Q is frozen.
|
||||||
|
*/
|
||||||
|
if (ahc->platform_data->qfrozen != 0)
|
||||||
|
return SCSI_MLQUEUE_HOST_BUSY;
|
||||||
|
|
||||||
while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
|
/*
|
||||||
&& dev->openings > 0 && dev->qfrozen == 0) {
|
* We only allow one untagged transaction
|
||||||
|
* per target in the initiator role unless
|
||||||
|
* we are storing a full busy target *lun*
|
||||||
|
* table in SCB space.
|
||||||
|
*/
|
||||||
|
if (!blk_rq_tagged(cmd->request)
|
||||||
|
&& (ahc->features & AHC_SCB_BTT) == 0) {
|
||||||
|
int target_offset;
|
||||||
|
|
||||||
/*
|
target_offset = cmd->device->id + cmd->device->channel * 8;
|
||||||
* Schedule us to run later. The only reason we are not
|
untagged_q = &(ahc->untagged_queues[target_offset]);
|
||||||
* running is because the whole controller Q is frozen.
|
if (!TAILQ_EMPTY(untagged_q))
|
||||||
*/
|
/* if we're already executing an untagged command
|
||||||
if (ahc->platform_data->qfrozen != 0) {
|
* we're busy to another */
|
||||||
TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
|
return SCSI_MLQUEUE_DEVICE_BUSY;
|
||||||
dev, links);
|
|
||||||
dev->flags |= AHC_DEV_ON_RUN_LIST;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Get an scb to use.
|
|
||||||
*/
|
|
||||||
if ((scb = ahc_get_scb(ahc)) == NULL) {
|
|
||||||
TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
|
|
||||||
dev, links);
|
|
||||||
dev->flags |= AHC_DEV_ON_RUN_LIST;
|
|
||||||
ahc->flags |= AHC_RESOURCE_SHORTAGE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);
|
|
||||||
cmd = &acmd_scsi_cmd(acmd);
|
|
||||||
scb->io_ctx = cmd;
|
|
||||||
scb->platform_data->dev = dev;
|
|
||||||
hscb = scb->hscb;
|
|
||||||
cmd->host_scribble = (char *)scb;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fill out basics of the HSCB.
|
|
||||||
*/
|
|
||||||
hscb->control = 0;
|
|
||||||
hscb->scsiid = BUILD_SCSIID(ahc, cmd);
|
|
||||||
hscb->lun = cmd->device->lun;
|
|
||||||
mask = SCB_GET_TARGET_MASK(ahc, scb);
|
|
||||||
tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
|
|
||||||
SCB_GET_OUR_ID(scb),
|
|
||||||
SCB_GET_TARGET(ahc, scb), &tstate);
|
|
||||||
hscb->scsirate = tinfo->scsirate;
|
|
||||||
hscb->scsioffset = tinfo->curr.offset;
|
|
||||||
if ((tstate->ultraenb & mask) != 0)
|
|
||||||
hscb->control |= ULTRAENB;
|
|
||||||
|
|
||||||
if ((ahc->user_discenable & mask) != 0)
|
|
||||||
hscb->control |= DISCENB;
|
|
||||||
|
|
||||||
if ((tstate->auto_negotiate & mask) != 0) {
|
|
||||||
scb->flags |= SCB_AUTO_NEGOTIATE;
|
|
||||||
scb->hscb->control |= MK_MESSAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
|
|
||||||
int msg_bytes;
|
|
||||||
uint8_t tag_msgs[2];
|
|
||||||
|
|
||||||
msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
|
|
||||||
if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
|
|
||||||
hscb->control |= tag_msgs[0];
|
|
||||||
if (tag_msgs[0] == MSG_ORDERED_TASK)
|
|
||||||
dev->commands_since_idle_or_otag = 0;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
|
|
||||||
&& (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
|
|
||||||
hscb->control |= MSG_ORDERED_TASK;
|
|
||||||
dev->commands_since_idle_or_otag = 0;
|
|
||||||
} else {
|
|
||||||
hscb->control |= MSG_SIMPLE_TASK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hscb->cdb_len = cmd->cmd_len;
|
|
||||||
if (hscb->cdb_len <= 12) {
|
|
||||||
memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len);
|
|
||||||
} else {
|
|
||||||
memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len);
|
|
||||||
scb->flags |= SCB_CDB32_PTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
scb->platform_data->xfer_len = 0;
|
|
||||||
ahc_set_residual(scb, 0);
|
|
||||||
ahc_set_sense_residual(scb, 0);
|
|
||||||
scb->sg_count = 0;
|
|
||||||
if (cmd->use_sg != 0) {
|
|
||||||
struct ahc_dma_seg *sg;
|
|
||||||
struct scatterlist *cur_seg;
|
|
||||||
struct scatterlist *end_seg;
|
|
||||||
int nseg;
|
|
||||||
|
|
||||||
cur_seg = (struct scatterlist *)cmd->request_buffer;
|
|
||||||
nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
|
|
||||||
cmd->sc_data_direction);
|
|
||||||
end_seg = cur_seg + nseg;
|
|
||||||
/* Copy the segments into the SG list. */
|
|
||||||
sg = scb->sg_list;
|
|
||||||
/*
|
|
||||||
* The sg_count may be larger than nseg if
|
|
||||||
* a transfer crosses a 32bit page.
|
|
||||||
*/
|
|
||||||
while (cur_seg < end_seg) {
|
|
||||||
dma_addr_t addr;
|
|
||||||
bus_size_t len;
|
|
||||||
int consumed;
|
|
||||||
|
|
||||||
addr = sg_dma_address(cur_seg);
|
|
||||||
len = sg_dma_len(cur_seg);
|
|
||||||
consumed = ahc_linux_map_seg(ahc, scb,
|
|
||||||
sg, addr, len);
|
|
||||||
sg += consumed;
|
|
||||||
scb->sg_count += consumed;
|
|
||||||
cur_seg++;
|
|
||||||
}
|
|
||||||
sg--;
|
|
||||||
sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset the sg list pointer.
|
|
||||||
*/
|
|
||||||
scb->hscb->sgptr =
|
|
||||||
ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy the first SG into the "current"
|
|
||||||
* data pointer area.
|
|
||||||
*/
|
|
||||||
scb->hscb->dataptr = scb->sg_list->addr;
|
|
||||||
scb->hscb->datacnt = scb->sg_list->len;
|
|
||||||
} else if (cmd->request_bufflen != 0) {
|
|
||||||
struct ahc_dma_seg *sg;
|
|
||||||
dma_addr_t addr;
|
|
||||||
|
|
||||||
sg = scb->sg_list;
|
|
||||||
addr = pci_map_single(ahc->dev_softc,
|
|
||||||
cmd->request_buffer,
|
|
||||||
cmd->request_bufflen,
|
|
||||||
cmd->sc_data_direction);
|
|
||||||
scb->platform_data->buf_busaddr = addr;
|
|
||||||
scb->sg_count = ahc_linux_map_seg(ahc, scb,
|
|
||||||
sg, addr,
|
|
||||||
cmd->request_bufflen);
|
|
||||||
sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset the sg list pointer.
|
|
||||||
*/
|
|
||||||
scb->hscb->sgptr =
|
|
||||||
ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy the first SG into the "current"
|
|
||||||
* data pointer area.
|
|
||||||
*/
|
|
||||||
scb->hscb->dataptr = sg->addr;
|
|
||||||
scb->hscb->datacnt = sg->len;
|
|
||||||
} else {
|
|
||||||
scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
|
|
||||||
scb->hscb->dataptr = 0;
|
|
||||||
scb->hscb->datacnt = 0;
|
|
||||||
scb->sg_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ahc_sync_sglist(ahc, scb, BUS_DMASYNC_PREWRITE);
|
|
||||||
LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
|
|
||||||
dev->openings--;
|
|
||||||
dev->active++;
|
|
||||||
dev->commands_issued++;
|
|
||||||
if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0)
|
|
||||||
dev->commands_since_idle_or_otag++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We only allow one untagged transaction
|
|
||||||
* per target in the initiator role unless
|
|
||||||
* we are storing a full busy target *lun*
|
|
||||||
* table in SCB space.
|
|
||||||
*/
|
|
||||||
if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0
|
|
||||||
&& (ahc->features & AHC_SCB_BTT) == 0) {
|
|
||||||
struct scb_tailq *untagged_q;
|
|
||||||
int target_offset;
|
|
||||||
|
|
||||||
target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
|
|
||||||
untagged_q = &(ahc->untagged_queues[target_offset]);
|
|
||||||
TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
|
|
||||||
scb->flags |= SCB_UNTAGGEDQ;
|
|
||||||
if (TAILQ_FIRST(untagged_q) != scb)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
scb->flags |= SCB_ACTIVE;
|
|
||||||
ahc_queue_scb(ahc, scb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get an scb to use.
|
||||||
|
*/
|
||||||
|
if ((scb = ahc_get_scb(ahc)) == NULL) {
|
||||||
|
ahc->flags |= AHC_RESOURCE_SHORTAGE;
|
||||||
|
return SCSI_MLQUEUE_HOST_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
scb->io_ctx = cmd;
|
||||||
|
scb->platform_data->dev = dev;
|
||||||
|
hscb = scb->hscb;
|
||||||
|
cmd->host_scribble = (char *)scb;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill out basics of the HSCB.
|
||||||
|
*/
|
||||||
|
hscb->control = 0;
|
||||||
|
hscb->scsiid = BUILD_SCSIID(ahc, cmd);
|
||||||
|
hscb->lun = cmd->device->lun;
|
||||||
|
mask = SCB_GET_TARGET_MASK(ahc, scb);
|
||||||
|
tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
|
||||||
|
SCB_GET_OUR_ID(scb),
|
||||||
|
SCB_GET_TARGET(ahc, scb), &tstate);
|
||||||
|
hscb->scsirate = tinfo->scsirate;
|
||||||
|
hscb->scsioffset = tinfo->curr.offset;
|
||||||
|
if ((tstate->ultraenb & mask) != 0)
|
||||||
|
hscb->control |= ULTRAENB;
|
||||||
|
|
||||||
|
if ((ahc->user_discenable & mask) != 0)
|
||||||
|
hscb->control |= DISCENB;
|
||||||
|
|
||||||
|
if ((tstate->auto_negotiate & mask) != 0) {
|
||||||
|
scb->flags |= SCB_AUTO_NEGOTIATE;
|
||||||
|
scb->hscb->control |= MK_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
|
||||||
|
int msg_bytes;
|
||||||
|
uint8_t tag_msgs[2];
|
||||||
|
|
||||||
|
msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
|
||||||
|
if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
|
||||||
|
hscb->control |= tag_msgs[0];
|
||||||
|
if (tag_msgs[0] == MSG_ORDERED_TASK)
|
||||||
|
dev->commands_since_idle_or_otag = 0;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
|
||||||
|
&& (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
|
||||||
|
hscb->control |= MSG_ORDERED_TASK;
|
||||||
|
dev->commands_since_idle_or_otag = 0;
|
||||||
|
} else {
|
||||||
|
hscb->control |= MSG_SIMPLE_TASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hscb->cdb_len = cmd->cmd_len;
|
||||||
|
if (hscb->cdb_len <= 12) {
|
||||||
|
memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len);
|
||||||
|
} else {
|
||||||
|
memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len);
|
||||||
|
scb->flags |= SCB_CDB32_PTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
scb->platform_data->xfer_len = 0;
|
||||||
|
ahc_set_residual(scb, 0);
|
||||||
|
ahc_set_sense_residual(scb, 0);
|
||||||
|
scb->sg_count = 0;
|
||||||
|
if (cmd->use_sg != 0) {
|
||||||
|
struct ahc_dma_seg *sg;
|
||||||
|
struct scatterlist *cur_seg;
|
||||||
|
struct scatterlist *end_seg;
|
||||||
|
int nseg;
|
||||||
|
|
||||||
|
cur_seg = (struct scatterlist *)cmd->request_buffer;
|
||||||
|
nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
|
||||||
|
cmd->sc_data_direction);
|
||||||
|
end_seg = cur_seg + nseg;
|
||||||
|
/* Copy the segments into the SG list. */
|
||||||
|
sg = scb->sg_list;
|
||||||
|
/*
|
||||||
|
* The sg_count may be larger than nseg if
|
||||||
|
* a transfer crosses a 32bit page.
|
||||||
|
*/
|
||||||
|
while (cur_seg < end_seg) {
|
||||||
|
dma_addr_t addr;
|
||||||
|
bus_size_t len;
|
||||||
|
int consumed;
|
||||||
|
|
||||||
|
addr = sg_dma_address(cur_seg);
|
||||||
|
len = sg_dma_len(cur_seg);
|
||||||
|
consumed = ahc_linux_map_seg(ahc, scb,
|
||||||
|
sg, addr, len);
|
||||||
|
sg += consumed;
|
||||||
|
scb->sg_count += consumed;
|
||||||
|
cur_seg++;
|
||||||
|
}
|
||||||
|
sg--;
|
||||||
|
sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the sg list pointer.
|
||||||
|
*/
|
||||||
|
scb->hscb->sgptr =
|
||||||
|
ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the first SG into the "current"
|
||||||
|
* data pointer area.
|
||||||
|
*/
|
||||||
|
scb->hscb->dataptr = scb->sg_list->addr;
|
||||||
|
scb->hscb->datacnt = scb->sg_list->len;
|
||||||
|
} else if (cmd->request_bufflen != 0) {
|
||||||
|
struct ahc_dma_seg *sg;
|
||||||
|
dma_addr_t addr;
|
||||||
|
|
||||||
|
sg = scb->sg_list;
|
||||||
|
addr = pci_map_single(ahc->dev_softc,
|
||||||
|
cmd->request_buffer,
|
||||||
|
cmd->request_bufflen,
|
||||||
|
cmd->sc_data_direction);
|
||||||
|
scb->platform_data->buf_busaddr = addr;
|
||||||
|
scb->sg_count = ahc_linux_map_seg(ahc, scb,
|
||||||
|
sg, addr,
|
||||||
|
cmd->request_bufflen);
|
||||||
|
sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the sg list pointer.
|
||||||
|
*/
|
||||||
|
scb->hscb->sgptr =
|
||||||
|
ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the first SG into the "current"
|
||||||
|
* data pointer area.
|
||||||
|
*/
|
||||||
|
scb->hscb->dataptr = sg->addr;
|
||||||
|
scb->hscb->datacnt = sg->len;
|
||||||
|
} else {
|
||||||
|
scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
|
||||||
|
scb->hscb->dataptr = 0;
|
||||||
|
scb->hscb->datacnt = 0;
|
||||||
|
scb->sg_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
|
||||||
|
dev->openings--;
|
||||||
|
dev->active++;
|
||||||
|
dev->commands_issued++;
|
||||||
|
if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0)
|
||||||
|
dev->commands_since_idle_or_otag++;
|
||||||
|
|
||||||
|
scb->flags |= SCB_ACTIVE;
|
||||||
|
if (untagged_q) {
|
||||||
|
TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
|
||||||
|
scb->flags |= SCB_UNTAGGEDQ;
|
||||||
|
}
|
||||||
|
ahc_queue_scb(ahc, scb);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2267,8 +2087,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);
|
||||||
if (ahc_linux_next_device_to_run(ahc) != NULL)
|
|
||||||
ahc_schedule_runq(ahc);
|
|
||||||
ahc_linux_run_complete_queue(ahc);
|
ahc_linux_run_complete_queue(ahc);
|
||||||
ahc_unlock(ahc, &flags);
|
ahc_unlock(ahc, &flags);
|
||||||
return IRQ_RETVAL(ours);
|
return IRQ_RETVAL(ours);
|
||||||
@ -2349,7 +2167,6 @@ ahc_linux_alloc_device(struct ahc_softc *ahc,
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
memset(dev, 0, sizeof(*dev));
|
memset(dev, 0, sizeof(*dev));
|
||||||
init_timer(&dev->timer);
|
init_timer(&dev->timer);
|
||||||
TAILQ_INIT(&dev->busyq);
|
|
||||||
dev->flags = AHC_DEV_UNCONFIGURED;
|
dev->flags = AHC_DEV_UNCONFIGURED;
|
||||||
dev->lun = lun;
|
dev->lun = lun;
|
||||||
dev->target = targ;
|
dev->target = targ;
|
||||||
@ -2515,7 +2332,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
|
|||||||
target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
|
target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
|
||||||
untagged_q = &(ahc->untagged_queues[target_offset]);
|
untagged_q = &(ahc->untagged_queues[target_offset]);
|
||||||
TAILQ_REMOVE(untagged_q, scb, links.tqe);
|
TAILQ_REMOVE(untagged_q, scb, links.tqe);
|
||||||
ahc_run_untagged_queue(ahc, untagged_q);
|
BUG_ON(!TAILQ_EMPTY(untagged_q));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((scb->flags & SCB_ACTIVE) == 0) {
|
if ((scb->flags & SCB_ACTIVE) == 0) {
|
||||||
@ -2606,12 +2423,11 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
|
|||||||
if (dev->active == 0)
|
if (dev->active == 0)
|
||||||
dev->commands_since_idle_or_otag = 0;
|
dev->commands_since_idle_or_otag = 0;
|
||||||
|
|
||||||
if (TAILQ_EMPTY(&dev->busyq)) {
|
if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
|
||||||
if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
|
&& dev->active == 0
|
||||||
&& dev->active == 0
|
&& (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
|
||||||
&& (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
|
ahc_linux_free_device(ahc, dev);
|
||||||
ahc_linux_free_device(ahc, dev);
|
else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
|
||||||
} else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
|
|
||||||
TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
|
TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
|
||||||
dev->flags |= AHC_DEV_ON_RUN_LIST;
|
dev->flags |= AHC_DEV_ON_RUN_LIST;
|
||||||
}
|
}
|
||||||
@ -2940,7 +2756,6 @@ ahc_linux_release_simq(u_long arg)
|
|||||||
ahc->platform_data->qfrozen--;
|
ahc->platform_data->qfrozen--;
|
||||||
if (ahc->platform_data->qfrozen == 0)
|
if (ahc->platform_data->qfrozen == 0)
|
||||||
unblock_reqs = 1;
|
unblock_reqs = 1;
|
||||||
ahc_schedule_runq(ahc);
|
|
||||||
ahc_unlock(ahc, &s);
|
ahc_unlock(ahc, &s);
|
||||||
/*
|
/*
|
||||||
* There is still a race here. The mid-layer
|
* There is still a race here. The mid-layer
|
||||||
@ -2965,11 +2780,7 @@ ahc_linux_dev_timed_unfreeze(u_long arg)
|
|||||||
dev->flags &= ~AHC_DEV_TIMER_ACTIVE;
|
dev->flags &= ~AHC_DEV_TIMER_ACTIVE;
|
||||||
if (dev->qfrozen > 0)
|
if (dev->qfrozen > 0)
|
||||||
dev->qfrozen--;
|
dev->qfrozen--;
|
||||||
if (dev->qfrozen == 0
|
if (dev->active == 0)
|
||||||
&& (dev->flags & AHC_DEV_ON_RUN_LIST) == 0)
|
|
||||||
ahc_linux_run_device_queue(ahc, dev);
|
|
||||||
if (TAILQ_EMPTY(&dev->busyq)
|
|
||||||
&& dev->active == 0)
|
|
||||||
__ahc_linux_free_device(ahc, dev);
|
__ahc_linux_free_device(ahc, dev);
|
||||||
ahc_unlock(ahc, &s);
|
ahc_unlock(ahc, &s);
|
||||||
}
|
}
|
||||||
@ -2978,8 +2789,6 @@ static int
|
|||||||
ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
|
ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
|
||||||
{
|
{
|
||||||
struct ahc_softc *ahc;
|
struct ahc_softc *ahc;
|
||||||
struct ahc_cmd *acmd;
|
|
||||||
struct ahc_cmd *list_acmd;
|
|
||||||
struct ahc_linux_device *dev;
|
struct ahc_linux_device *dev;
|
||||||
struct scb *pending_scb;
|
struct scb *pending_scb;
|
||||||
u_long s;
|
u_long s;
|
||||||
@ -2998,7 +2807,6 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
|
|||||||
paused = FALSE;
|
paused = FALSE;
|
||||||
wait = FALSE;
|
wait = FALSE;
|
||||||
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
|
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
|
||||||
acmd = (struct ahc_cmd *)cmd;
|
|
||||||
|
|
||||||
printf("%s:%d:%d:%d: Attempting to queue a%s message\n",
|
printf("%s:%d:%d:%d: Attempting to queue a%s message\n",
|
||||||
ahc_name(ahc), cmd->device->channel,
|
ahc_name(ahc), cmd->device->channel,
|
||||||
@ -3048,24 +2856,6 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
|
|||||||
goto no_cmd;
|
goto no_cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) {
|
|
||||||
if (list_acmd == acmd)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list_acmd != NULL) {
|
|
||||||
printf("%s:%d:%d:%d: Command found on device queue\n",
|
|
||||||
ahc_name(ahc), cmd->device->channel, cmd->device->id,
|
|
||||||
cmd->device->lun);
|
|
||||||
if (flag == SCB_ABORT) {
|
|
||||||
TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
|
|
||||||
cmd->result = DID_ABORT << 16;
|
|
||||||
ahc_linux_queue_cmd_complete(ahc, cmd);
|
|
||||||
retval = SUCCESS;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
|
if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
|
||||||
&& ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
|
&& ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
|
||||||
cmd->device->channel + 'A',
|
cmd->device->channel + 'A',
|
||||||
@ -3299,7 +3089,6 @@ done:
|
|||||||
}
|
}
|
||||||
spin_lock_irq(&ahc->platform_data->spin_lock);
|
spin_lock_irq(&ahc->platform_data->spin_lock);
|
||||||
}
|
}
|
||||||
ahc_schedule_runq(ahc);
|
|
||||||
ahc_linux_run_complete_queue(ahc);
|
ahc_linux_run_complete_queue(ahc);
|
||||||
ahc_midlayer_entrypoint_unlock(ahc, &s);
|
ahc_midlayer_entrypoint_unlock(ahc, &s);
|
||||||
return (retval);
|
return (retval);
|
||||||
@ -3308,40 +3097,6 @@ done:
|
|||||||
void
|
void
|
||||||
ahc_platform_dump_card_state(struct ahc_softc *ahc)
|
ahc_platform_dump_card_state(struct ahc_softc *ahc)
|
||||||
{
|
{
|
||||||
struct ahc_linux_device *dev;
|
|
||||||
int channel;
|
|
||||||
int maxchannel;
|
|
||||||
int target;
|
|
||||||
int maxtarget;
|
|
||||||
int lun;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
maxchannel = (ahc->features & AHC_TWIN) ? 1 : 0;
|
|
||||||
maxtarget = (ahc->features & AHC_WIDE) ? 15 : 7;
|
|
||||||
for (channel = 0; channel <= maxchannel; channel++) {
|
|
||||||
|
|
||||||
for (target = 0; target <=maxtarget; target++) {
|
|
||||||
|
|
||||||
for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
|
|
||||||
struct ahc_cmd *acmd;
|
|
||||||
|
|
||||||
dev = ahc_linux_get_device(ahc, channel, target,
|
|
||||||
lun, /*alloc*/FALSE);
|
|
||||||
if (dev == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
printf("DevQ(%d:%d:%d): ",
|
|
||||||
channel, target, lun);
|
|
||||||
i = 0;
|
|
||||||
TAILQ_FOREACH(acmd, &dev->busyq,
|
|
||||||
acmd_links.tqe) {
|
|
||||||
if (i++ > AHC_SCB_MAX)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("%d waiting\n", i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ahc_linux_exit(void);
|
static void ahc_linux_exit(void);
|
||||||
|
@ -66,11 +66,11 @@
|
|||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/smp_lock.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include <linux/interrupt.h> /* For tasklet support. */
|
|
||||||
#include <linux/config.h>
|
#include <linux/config.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
@ -341,7 +341,6 @@ typedef enum {
|
|||||||
struct ahc_linux_target;
|
struct ahc_linux_target;
|
||||||
struct ahc_linux_device {
|
struct ahc_linux_device {
|
||||||
TAILQ_ENTRY(ahc_linux_device) links;
|
TAILQ_ENTRY(ahc_linux_device) links;
|
||||||
struct ahc_busyq busyq;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The number of transactions currently
|
* The number of transactions currently
|
||||||
@ -488,7 +487,6 @@ struct ahc_platform_data {
|
|||||||
struct ahc_completeq completeq;
|
struct ahc_completeq completeq;
|
||||||
|
|
||||||
spinlock_t spin_lock;
|
spinlock_t spin_lock;
|
||||||
struct tasklet_struct runq_tasklet;
|
|
||||||
u_int qfrozen;
|
u_int qfrozen;
|
||||||
pid_t dv_pid;
|
pid_t dv_pid;
|
||||||
struct timer_list completeq_timer;
|
struct timer_list completeq_timer;
|
||||||
|
Loading…
Reference in New Issue
Block a user