Commit 2f1b8457 authored by Jamie Lenehan's avatar Jamie Lenehan Committed by James Bottomley

[PATCH] dc395x - list handling cleanups

Here's another patch in the "try and make the driver readable"
cleanup series. This one cleans up all of the list handling.

Description: Replaced the various hand crafted scsi req lists
(waiting and going in the dcb and free in the acb) and the dcb list
(in the acb) with the generic linux lists. This makes all of the list
related code a *lot* more readable then it was previously.
parent 07bc1c68
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/list.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Features Features
...@@ -306,7 +307,7 @@ struct NvRamType { ...@@ -306,7 +307,7 @@ struct NvRamType {
SCSI Request Block SCSI Request Block
-----------------------------------------------------------------------*/ -----------------------------------------------------------------------*/
struct ScsiReqBlk { struct ScsiReqBlk {
struct ScsiReqBlk *next; struct list_head list; /* next/prev ptrs for srb lists */
struct DeviceCtlBlk *dcb; struct DeviceCtlBlk *dcb;
/* HW scatter list (up to 64 entries) */ /* HW scatter list (up to 64 entries) */
...@@ -350,22 +351,16 @@ struct ScsiReqBlk { ...@@ -350,22 +351,16 @@ struct ScsiReqBlk {
Device Control Block Device Control Block
-----------------------------------------------------------------------*/ -----------------------------------------------------------------------*/
struct DeviceCtlBlk { struct DeviceCtlBlk {
struct DeviceCtlBlk *next; struct list_head list; /* next/prev ptrs for the dcb list */
struct AdapterCtlBlk *acb; struct AdapterCtlBlk *acb;
struct list_head srb_going_list; /* head of going srb list */
struct ScsiReqBlk *going_srb; struct list_head srb_waiting_list; /* head of waiting srb list */
struct ScsiReqBlk *going_last;
struct ScsiReqBlk *waiting_srb;
struct ScsiReqBlk *wait_list;
struct ScsiReqBlk *active_srb; struct ScsiReqBlk *active_srb;
u32 tag_mask; u32 tag_mask;
u16 max_command; u16 max_command;
u16 going_srb_count;
u16 waiting_srb_count;
u8 target_id; /* SCSI Target ID (SCSI Only) */ u8 target_id; /* SCSI Target ID (SCSI Only) */
u8 target_lun; /* SCSI Log. Unit (SCSI Only) */ u8 target_lun; /* SCSI Log. Unit (SCSI Only) */
u8 identify_msg; u8 identify_msg;
...@@ -390,20 +385,17 @@ struct AdapterCtlBlk { ...@@ -390,20 +385,17 @@ struct AdapterCtlBlk {
u16 IOPortBase; u16 IOPortBase;
struct DeviceCtlBlk *link_dcb; struct list_head dcb_list; /* head of going dcb list */
struct DeviceCtlBlk *last_dcb;
struct DeviceCtlBlk *dcb_run_robin; struct DeviceCtlBlk *dcb_run_robin;
struct DeviceCtlBlk *active_dcb; struct DeviceCtlBlk *active_dcb;
struct ScsiReqBlk *free_srb; struct list_head srb_free_list; /* head of free srb list */
struct ScsiReqBlk *tmp_srb; struct ScsiReqBlk *tmp_srb;
struct timer_list waiting_timer; struct timer_list waiting_timer;
struct timer_list selto_timer; struct timer_list selto_timer;
u16 srb_count; u16 srb_count;
u8 dcb_count;
u8 sel_timeout; u8 sel_timeout;
u8 irq_level; u8 irq_level;
...@@ -824,6 +816,60 @@ void __init eeprom_override(struct NvRamType *eeprom) ...@@ -824,6 +816,60 @@ void __init eeprom_override(struct NvRamType *eeprom)
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/**
* list_size - Returns the size (in number of entries) of the
* supplied list.
*
* @head: The pointer to the head of the list to count the items in.
**/
unsigned int list_size(struct list_head *head)
{
unsigned int count = 0;
struct list_head *pos;
list_for_each(pos, head)
count++;
return count;
}
/**
* dcb_get_next - Given a dcb return the next dcb in the list of
* dcb's, wrapping back to the start of the dcb list if required.
* Returns the supplied dcb if there is only one dcb in the list.
*
* @head: The pointer to the head of the list to count the items in.
* @pos: The pointer the dcb for which we are searching for the
* following dcb.
**/
struct DeviceCtlBlk *dcb_get_next(
struct list_head *head,
struct DeviceCtlBlk *pos)
{
int use_next = 0;
struct DeviceCtlBlk* next = NULL;
struct DeviceCtlBlk* i;
if (list_empty(head))
return NULL;
/* find supplied dcb and then select the next one */
list_for_each_entry(i, head, list)
if (use_next) {
next = i;
break;
} else if (i == pos) {
use_next = 1;
}
/* if no next one take the head one (ie, wraparound) */
if (!next)
list_for_each_entry(i, head, list) {
next = i;
break;
}
return next;
}
/* /*
* Queueing philosphy: * Queueing philosphy:
...@@ -851,200 +897,153 @@ void free_tag(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) ...@@ -851,200 +897,153 @@ void free_tag(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
/* Find cmd in SRB list */ /* Find cmd in SRB list */
inline static inline static
struct ScsiReqBlk *find_cmd(Scsi_Cmnd * cmd, struct ScsiReqBlk *find_cmd(Scsi_Cmnd *cmd,
struct ScsiReqBlk *start) struct list_head *head)
{ {
struct ScsiReqBlk *psrb = start; struct ScsiReqBlk *i;
if (!start) list_for_each_entry(i, head, list)
return 0; if (i->cmd == cmd)
do { return i;
if (psrb->cmd == cmd) return NULL;
return psrb;
psrb = psrb->next;
} while (psrb && psrb != start);
return 0;
} }
/* Return next free SRB */ /*
static inline * srb_get_free - Return a free srb from the list of free SRBs that
struct ScsiReqBlk *get_srb_free(struct AdapterCtlBlk *acb) * is stored with the acb.
*/
static
struct ScsiReqBlk *srb_get_free(struct AdapterCtlBlk *acb)
{ {
struct list_head *head = &acb->srb_free_list;
struct ScsiReqBlk *srb; struct ScsiReqBlk *srb;
/*DC395x_Free_integrity (acb); */ if (!list_empty(head)) {
srb = acb->free_srb; srb = list_entry(head->next, struct ScsiReqBlk, list);
if (!srb) list_del(head->next);
dprintkdbg(DBG_0, "srb_get_free: got srb %p\n", srb);
} else {
srb = NULL;
dprintkl(KERN_ERR, "Out of Free SRBs :-(\n"); dprintkl(KERN_ERR, "Out of Free SRBs :-(\n");
if (srb) {
acb->free_srb = srb->next;
srb->next = NULL;
} }
return srb; return srb;
} }
/* Insert SRB oin top of free list */ /*
static inline * srb_free_insert - Insert an srb to the head of the free list
void insert_srb_free(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) * stored in the acb.
*/
static
void srb_free_insert(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
{ {
dprintkdbg(DBG_0, "Free SRB %p\n", srb); dprintkdbg(DBG_0, "srb_free_insert: put srb %p\n", srb);
srb->next = acb->free_srb; list_add_tail(&srb->list, &acb->srb_free_list);
acb->free_srb = srb;
} }
/* Inserts a SRB to the top of the Waiting list */ /*
static inline * srb_waiting_insert - Insert an srb to the head of the wiating list
void insert_srb_waiting(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) * stored in the dcb.
*/
static
void srb_waiting_insert(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
{ {
dprintkdbg(DBG_0, "Insert srb %p cmd %li to Waiting\n", srb, srb->cmd->pid); dprintkdbg(DBG_0, "srb_waiting_insert: srb %p cmd %li\n", srb, srb->cmd->pid);
srb->next = dcb->waiting_srb; list_add(&srb->list, &dcb->srb_waiting_list);
if (!dcb->waiting_srb)
dcb->wait_list = srb;
dcb->waiting_srb = srb;
dcb->waiting_srb_count++;
} }
/* Queue SRB to waiting list */ /*
* srb_waiting_append - Append an srb to the tail of the waiting list
* stored in the dcb.
*/
static inline static inline
void append_srb_waiting(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) void srb_waiting_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
{ {
dprintkdbg(DBG_0, "Append srb %p cmd %li to Waiting\n", srb, srb->cmd->pid); dprintkdbg(DBG_0, "srb_waiting_append: srb %p cmd %li\n", srb, srb->cmd->pid);
if (dcb->waiting_srb) list_add_tail(&srb->list, &dcb->srb_waiting_list);
dcb->wait_list->next = srb;
else
dcb->waiting_srb = srb;
dcb->wait_list = srb;
/* No next one in waiting list */
srb->next = NULL;
dcb->waiting_srb_count++;
} }
/*
* srb_going_append - Append an srb to the tail of the going list
* stored in the dcb.
*/
static inline static inline
void append_srb_going(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
{ {
dprintkdbg(DBG_0, "Append SRB %p to Going\n", srb); dprintkdbg(DBG_0, "srb_going_append: srb %p\n", srb);
/* Append to the list of Going commands */ list_add_tail(&srb->list, &dcb->srb_going_list);
if (dcb->going_srb)
dcb->going_last->next = srb;
else
dcb->going_srb = srb;
dcb->going_last = srb;
/* No next one in sent list */
srb->next = NULL;
dcb->going_srb_count++;
} }
/* Find predecessor SRB */
inline static
struct ScsiReqBlk *find_srb_prev(struct ScsiReqBlk *srb,
struct ScsiReqBlk *start)
{
struct ScsiReqBlk *p = start;
if (!start)
return 0;
do {
if (p->next == srb)
return p;
p = p->next;
} while (p && p != start);
return 0;
}
/*
/* Remove SRB from SRB queue */ * srb_going_remove - Remove an srb from the going list stored in the
inline static * dcb.
struct ScsiReqBlk *remove_srb(struct ScsiReqBlk *srb, */
struct ScsiReqBlk *pre) static
void srb_going_remove(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{ {
if (pre->next != srb) struct ScsiReqBlk *i;
pre = find_srb_prev(srb, pre); struct ScsiReqBlk *tmp;
if (!pre) { dprintkdbg(DBG_0, "srb_going_remove: srb %p\n", srb);
dprintkl(KERN_ERR, "Internal ERROR: SRB to rmv not found in Q!\n");
return 0; list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list)
if (i == srb) {
list_del(&srb->list);
break;
} }
pre->next = srb->next;
/*srb->next = NULL; */
return pre;
} }
/* Remove SRB from Going queue */ /*
* srb_waiting_remove - Remove an srb from the waiting list stored in the
* dcb.
*/
static static
void remove_srb_going(struct DeviceCtlBlk *dcb, void srb_waiting_remove(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb, struct ScsiReqBlk *srb)
struct ScsiReqBlk *hint)
{ {
struct ScsiReqBlk *pre = NULL; struct ScsiReqBlk *i;
dprintkdbg(DBG_0, "Remove SRB %p from Going\n", srb); struct ScsiReqBlk *tmp;
if (!srb) dprintkdbg(DBG_0, "srb_waiting_remove: srb %p\n", srb);
dprintkl(KERN_ERR, "Going_remove %p!\n", srb);
if (srb == dcb->going_srb)
dcb->going_srb = srb->next;
else if (hint && hint->next == srb)
pre = remove_srb(srb, hint);
else
pre = remove_srb(srb, dcb->going_srb);
if (srb == dcb->going_last)
dcb->going_last = pre;
dcb->going_srb_count--;
}
/* Remove SRB from Waiting queue */ list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list)
static if (i == srb) {
void remove_srb_waiting(struct DeviceCtlBlk *dcb, list_del(&srb->list);
struct ScsiReqBlk *srb, break;
struct ScsiReqBlk *hint) }
{
struct ScsiReqBlk *pre = NULL;
dprintkdbg(DBG_0, "Remove SRB %p from Waiting\n", srb);
if (!srb)
dprintkl(KERN_ERR, "Waiting_remove %p!\n", srb);
if (srb == dcb->waiting_srb)
dcb->waiting_srb = srb->next;
else if (hint && hint->next == srb)
pre = remove_srb(srb, hint);
else
pre = remove_srb(srb, dcb->waiting_srb);
if (srb == dcb->wait_list)
dcb->wait_list = pre;
dcb->waiting_srb_count--;
} }
/* Moves SRB from Going list to the top of Waiting list */ /*
* srb_going_to_waiting_move - Remove an srb from the going list in
* the dcb and insert it at the head of the waiting list in the dcb.
*/
static static
void move_srb_going_to_waiting(struct DeviceCtlBlk *dcb, void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb) struct ScsiReqBlk *srb)
{ {
dprintkdbg(DBG_0, "Going_to_Waiting (SRB %p) pid = %li\n", srb, srb->cmd->pid); dprintkdbg(DBG_0, "srb_going_waiting_move: srb %p, pid = %li\n", srb, srb->cmd->pid);
/* Remove SRB from Going */ list_move(&srb->list, &dcb->srb_waiting_list);
remove_srb_going(dcb, srb, 0);
TRACEPRINTF("GtW *");
/* Insert on top of Waiting */
insert_srb_waiting(dcb, srb);
/* Tag Mask must be freed elsewhere ! (KG, 99/06/18) */
} }
/* Moves first SRB from Waiting list to Going list */ /*
static inline * srb_waiting_to_going_move - Remove an srb from the waiting list in
void move_srb_waiting_to_going(struct DeviceCtlBlk *dcb, * the dcb and insert it at the head of the going list in the dcb.
*/
static
void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb) struct ScsiReqBlk *srb)
{ {
/* Remove from waiting list */ /* Remove from waiting list */
dprintkdbg(DBG_0, "Remove SRB %p from head of Waiting\n", srb); dprintkdbg(DBG_0, "srb_waiting_to_going: srb %p\n", srb);
remove_srb_waiting(dcb, srb, 0);
TRACEPRINTF("WtG *"); TRACEPRINTF("WtG *");
append_srb_going(dcb, srb); list_move(&srb->list, &dcb->srb_going_list);
} }
...@@ -1070,39 +1069,66 @@ void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to) ...@@ -1070,39 +1069,66 @@ void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to)
static static
void waiting_process_next(struct AdapterCtlBlk *acb) void waiting_process_next(struct AdapterCtlBlk *acb)
{ {
struct DeviceCtlBlk *ptr; struct DeviceCtlBlk *start = NULL;
struct DeviceCtlBlk *ptr1; struct DeviceCtlBlk *pos;
struct DeviceCtlBlk *dcb;
struct ScsiReqBlk *srb; struct ScsiReqBlk *srb;
struct list_head *dcb_list_head = &acb->dcb_list;
if ((acb->active_dcb) if ((acb->active_dcb)
|| (acb->acb_flag & (RESET_DETECT + RESET_DONE + RESET_DEV))) || (acb->acb_flag & (RESET_DETECT + RESET_DONE + RESET_DEV)))
return; return;
if (timer_pending(&acb->waiting_timer)) if (timer_pending(&acb->waiting_timer))
del_timer(&acb->waiting_timer); del_timer(&acb->waiting_timer);
ptr = acb->dcb_run_robin;
if (!ptr) { /* This can happen! */ if (list_empty(dcb_list_head))
ptr = acb->link_dcb;
acb->dcb_run_robin = ptr;
}
ptr1 = ptr;
if (!ptr1)
return; return;
/*
* Find the starting dcb. Need to find it again in the list
* since the list may have changed since we set the ptr to it
*/
list_for_each_entry(dcb, dcb_list_head, list)
if (dcb == acb->dcb_run_robin) {
start = dcb;
break;
}
if (!start) {
/* This can happen! */
start = list_entry(dcb_list_head->next, typeof(*start), list);
acb->dcb_run_robin = start;
}
/*
* Loop over the dcb, but we start somewhere (potentially) in
* the middle of the loop so we need to manully do this.
*/
pos = start;
do { do {
struct list_head *waiting_list_head = &pos->srb_waiting_list;
/* Make sure, the next another device gets scheduled ... */ /* Make sure, the next another device gets scheduled ... */
acb->dcb_run_robin = ptr1->next; acb->dcb_run_robin = dcb_get_next(dcb_list_head,
if (!(srb = ptr1->waiting_srb) acb->dcb_run_robin);
|| (ptr1->max_command <= ptr1->going_srb_count))
ptr1 = ptr1->next; if (list_empty(waiting_list_head) ||
else { pos->max_command <= list_size(&pos->srb_going_list)) {
/* move to next dcb */
pos = dcb_get_next(dcb_list_head, pos);
} else {
srb = list_entry(waiting_list_head->next,
struct ScsiReqBlk, list);
/* Try to send to the bus */ /* Try to send to the bus */
if (!start_scsi(acb, ptr1, srb)) if (!start_scsi(acb, pos, srb))
move_srb_waiting_to_going(ptr1, srb); srb_waiting_to_going_move(pos, srb);
else else
waiting_set_timer(acb, HZ / 50); waiting_set_timer(acb, HZ/50);
break; break;
} }
} while (ptr1 != ptr); } while (pos != start);
return;
} }
...@@ -1141,30 +1167,18 @@ void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) ...@@ -1141,30 +1167,18 @@ void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
struct DeviceCtlBlk *dcb; struct DeviceCtlBlk *dcb;
dcb = srb->dcb; dcb = srb->dcb;
if ((dcb->max_command <= dcb->going_srb_count) || if (dcb->max_command <= list_size(&dcb->srb_going_list) ||
(acb->active_dcb) || acb->active_dcb ||
(acb->acb_flag & (RESET_DETECT + RESET_DONE + RESET_DEV))) { (acb->acb_flag & (RESET_DETECT + RESET_DONE + RESET_DEV))) {
append_srb_waiting(dcb, srb); srb_waiting_append(dcb, srb);
waiting_process_next(acb); waiting_process_next(acb);
return; return;
} }
#if 0
if (dcb->waiting_srb) {
append_srb_waiting(dcb, srb);
/* srb = waiting_srb_get(dcb); *//* non-existent */
srb = dcb->waiting_srb;
/* Remove from waiting list */
dcb->waiting_srb = srb->next;
srb->next = NULL;
if (!dcb->waiting_srb)
dcb->wait_list = NULL;
}
#endif
if (!start_scsi(acb, dcb, srb)) if (!start_scsi(acb, dcb, srb)) {
append_srb_going(dcb, srb); srb_going_append(dcb, srb);
else { } else {
insert_srb_waiting(dcb, srb); srb_waiting_insert(dcb, srb);
waiting_set_timer(acb, HZ / 50); waiting_set_timer(acb, HZ / 50);
} }
} }
...@@ -1391,7 +1405,7 @@ dc395x_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) ...@@ -1391,7 +1405,7 @@ dc395x_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
cmd->result = 0; cmd->result = 0;
/* get a free SRB */ /* get a free SRB */
srb = get_srb_free(acb); srb = srb_get_free(acb);
if (!srb) if (!srb)
{ {
/* /*
...@@ -1405,9 +1419,9 @@ dc395x_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) ...@@ -1405,9 +1419,9 @@ dc395x_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
/* build srb for the command */ /* build srb for the command */
build_srb(cmd, dcb, srb); build_srb(cmd, dcb, srb);
if (dcb->waiting_srb) { if (!list_empty(&dcb->srb_waiting_list)) {
/* append to waiting queue */ /* append to waiting queue */
append_srb_waiting(dcb, srb); srb_waiting_append(dcb, srb);
waiting_process_next(acb); waiting_process_next(acb);
} else { } else {
/* process immediately */ /* process immediately */
...@@ -1609,17 +1623,13 @@ static inline void clear_fifo(struct AdapterCtlBlk *acb, char *txt) ...@@ -1609,17 +1623,13 @@ static inline void clear_fifo(struct AdapterCtlBlk *acb, char *txt)
*/ */
static void reset_dev_param(struct AdapterCtlBlk *acb) static void reset_dev_param(struct AdapterCtlBlk *acb)
{ {
struct DeviceCtlBlk *dcb = acb->link_dcb; struct DeviceCtlBlk *dcb;
struct DeviceCtlBlk *dcb_temp;
struct NvRamType *eeprom = &acb->eeprom; struct NvRamType *eeprom = &acb->eeprom;
u8 period_index;
dprintkdbg(DBG_0, "reset_dev_param..............\n"); dprintkdbg(DBG_0, "reset_dev_param..............\n");
if (dcb == NULL) list_for_each_entry(dcb, &acb->dcb_list, list) {
return; u8 period_index;
dcb_temp = dcb;
do {
dcb->sync_mode &= ~(SYNC_NEGO_DONE + WIDE_NEGO_DONE); dcb->sync_mode &= ~(SYNC_NEGO_DONE + WIDE_NEGO_DONE);
dcb->sync_period = 0; dcb->sync_period = 0;
dcb->sync_offset = 0; dcb->sync_offset = 0;
...@@ -1631,10 +1641,7 @@ static void reset_dev_param(struct AdapterCtlBlk *acb) ...@@ -1631,10 +1641,7 @@ static void reset_dev_param(struct AdapterCtlBlk *acb)
if (!(dcb->dev_mode & NTC_DO_WIDE_NEGO) if (!(dcb->dev_mode & NTC_DO_WIDE_NEGO)
|| !(acb->config & HCC_WIDE_CARD)) || !(acb->config & HCC_WIDE_CARD))
dcb->sync_mode &= ~WIDE_NEGO_ENABLE; dcb->sync_mode &= ~WIDE_NEGO_ENABLE;
dcb = dcb->next;
} }
while (dcb_temp != dcb && dcb != NULL);
} }
...@@ -1729,18 +1736,18 @@ static int dc395x_eh_abort(Scsi_Cmnd * cmd) ...@@ -1729,18 +1736,18 @@ static int dc395x_eh_abort(Scsi_Cmnd * cmd)
return FAILED; return FAILED;
} }
srb = find_cmd(cmd, dcb->waiting_srb); srb = find_cmd(cmd, &dcb->srb_waiting_list);
if (srb) { if (srb) {
remove_srb_waiting(dcb, srb, 0); srb_waiting_remove(dcb, srb);
pci_unmap_srb_sense(acb, srb); pci_unmap_srb_sense(acb, srb);
pci_unmap_srb(acb, srb); pci_unmap_srb(acb, srb);
free_tag(dcb, srb); free_tag(dcb, srb);
insert_srb_free(acb, srb); srb_free_insert(acb, srb);
dprintkl(KERN_DEBUG, "abort - command found in waiting commands queue"); dprintkl(KERN_DEBUG, "abort - command found in waiting commands queue");
cmd->result = DID_ABORT << 16; cmd->result = DID_ABORT << 16;
return SUCCESS; return SUCCESS;
} }
srb = find_cmd(cmd, dcb->going_srb); srb = find_cmd(cmd, &dcb->srb_going_list);
if (srb) { if (srb) {
dprintkl(KERN_DEBUG, "abort - command currently in progress"); dprintkl(KERN_DEBUG, "abort - command currently in progress");
/* XXX: Should abort the command here */ /* XXX: Should abort the command here */
...@@ -3322,23 +3329,27 @@ struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, ...@@ -3322,23 +3329,27 @@ struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
struct DeviceCtlBlk *dcb, struct DeviceCtlBlk *dcb,
u8 tag) u8 tag)
{ {
struct ScsiReqBlk *last_srb = dcb->going_last; struct ScsiReqBlk *srb = NULL;
struct ScsiReqBlk *srb = dcb->going_srb; struct ScsiReqBlk *i;
dprintkdbg(DBG_0, "QTag Msg (SRB %p): %i\n", srb, tag); dprintkdbg(DBG_0, "QTag Msg (SRB %p): %i\n", srb, tag);
if (!(dcb->tag_mask & (1 << tag))) if (!(dcb->tag_mask & (1 << tag)))
dprintkl(KERN_DEBUG, dprintkl(KERN_DEBUG,
"MsgIn_QTag: tag_mask (%08x) does not reserve tag %i!\n", "MsgIn_QTag: tag_mask (%08x) does not reserve tag %i!\n",
dcb->tag_mask, tag); dcb->tag_mask, tag);
if (!srb) if (list_empty(&dcb->srb_going_list))
goto mingx0; goto mingx0;
while (srb) { list_for_each_entry(i, &dcb->srb_going_list, list) {
if (srb->tag_number == tag) if (i->tag_number == tag) {
srb = i;
break; break;
if (srb == last_srb)
goto mingx0;
srb = srb->next;
} }
}
if (!srb)
goto mingx0;
dprintkdbg(DBG_0, "pid %li (%i-%i)\n", srb->cmd->pid, dprintkdbg(DBG_0, "pid %li (%i-%i)\n", srb->cmd->pid,
srb->dcb->target_id, srb->dcb->target_lun); srb->dcb->target_id, srb->dcb->target_lun);
if (dcb->flag & ABORT_DEV_) { if (dcb->flag & ABORT_DEV_) {
...@@ -3350,13 +3361,18 @@ struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, ...@@ -3350,13 +3361,18 @@ struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
goto mingx0; goto mingx0;
/* Tag found */ /* Tag found */
{
struct ScsiReqBlk *last_srb;
TRACEPRINTF("[%s]*", dcb->active_srb->debugtrace); TRACEPRINTF("[%s]*", dcb->active_srb->debugtrace);
TRACEPRINTF("RTag*"); TRACEPRINTF("RTag*");
/* Just for debugging ... */ /* Just for debugging ... */
last_srb = srb; last_srb = srb;
srb = dcb->active_srb; srb = dcb->active_srb;
TRACEPRINTF("Found.*"); TRACEPRINTF("Found.*");
srb = last_srb; srb = last_srb;
}
memcpy(srb->msgin_buf, dcb->active_srb->msgin_buf, acb->msg_len); memcpy(srb->msgin_buf, dcb->active_srb->msgin_buf, acb->msg_len);
srb->state |= dcb->active_srb->state; srb->state |= dcb->active_srb->state;
...@@ -3774,36 +3790,26 @@ void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -3774,36 +3790,26 @@ void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static static
void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb)
{ {
u8 bval; struct DeviceCtlBlk *i;
u16 cnt, i;
struct DeviceCtlBlk *dcb_temp;
/* /*
** set all lun device's period , offset * set all lun device's period , offset
*/ */
if (!(dcb->identify_msg & 0x07)) { if (dcb->identify_msg & 0x07)
if (acb->scan_devices) return;
if (acb->scan_devices) {
current_sync_offset = dcb->sync_offset; current_sync_offset = dcb->sync_offset;
else { return;
dcb_temp = acb->link_dcb;
cnt = acb->dcb_count;
bval = dcb->target_id;
for (i = 0; i < cnt; i++) {
if (dcb_temp->target_id == bval) {
dcb_temp->sync_period =
dcb->sync_period;
dcb_temp->sync_offset =
dcb->sync_offset;
dcb_temp->sync_mode =
dcb->sync_mode;
dcb_temp->min_nego_period =
dcb->min_nego_period;
}
dcb_temp = dcb_temp->next;
}
} }
list_for_each_entry(i, &acb->dcb_list, list)
if (i->target_id == dcb->target_id) {
i->sync_period = dcb->sync_period;
i->sync_offset = dcb->sync_offset;
i->sync_mode = dcb->sync_mode;
i->min_nego_period = dcb->min_nego_period;
} }
return;
} }
...@@ -3882,7 +3888,7 @@ static void disconnect(struct AdapterCtlBlk *acb) ...@@ -3882,7 +3888,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
goto disc1; goto disc1;
} }
free_tag(dcb, srb); free_tag(dcb, srb);
move_srb_going_to_waiting(dcb, srb); srb_going_to_waiting_move(dcb, srb);
dprintkdbg(DBG_KG, "Retry pid %li ...\n", dprintkdbg(DBG_KG, "Retry pid %li ...\n",
srb->cmd->pid); srb->cmd->pid);
waiting_set_timer(acb, HZ / 20); waiting_set_timer(acb, HZ / 20);
...@@ -3964,7 +3970,7 @@ static void reselect(struct AdapterCtlBlk *acb) ...@@ -3964,7 +3970,7 @@ static void reselect(struct AdapterCtlBlk *acb)
srb->state = SRB_READY; srb->state = SRB_READY;
free_tag(dcb, srb); free_tag(dcb, srb);
move_srb_going_to_waiting(dcb, srb); srb_going_to_waiting_move(dcb, srb);
waiting_set_timer(acb, HZ / 20); waiting_set_timer(acb, HZ / 20);
/* return; */ /* return; */
...@@ -4049,43 +4055,32 @@ static void reselect(struct AdapterCtlBlk *acb) ...@@ -4049,43 +4055,32 @@ static void reselect(struct AdapterCtlBlk *acb)
static static
void remove_dev(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) void remove_dev(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb)
{ {
struct DeviceCtlBlk *pPrevDCB = acb->link_dcb; struct DeviceCtlBlk *i;
struct DeviceCtlBlk *tmp;
dprintkdbg(DBG_0, "remove_dev\n"); dprintkdbg(DBG_0, "remove_dev\n");
if (dcb->going_srb_count > 1) { if (list_size(&dcb->srb_going_list) > 1) {
dprintkdbg(DBG_DCB, "Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n", dprintkdbg(DBG_DCB, "Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",
dcb->target_id, dcb->target_lun, (int) dcb, dcb->target_id, dcb->target_lun, (int) dcb,
dcb->going_srb_count); list_size(&dcb->srb_going_list));
return; return;
} }
acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun); acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun);
acb->children[dcb->target_id][dcb->target_lun] = NULL; acb->children[dcb->target_id][dcb->target_lun] = NULL;
/* The first one */ list_for_each_entry_safe(i, tmp, &acb->dcb_list, list) {
if (dcb == acb->link_dcb) { if (dcb == i) {
/* The last one */ list_del(&i->list);
if (acb->last_dcb == dcb) { break;
dcb->next = NULL;
acb->last_dcb = NULL;
} }
acb->link_dcb = dcb->next;
} else {
while (pPrevDCB->next != dcb)
pPrevDCB = pPrevDCB->next;
pPrevDCB->next = dcb->next;
if (dcb == acb->last_dcb)
acb->last_dcb = pPrevDCB;
} }
dprintkdbg(DBG_DCB, "Driver about to free DCB (ID %i, LUN %i): %p\n", dprintkdbg(DBG_DCB, "Driver about to free DCB (ID %i, LUN %i): %p\n",
dcb->target_id, dcb->target_lun, dcb); dcb->target_id, dcb->target_lun, dcb);
if (dcb == acb->active_dcb) if (dcb == acb->active_dcb)
acb->active_dcb = NULL; acb->active_dcb = NULL;
if (dcb == acb->link_dcb)
acb->link_dcb = dcb->next;
if (dcb == acb->dcb_run_robin) if (dcb == acb->dcb_run_robin)
acb->dcb_run_robin = dcb->next; acb->dcb_run_robin = dcb_get_next(&acb->dcb_list, dcb);
acb->dcb_count--;
dc395x_kfree(dcb); dc395x_kfree(dcb);
} }
...@@ -4320,7 +4315,7 @@ void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, ...@@ -4320,7 +4315,7 @@ void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
request_sense(acb, dcb, srb); request_sense(acb, dcb, srb);
return; return;
} else if (status_byte(status) == QUEUE_FULL) { } else if (status_byte(status) == QUEUE_FULL) {
tempcnt = (u8) dcb->going_srb_count; tempcnt = (u8)list_size(&dcb->srb_going_list);
printk printk
("\nDC395x: QUEUE_FULL for dev %02i-%i with %i cmnds\n", ("\nDC395x: QUEUE_FULL for dev %02i-%i with %i cmnds\n",
dcb->target_id, dcb->target_lun, tempcnt); dcb->target_id, dcb->target_lun, tempcnt);
...@@ -4328,7 +4323,7 @@ void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, ...@@ -4328,7 +4323,7 @@ void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
tempcnt--; tempcnt--;
dcb->max_command = tempcnt; dcb->max_command = tempcnt;
free_tag(dcb, srb); free_tag(dcb, srb);
move_srb_going_to_waiting(dcb, srb); srb_going_to_waiting_move(dcb, srb);
waiting_set_timer(acb, HZ / 20); waiting_set_timer(acb, HZ / 20);
srb->adapter_status = 0; srb->adapter_status = 0;
srb->target_status = 0; srb->target_status = 0;
...@@ -4409,12 +4404,12 @@ void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, ...@@ -4409,12 +4404,12 @@ void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
cmd->device->lun, srb->total_xfer_length); cmd->device->lun, srb->total_xfer_length);
} }
remove_srb_going(dcb, srb, 0); srb_going_remove(dcb, srb);
/* Add to free list */ /* Add to free list */
if (srb == acb->tmp_srb) if (srb == acb->tmp_srb)
dprintkl(KERN_ERR, "ERROR! Completed Cmnd with tmp_srb!\n"); dprintkl(KERN_ERR, "ERROR! Completed Cmnd with tmp_srb!\n");
else else
insert_srb_free(acb, srb); srb_free_insert(acb, srb);
dprintkdbg(DBG_0, "SRBdone: done pid %li\n", cmd->pid); dprintkdbg(DBG_0, "SRBdone: done pid %li\n", cmd->pid);
if (debug_enabled(DBG_KG)) { if (debug_enabled(DBG_KG)) {
...@@ -4444,30 +4439,21 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, ...@@ -4444,30 +4439,21 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
Scsi_Cmnd * cmd, u8 force) Scsi_Cmnd * cmd, u8 force)
{ {
struct DeviceCtlBlk *dcb; struct DeviceCtlBlk *dcb;
dprintkl(KERN_INFO, "doing_srb_done: pids ");
list_for_each_entry(dcb, &acb->dcb_list, list) {
struct ScsiReqBlk *srb; struct ScsiReqBlk *srb;
struct ScsiReqBlk *srb_temp; struct ScsiReqBlk *tmp;
u16 cnt;
Scsi_Cmnd *p; Scsi_Cmnd *p;
dcb = acb->link_dcb; list_for_each_entry_safe(srb, tmp, &dcb->srb_going_list, list) {
if (!dcb)
return;
dprintkl(KERN_INFO, "doing_srb_done: pids ");
do {
/* As the ML may queue cmnds again, cache old values */
struct ScsiReqBlk *waiting_srb = dcb->waiting_srb;
/*struct ScsiReqBlk* wait_list = dcb->wait_list; */
u16 waiting_srb_count = dcb->waiting_srb_count;
/* Going queue */
cnt = dcb->going_srb_count;
srb = dcb->going_srb;
while (cnt--) {
int result; int result;
int dir; int dir;
srb_temp = srb->next;
p = srb->cmd; p = srb->cmd;
dir = scsi_to_pci_dma_dir(p->sc_data_direction); dir = scsi_to_pci_dma_dir(p->sc_data_direction);
result = MK_RES(0, did_flag, 0, 0); result = MK_RES(0, did_flag, 0, 0);
/*result = MK_RES(0,DID_RESET,0,0); */ /*result = MK_RES(0,DID_RESET,0,0); */
TRACEPRINTF("Reset(%li):%08x*", jiffies, result); TRACEPRINTF("Reset(%li):%08x*", jiffies, result);
printk(" (G)"); printk(" (G)");
...@@ -4476,12 +4462,10 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, ...@@ -4476,12 +4462,10 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
p->device->id, p->device->lun); p->device->id, p->device->lun);
#endif #endif
TRACEOUT("%s\n", srb->debugtrace); TRACEOUT("%s\n", srb->debugtrace);
dcb->going_srb = srb_temp;
dcb->going_srb_count--; srb_going_remove(dcb, srb);
if (!srb_temp)
dcb->going_last = NULL;
free_tag(dcb, srb); free_tag(dcb, srb);
insert_srb_free(acb, srb); srb_free_insert(acb, srb);
p->result = result; p->result = result;
pci_unmap_srb_sense(acb, srb); pci_unmap_srb_sense(acb, srb);
pci_unmap_srb(acb, srb); pci_unmap_srb(acb, srb);
...@@ -4490,9 +4474,8 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, ...@@ -4490,9 +4474,8 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
* as they all complete or all time out */ * as they all complete or all time out */
p->scsi_done(p); p->scsi_done(p);
} }
srb = srb_temp;
} }
if (dcb->going_srb) if (!list_empty(&dcb->srb_going_list))
dprintkl(KERN_DEBUG, dprintkl(KERN_DEBUG,
"How could the ML send cmnds to the Going queue? (%02i-%i)!!\n", "How could the ML send cmnds to the Going queue? (%02i-%i)!!\n",
dcb->target_id, dcb->target_lun); dcb->target_id, dcb->target_lun);
...@@ -4501,16 +4484,12 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, ...@@ -4501,16 +4484,12 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
"tag_mask for %02i-%i should be empty, is %08x!\n", "tag_mask for %02i-%i should be empty, is %08x!\n",
dcb->target_id, dcb->target_lun, dcb->target_id, dcb->target_lun,
dcb->tag_mask); dcb->tag_mask);
/*dcb->going_srb_count = 0;; */
/*dcb->going_srb = NULL; dcb->going_last = NULL; */
/* Waiting queue */ /* Waiting queue */
cnt = waiting_srb_count; list_for_each_entry_safe(srb, tmp, &dcb->srb_waiting_list, list) {
srb = waiting_srb;
while (cnt--) {
int result; int result;
srb_temp = srb->next;
p = srb->cmd; p = srb->cmd;
result = MK_RES(0, did_flag, 0, 0); result = MK_RES(0, did_flag, 0, 0);
TRACEPRINTF("Reset(%li):%08x*", jiffies, result); TRACEPRINTF("Reset(%li):%08x*", jiffies, result);
printk(" (W)"); printk(" (W)");
...@@ -4519,11 +4498,8 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, ...@@ -4519,11 +4498,8 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
p->device->lun); p->device->lun);
#endif #endif
TRACEOUT("%s\n", srb->debugtrace); TRACEOUT("%s\n", srb->debugtrace);
dcb->waiting_srb = srb_temp; srb_waiting_remove(dcb, srb);
dcb->waiting_srb_count--; srb_free_insert(acb, srb);
if (!srb_temp)
dcb->wait_list = NULL;
insert_srb_free(acb, srb);
p->result = result; p->result = result;
pci_unmap_srb_sense(acb, srb); pci_unmap_srb_sense(acb, srb);
...@@ -4532,21 +4508,16 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, ...@@ -4532,21 +4508,16 @@ void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
/* For new EH, we normally don't need to give commands back, /* For new EH, we normally don't need to give commands back,
* as they all complete or all time out */ * as they all complete or all time out */
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
srb = srb_temp;
} }
} }
if (dcb->waiting_srb_count) if (!list_empty(&dcb->srb_waiting_list))
printk printk
("\nDC395x: Debug: ML queued %i cmnds again to %02i-%i\n", ("\nDC395x: Debug: ML queued %i cmnds again to %02i-%i\n",
dcb->waiting_srb_count, dcb->target_id, list_size(&dcb->srb_waiting_list), dcb->target_id,
dcb->target_lun); dcb->target_lun);
/* The ML could have queued the cmnds again! */
/*dcb->waiting_srb_count = 0;; */
/*dcb->waiting_srb = NULL; dcb->wait_list = NULL; */
dcb->flag &= ~ABORT_DEV_; dcb->flag &= ~ABORT_DEV_;
dcb = dcb->next;
} }
while (dcb != acb->link_dcb && dcb);
printk("\n"); printk("\n");
} }
...@@ -4703,7 +4674,7 @@ void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, ...@@ -4703,7 +4674,7 @@ void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
"Request Sense failed for pid %li (%02i-%i)!\n", "Request Sense failed for pid %li (%02i-%i)!\n",
srb->cmd->pid, dcb->target_id, dcb->target_lun); srb->cmd->pid, dcb->target_id, dcb->target_lun);
TRACEPRINTF("?*"); TRACEPRINTF("?*");
move_srb_going_to_waiting(dcb, srb); srb_going_to_waiting_move(dcb, srb);
waiting_set_timer(acb, HZ / 100); waiting_set_timer(acb, HZ / 100);
} }
TRACEPRINTF(".*"); TRACEPRINTF(".*");
...@@ -4736,26 +4707,17 @@ void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb, ...@@ -4736,26 +4707,17 @@ void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb,
if (!dcb) if (!dcb)
return; return;
if (acb->dcb_count == 0) { INIT_LIST_HEAD(&dcb->srb_waiting_list);
acb->link_dcb = dcb; INIT_LIST_HEAD(&dcb->srb_going_list);
if (list_empty(&acb->dcb_list))
acb->dcb_run_robin = dcb; acb->dcb_run_robin = dcb;
} else { list_add_tail(&dcb->list, &acb->dcb_list);
acb->last_dcb->next = dcb;
}
acb->dcb_count++;
dcb->next = acb->link_dcb;
acb->last_dcb = dcb;
/* $$$$$$$ */ /* $$$$$$$ */
dcb->acb = acb; dcb->acb = acb;
dcb->target_id = target; dcb->target_id = target;
dcb->target_lun = lun; dcb->target_lun = lun;
/* $$$$$$$ */ /* $$$$$$$ */
dcb->waiting_srb = NULL;
dcb->going_srb = NULL;
dcb->going_srb_count = 0;
dcb->waiting_srb_count = 0;
dcb->active_srb = NULL; dcb->active_srb = NULL;
/* $$$$$$$ */ /* $$$$$$$ */
dcb->tag_mask = 0; dcb->tag_mask = 0;
...@@ -4792,9 +4754,10 @@ void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb, ...@@ -4792,9 +4754,10 @@ void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb,
/* $$$$$$$ */ /* $$$$$$$ */
if (dcb->target_lun != 0) { if (dcb->target_lun != 0) {
/* Copy settings */ /* Copy settings */
struct DeviceCtlBlk *prevDCB = acb->link_dcb; struct DeviceCtlBlk *prevDCB;
while (prevDCB->target_id != dcb->target_id) list_for_each_entry(prevDCB, &acb->dcb_list, list)
prevDCB = prevDCB->next; if (prevDCB->target_id == dcb->target_id)
break;
dprintkdbg(DBG_KG, dprintkdbg(DBG_KG,
"Copy settings from %02i-%02i to %02i-%02i\n", "Copy settings from %02i-%02i to %02i-%02i\n",
prevDCB->target_id, prevDCB->target_lun, prevDCB->target_id, prevDCB->target_lun,
...@@ -4924,9 +4887,7 @@ static void __init link_srb(struct AdapterCtlBlk *acb) ...@@ -4924,9 +4887,7 @@ static void __init link_srb(struct AdapterCtlBlk *acb)
int i; int i;
for (i = 0; i < acb->srb_count - 1; i++) for (i = 0; i < acb->srb_count - 1; i++)
acb->srb_array[i].next = &acb->srb_array[i + 1]; srb_free_insert(acb, &acb->srb_array[i]);
acb->srb_array[i].next = NULL;
/*DC395x_Free_integrity (acb); */
} }
...@@ -4974,14 +4935,12 @@ int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq) ...@@ -4974,14 +4935,12 @@ int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq)
*/ */
acb->scsi_host = host; acb->scsi_host = host;
acb->IOPortBase = (u16) io_port; acb->IOPortBase = (u16) io_port;
acb->link_dcb = NULL;
acb->dcb_run_robin = NULL; acb->dcb_run_robin = NULL;
acb->active_dcb = NULL; acb->active_dcb = NULL;
acb->srb_count = DC395x_MAX_SRB_CNT; acb->srb_count = DC395x_MAX_SRB_CNT;
acb->scsi_host->this_id = eeprom->scsi_id; acb->scsi_host->this_id = eeprom->scsi_id;
acb->hostid_bit = (1 << acb->scsi_host->this_id); acb->hostid_bit = (1 << acb->scsi_host->this_id);
/*acb->scsi_host->this_lun = 0; */ /*acb->scsi_host->this_lun = 0; */
acb->dcb_count = 0;
acb->irq_level = irq; acb->irq_level = irq;
acb->tag_max_num = 1 << eeprom->max_tag; acb->tag_max_num = 1 << eeprom->max_tag;
if (acb->tag_max_num > 30) if (acb->tag_max_num > 30)
...@@ -5006,14 +4965,14 @@ int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq) ...@@ -5006,14 +4965,14 @@ int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq)
return 1; return 1;
} }
#endif #endif
INIT_LIST_HEAD(&acb->dcb_list);
INIT_LIST_HEAD(&acb->srb_free_list);
link_srb(acb); link_srb(acb);
acb->free_srb = acb->srb_array;
/* /*
* temp SRB for Q tag used or abort command used * temp SRB for Q tag used or abort command used
*/ */
acb->tmp_srb = &acb->srb; acb->tmp_srb = &acb->srb;
acb->srb.dcb = NULL;
acb->srb.next = NULL;
init_timer(&acb->waiting_timer); init_timer(&acb->waiting_timer);
for (i = 0; i < DC395x_MAX_SCSI_ID; i++) for (i = 0; i < DC395x_MAX_SCSI_ID; i++)
...@@ -5550,10 +5509,11 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o ...@@ -5550,10 +5509,11 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o
int inout) int inout)
{ {
struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
int dev, spd, spd1; int spd, spd1;
char *pos = buffer; char *pos = buffer;
struct DeviceCtlBlk *dcb; struct DeviceCtlBlk *dcb;
unsigned long flags; unsigned long flags;
int dev;
if (inout) /* Has data been written to the file ? */ if (inout) /* Has data been written to the file ? */
return -EPERM; return -EPERM;
...@@ -5580,7 +5540,7 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o ...@@ -5580,7 +5540,7 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o
SPRINTF(", DelayReset %is\n", acb->eeprom.delay_time); SPRINTF(", DelayReset %is\n", acb->eeprom.delay_time);
/*SPRINTF("\n"); */ /*SPRINTF("\n"); */
SPRINTF("Nr of DCBs: %i\n", acb->dcb_count); SPRINTF("Nr of DCBs: %i\n", list_size(&acb->dcb_list));
SPRINTF SPRINTF
("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n", ("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n",
acb->dcb_map[0], acb->dcb_map[1], acb->dcb_map[2], acb->dcb_map[0], acb->dcb_map[1], acb->dcb_map[2],
...@@ -5595,8 +5555,8 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o ...@@ -5595,8 +5555,8 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o
SPRINTF SPRINTF
("Un ID LUN Prty Sync Wide DsCn SndS TagQ nego_period SyncFreq SyncOffs MaxCmd\n"); ("Un ID LUN Prty Sync Wide DsCn SndS TagQ nego_period SyncFreq SyncOffs MaxCmd\n");
dcb = acb->link_dcb; dev = 0;
for (dev = 0; dev < acb->dcb_count; dev++) { list_for_each_entry(dcb, &acb->dcb_list, list) {
int nego_period; int nego_period;
SPRINTF("%02i %02i %02i ", dev, dcb->target_id, SPRINTF("%02i %02i %02i ", dev, dcb->target_id,
dcb->target_lun); dcb->target_lun);
...@@ -5606,8 +5566,7 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o ...@@ -5606,8 +5566,7 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o
YESNO(dcb->dev_mode & NTC_DO_DISCONNECT); YESNO(dcb->dev_mode & NTC_DO_DISCONNECT);
YESNO(dcb->dev_mode & NTC_DO_SEND_START); YESNO(dcb->dev_mode & NTC_DO_SEND_START);
YESNO(dcb->sync_mode & EN_TAG_QUEUEING); YESNO(dcb->sync_mode & EN_TAG_QUEUEING);
nego_period = nego_period = clock_period[dcb->sync_period & 0x07] << 2;
clock_period[dcb->sync_period & 0x07] << 2;
if (dcb->sync_offset) if (dcb->sync_offset)
SPRINTF(" %03i ns ", nego_period); SPRINTF(" %03i ns ", nego_period);
else else
...@@ -5624,45 +5583,42 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o ...@@ -5624,45 +5583,42 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o
/* Add more info ... */ /* Add more info ... */
SPRINTF(" %02i\n", dcb->max_command); SPRINTF(" %02i\n", dcb->max_command);
dcb = dcb->next; dev++;
} }
if (timer_pending(&acb->waiting_timer)) if (timer_pending(&acb->waiting_timer))
SPRINTF("Waiting queue timer running\n"); SPRINTF("Waiting queue timer running\n");
else else
SPRINTF("\n"); SPRINTF("\n");
dcb = acb->link_dcb;
for (dev = 0; dev < acb->dcb_count; dev++) { list_for_each_entry(dcb, &acb->dcb_list, list) {
struct ScsiReqBlk *srb; struct ScsiReqBlk *srb;
if (dcb->waiting_srb_count) if (!list_empty(&dcb->srb_waiting_list))
SPRINTF("DCB (%02i-%i): Waiting: %i:", SPRINTF("DCB (%02i-%i): Waiting: %i:",
dcb->target_id, dcb->target_lun, dcb->target_id, dcb->target_lun,
dcb->waiting_srb_count); list_size(&dcb->srb_waiting_list));
for (srb = dcb->waiting_srb; srb; srb = srb->next) list_for_each_entry(srb, &dcb->srb_waiting_list, list)
SPRINTF(" %li", srb->cmd->pid); SPRINTF(" %li", srb->cmd->pid);
if (dcb->going_srb_count) if (!list_empty(&dcb->srb_going_list))
SPRINTF("\nDCB (%02i-%i): Going : %i:", SPRINTF("\nDCB (%02i-%i): Going : %i:",
dcb->target_id, dcb->target_lun, dcb->target_id, dcb->target_lun,
dcb->going_srb_count); list_size(&dcb->srb_going_list));
for (srb = dcb->going_srb; srb; srb = srb->next) list_for_each_entry(srb, &dcb->srb_going_list, list)
#if debug_enabled(DBG_TRACE|DBG_TRACEALL) #if debug_enabled(DBG_TRACE|DBG_TRACEALL)
SPRINTF("\n %s", srb->debugtrace); SPRINTF("\n %s", srb->debugtrace);
#else #else
SPRINTF(" %li", srb->cmd->pid); SPRINTF(" %li", srb->cmd->pid);
#endif #endif
if (dcb->waiting_srb_count || dcb->going_srb_count) if (!list_empty(&dcb->srb_waiting_list) || !list_empty(&dcb->srb_going_list))
SPRINTF("\n"); SPRINTF("\n");
dcb = dcb->next;
} }
if (debug_enabled(DBG_DCB)) { if (debug_enabled(DBG_DCB)) {
SPRINTF("DCB list for ACB %p:\n", acb); SPRINTF("DCB list for ACB %p:\n", acb);
dcb = acb->link_dcb; list_for_each_entry(dcb, &acb->dcb_list, list) {
SPRINTF("%p", dcb); SPRINTF("%p -> ", dcb);
for (dev = 0; dev < acb->dcb_count; dev++, dcb = dcb->next) }
SPRINTF("->%p", dcb->next); SPRINTF("END\n");
SPRINTF("\n");
} }
*start = buffer + offset; *start = buffer + offset;
...@@ -5721,19 +5677,13 @@ static ...@@ -5721,19 +5677,13 @@ static
void free_dcbs(struct AdapterCtlBlk* acb) void free_dcbs(struct AdapterCtlBlk* acb)
{ {
struct DeviceCtlBlk *dcb; struct DeviceCtlBlk *dcb;
struct DeviceCtlBlk *dcb_next; struct DeviceCtlBlk *tmp;
dprintkdbg(DBG_DCB, "Free %i DCBs\n", acb->dcb_count); dprintkdbg(DBG_DCB, "Free %i DCBs\n", list_size(&acb->dcb_list));
for (dcb = acb->link_dcb; dcb != NULL; dcb = dcb_next) list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list) {
{
dcb_next = dcb->next;
dprintkdbg(DBG_DCB, "Free DCB (ID %i, LUN %i): %p\n", dprintkdbg(DBG_DCB, "Free DCB (ID %i, LUN %i): %p\n",
dcb->target_id, dcb->target_lun, dcb); dcb->target_id, dcb->target_lun, dcb);
/*
* Free the DCB. This removes the entry from the
* link_dcb list and decrements the count in dcb_count
*/
remove_dev(acb, dcb); remove_dev(acb, dcb);
} }
} }
......
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