Scsi_Device* d = NULL;
list_for_each_entry(d, &pHba->host->my_devices, siblings) {
- for(cmd = d->device_queue; cmd ; cmd = cmd->next){
+ unsigned long flags;
+ spin_lock_irqsave(&d->list_lock, flags);
+ list_for_each_entry(cmd, &d->cmd_list, list) {
if(cmd->serial_number == 0){
continue;
}
cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
cmd->scsi_done(cmd);
}
+ spin_unlock_irqrestore(&d->list_lock, flags);
}
}
{
struct Scsi_Host *shost = sdev->host;
struct scsi_cmnd *scmd;
+ unsigned long flags;
/*
* Loop over all of the commands associated with the
* device. If any of them are busy, then set the state
* back to inactive and bail.
*/
- for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
+ spin_lock_irqsave(&sdev->list_lock, flags);
+ list_for_each_entry(scmd, &sdev->cmd_list, list) {
if (scmd->request && scmd->request->rq_status != RQ_INACTIVE)
goto active;
if (scmd->request)
scmd->request->rq_status = RQ_SCSI_DISCONNECTING;
}
+ spin_unlock_irqrestore(&sdev->list_lock, flags);
return 0;
scmd->pid, scmd->state, scmd->owner);
list_for_each_entry(sdev, &shost->my_devices, siblings) {
- for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
+ list_for_each_entry(scmd, &sdev->cmd_list, list) {
if (scmd->request->rq_status == RQ_SCSI_DISCONNECTING)
scmd->request->rq_status = RQ_INACTIVE;
}
}
+ spin_unlock_irqrestore(&sdev->list_lock, flags);
printk(KERN_ERR "Device busy???\n");
return 1;
}
struct scsi_cmnd *cmd = __scsi_get_command(dev->host, gfp_mask);
if (likely(cmd != NULL)) {
+ unsigned long flags;
+
memset(cmd, 0, sizeof(*cmd));
cmd->device = dev;
cmd->state = SCSI_STATE_UNUSED;
cmd->owner = SCSI_OWNER_NOBODY;
init_timer(&cmd->eh_timeout);
INIT_LIST_HEAD(&cmd->list);
+ spin_lock_irqsave(&dev->list_lock, flags);
+ list_add(&dev->cmd_list, &cmd->list);
+ spin_unlock_irqrestore(&dev->list_lock, flags);
}
return cmd;
struct Scsi_Host *shost = cmd->device->host;
unsigned long flags;
- spin_lock_irqsave(&shost->free_list_lock, flags);
+ /* serious error if the command hasn't come from a device list */
+ spin_lock_irqsave(&cmd->device->list_lock, flags);
+ BUG_ON(list_empty(&cmd->list));
+ list_del_init(&cmd->list);
+ spin_unlock(&cmd->device->list_lock);
+ /* changing locks here, don't need to restore the irq state */
+ spin_lock(&shost->free_list_lock);
if (unlikely(list_empty(&shost->free_list))) {
list_add(&cmd->list, &shost->free_list);
cmd = NULL;
struct Scsi_Host *host;
request_queue_t *request_queue;
volatile unsigned short device_busy; /* commands actually active on low-level */
- struct list_head free_cmnds; /* list of available Scsi_Cmnd structs */
- struct list_head busy_cmnds; /* list of Scsi_Cmnd structs in use */
- Scsi_Cmnd *device_queue; /* queue of SCSI Command structures */
+ spinlock_t list_lock;
+ struct list_head cmd_list; /* queue of in use SCSI Command structures */
Scsi_Cmnd *current_cmnd; /* currently active command */
unsigned short queue_depth; /* How deep of a queue we want */
unsigned short last_queue_full_depth; /* These two are used by */
unsigned short state;
unsigned short owner;
Scsi_Request *sc_request;
- struct scsi_cmnd *next;
struct scsi_cmnd *reset_chain;
struct list_head list; /* scsi_cmnd participates in queue lists */
found = 0;
list_for_each_entry(sdev, &shost->my_devices, siblings) {
- for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&sdev->list_lock, flags);
+ list_for_each_entry(scmd, &sdev->cmd_list, list) {
if (scsi_eh_eflags_chk(scmd, SCSI_EH_CMD_ERR)) {
scmd->bh_next = *sc_list;
*sc_list = scmd;
}
}
}
+ spin_unlock_irqrestore(&sdev->list_lock, flags);
}
SCSI_LOG_ERROR_RECOVERY(1, scsi_eh_prt_fail_stats(*sc_list, shost));
int
scsi_reset_provider(Scsi_Device *dev, int flag)
{
- struct scsi_cmnd SC, *SCpnt = &SC;
+ struct scsi_cmnd *SCpnt = scsi_get_command(dev, GFP_KERNEL);
struct request req;
int rtn;
SCpnt->request = &req;
memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));
- SCpnt->device = dev;
SCpnt->request->rq_status = RQ_SCSI_BUSY;
- SCpnt->request->waiting = NULL;
- SCpnt->use_sg = 0;
- SCpnt->old_use_sg = 0;
- SCpnt->old_cmd_len = 0;
- SCpnt->underflow = 0;
- SCpnt->transfersize = 0;
- SCpnt->resid = 0;
- SCpnt->serial_number = 0;
- SCpnt->serial_number_at_timeout = 0;
- SCpnt->host_scribble = NULL;
- SCpnt->next = NULL;
SCpnt->state = SCSI_STATE_INITIALIZING;
SCpnt->owner = SCSI_OWNER_MIDLEVEL;
rtn = scsi_new_reset(SCpnt, flag);
scsi_delete_timer(SCpnt);
+ scsi_put_command(SCpnt);
return rtn;
}
printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) "
"(ret all flg) (to/cmd to ito) cmd snse result\n");
list_for_each_entry(SDpnt, &shpnt->my_devices, siblings) {
- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&SDpnt->list_lock, flags);
+ list_for_each_entry(SCpnt, &SDpnt->cmd_list, list) {
/* (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x */
printk(KERN_INFO "(%3d) %2d:%1d:%2d:%2d (%6s %4llu %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n",
i++,
SCpnt->sense_buffer[2],
SCpnt->result);
}
+ spin_unlock_irqrestore(&SDpnt->list_lock, flags);
}
}
}
sdev->online = TRUE;
INIT_LIST_HEAD(&sdev->siblings);
INIT_LIST_HEAD(&sdev->same_target_siblings);
+ spin_lock_init(&sdev->list_lock);
/*
* Some low level driver could use device->type
*/