#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
+#include <linux/list.h>
/*---------------------------------------------------------------------------
Features
SCSI Request Block
-----------------------------------------------------------------------*/
struct ScsiReqBlk {
- struct ScsiReqBlk *next;
+ struct list_head list; /* next/prev ptrs for srb lists */
struct DeviceCtlBlk *dcb;
/* HW scatter list (up to 64 entries) */
Device Control Block
-----------------------------------------------------------------------*/
struct DeviceCtlBlk {
- struct DeviceCtlBlk *next;
+ struct list_head list; /* next/prev ptrs for the dcb list */
struct AdapterCtlBlk *acb;
-
- struct ScsiReqBlk *going_srb;
- struct ScsiReqBlk *going_last;
-
- struct ScsiReqBlk *waiting_srb;
- struct ScsiReqBlk *wait_list;
+ struct list_head srb_going_list; /* head of going srb list */
+ struct list_head srb_waiting_list; /* head of waiting srb list */
struct ScsiReqBlk *active_srb;
u32 tag_mask;
u16 max_command;
- u16 going_srb_count;
- u16 waiting_srb_count;
u8 target_id; /* SCSI Target ID (SCSI Only) */
u8 target_lun; /* SCSI Log. Unit (SCSI Only) */
u8 identify_msg;
u16 IOPortBase;
- struct DeviceCtlBlk *link_dcb;
- struct DeviceCtlBlk *last_dcb;
+ struct list_head dcb_list; /* head of going dcb list */
struct DeviceCtlBlk *dcb_run_robin;
-
struct DeviceCtlBlk *active_dcb;
- struct ScsiReqBlk *free_srb;
+ struct list_head srb_free_list; /* head of free srb list */
struct ScsiReqBlk *tmp_srb;
struct timer_list waiting_timer;
struct timer_list selto_timer;
u16 srb_count;
- u8 dcb_count;
u8 sel_timeout;
u8 irq_level;
/*---------------------------------------------------------------------------
---------------------------------------------------------------------------*/
+/**
+ * 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:
/* Find cmd in SRB list */
inline static
-struct ScsiReqBlk *find_cmd(Scsi_Cmnd * cmd,
- struct ScsiReqBlk *start)
+struct ScsiReqBlk *find_cmd(Scsi_Cmnd *cmd,
+ struct list_head *head)
{
- struct ScsiReqBlk *psrb = start;
- if (!start)
- return 0;
- do {
- if (psrb->cmd == cmd)
- return psrb;
- psrb = psrb->next;
- } while (psrb && psrb != start);
- return 0;
+ struct ScsiReqBlk *i;
+ list_for_each_entry(i, head, list)
+ if (i->cmd == cmd)
+ return i;
+ return NULL;
}
-/* Return next free SRB */
-static inline
-struct ScsiReqBlk *get_srb_free(struct AdapterCtlBlk *acb)
+/*
+ * srb_get_free - Return a free srb from the list of free SRBs that
+ * 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;
- /*DC395x_Free_integrity (acb); */
- srb = acb->free_srb;
- if (!srb)
+ if (!list_empty(head)) {
+ srb = list_entry(head->next, struct ScsiReqBlk, list);
+ 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");
- if (srb) {
- acb->free_srb = srb->next;
- srb->next = NULL;
}
-
return srb;
}
-/* Insert SRB oin top of free list */
-static inline
-void insert_srb_free(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
+/*
+ * srb_free_insert - Insert an srb to the head of the free list
+ * stored in the acb.
+ */
+static
+void srb_free_insert(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
{
- dprintkdbg(DBG_0, "Free SRB %p\n", srb);
- srb->next = acb->free_srb;
- acb->free_srb = srb;
+ dprintkdbg(DBG_0, "srb_free_insert: put srb %p\n", srb);
+ list_add_tail(&srb->list, &acb->srb_free_list);
}
-/* Inserts a SRB to the top of the Waiting list */
-static inline
-void insert_srb_waiting(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
+/*
+ * srb_waiting_insert - Insert an srb to the head of the wiating list
+ * 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);
- srb->next = dcb->waiting_srb;
- if (!dcb->waiting_srb)
- dcb->wait_list = srb;
- dcb->waiting_srb = srb;
- dcb->waiting_srb_count++;
+ dprintkdbg(DBG_0, "srb_waiting_insert: srb %p cmd %li\n", srb, srb->cmd->pid);
+ list_add(&srb->list, &dcb->srb_waiting_list);
}
-/* Queue SRB to waiting list */
+/*
+ * srb_waiting_append - Append an srb to the tail of the waiting list
+ * stored in the dcb.
+ */
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);
- if (dcb->waiting_srb)
- 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++;
+ dprintkdbg(DBG_0, "srb_waiting_append: srb %p cmd %li\n", srb, srb->cmd->pid);
+ list_add_tail(&srb->list, &dcb->srb_waiting_list);
}
+/*
+ * srb_going_append - Append an srb to the tail of the going list
+ * stored in the dcb.
+ */
static inline
-void append_srb_going(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
-{
- dprintkdbg(DBG_0, "Append SRB %p to Going\n", srb);
- /* Append to the list of Going commands */
- 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)
+void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
{
- struct ScsiReqBlk *p = start;
- if (!start)
- return 0;
- do {
- if (p->next == srb)
- return p;
- p = p->next;
- } while (p && p != start);
- return 0;
+ dprintkdbg(DBG_0, "srb_going_append: srb %p\n", srb);
+ list_add_tail(&srb->list, &dcb->srb_going_list);
}
-/* Remove SRB from SRB queue */
-inline static
-struct ScsiReqBlk *remove_srb(struct ScsiReqBlk *srb,
- struct ScsiReqBlk *pre)
-{
- if (pre->next != srb)
- pre = find_srb_prev(srb, pre);
- if (!pre) {
- dprintkl(KERN_ERR, "Internal ERROR: SRB to rmv not found in Q!\n");
- return 0;
- }
- pre->next = srb->next;
- /*srb->next = NULL; */
- return pre;
-}
-
-/* Remove SRB from Going queue */
+/*
+ * srb_going_remove - Remove an srb from the going list stored in the
+ * dcb.
+ */
static
-void remove_srb_going(struct DeviceCtlBlk *dcb,
- struct ScsiReqBlk *srb,
- struct ScsiReqBlk *hint)
+void srb_going_remove(struct DeviceCtlBlk *dcb,
+ struct ScsiReqBlk *srb)
{
- struct ScsiReqBlk *pre = NULL;
- dprintkdbg(DBG_0, "Remove SRB %p from Going\n", srb);
- if (!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--;
+ struct ScsiReqBlk *i;
+ struct ScsiReqBlk *tmp;
+ dprintkdbg(DBG_0, "srb_going_remove: srb %p\n", srb);
+
+ list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list)
+ if (i == srb) {
+ list_del(&srb->list);
+ break;
+ }
}
-/* Remove SRB from Waiting queue */
+/*
+ * srb_waiting_remove - Remove an srb from the waiting list stored in the
+ * dcb.
+ */
static
-void remove_srb_waiting(struct DeviceCtlBlk *dcb,
- struct ScsiReqBlk *srb,
- struct ScsiReqBlk *hint)
+void srb_waiting_remove(struct DeviceCtlBlk *dcb,
+ struct ScsiReqBlk *srb)
{
- 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--;
+ struct ScsiReqBlk *i;
+ struct ScsiReqBlk *tmp;
+ dprintkdbg(DBG_0, "srb_waiting_remove: srb %p\n", srb);
+
+ list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list)
+ if (i == srb) {
+ list_del(&srb->list);
+ break;
+ }
}
-/* 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
-void move_srb_going_to_waiting(struct DeviceCtlBlk *dcb,
+void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{
- dprintkdbg(DBG_0, "Going_to_Waiting (SRB %p) pid = %li\n", srb, srb->cmd->pid);
- /* Remove SRB from Going */
- 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) */
+ dprintkdbg(DBG_0, "srb_going_waiting_move: srb %p, pid = %li\n", srb, srb->cmd->pid);
+ list_move(&srb->list, &dcb->srb_waiting_list);
}
-/* Moves first SRB from Waiting list to Going list */
-static inline
-void move_srb_waiting_to_going(struct DeviceCtlBlk *dcb,
+/*
+ * srb_waiting_to_going_move - Remove an srb from the waiting list in
+ * 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)
{
/* Remove from waiting list */
- dprintkdbg(DBG_0, "Remove SRB %p from head of Waiting\n", srb);
- remove_srb_waiting(dcb, srb, 0);
+ dprintkdbg(DBG_0, "srb_waiting_to_going: srb %p\n", srb);
TRACEPRINTF("WtG *");
- append_srb_going(dcb, srb);
+ list_move(&srb->list, &dcb->srb_going_list);
}
static
void waiting_process_next(struct AdapterCtlBlk *acb)
{
- struct DeviceCtlBlk *ptr;
- struct DeviceCtlBlk *ptr1;
+ struct DeviceCtlBlk *start = NULL;
+ struct DeviceCtlBlk *pos;
+ struct DeviceCtlBlk *dcb;
struct ScsiReqBlk *srb;
+ struct list_head *dcb_list_head = &acb->dcb_list;
if ((acb->active_dcb)
|| (acb->acb_flag & (RESET_DETECT + RESET_DONE + RESET_DEV)))
return;
+
if (timer_pending(&acb->waiting_timer))
del_timer(&acb->waiting_timer);
- ptr = acb->dcb_run_robin;
- if (!ptr) { /* This can happen! */
- ptr = acb->link_dcb;
- acb->dcb_run_robin = ptr;
- }
- ptr1 = ptr;
- if (!ptr1)
+
+ if (list_empty(dcb_list_head))
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 {
+ struct list_head *waiting_list_head = &pos->srb_waiting_list;
+
/* Make sure, the next another device gets scheduled ... */
- acb->dcb_run_robin = ptr1->next;
- if (!(srb = ptr1->waiting_srb)
- || (ptr1->max_command <= ptr1->going_srb_count))
- ptr1 = ptr1->next;
- else {
+ acb->dcb_run_robin = dcb_get_next(dcb_list_head,
+ acb->dcb_run_robin);
+
+ if (list_empty(waiting_list_head) ||
+ 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 */
- if (!start_scsi(acb, ptr1, srb))
- move_srb_waiting_to_going(ptr1, srb);
+ if (!start_scsi(acb, pos, srb))
+ srb_waiting_to_going_move(pos, srb);
else
- waiting_set_timer(acb, HZ / 50);
+ waiting_set_timer(acb, HZ/50);
break;
}
- } while (ptr1 != ptr);
- return;
+ } while (pos != start);
}
struct DeviceCtlBlk *dcb;
dcb = srb->dcb;
- if ((dcb->max_command <= dcb->going_srb_count) ||
- (acb->active_dcb) ||
+ if (dcb->max_command <= list_size(&dcb->srb_going_list) ||
+ acb->active_dcb ||
(acb->acb_flag & (RESET_DETECT + RESET_DONE + RESET_DEV))) {
- append_srb_waiting(dcb, srb);
+ srb_waiting_append(dcb, srb);
waiting_process_next(acb);
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))
- append_srb_going(dcb, srb);
- else {
- insert_srb_waiting(dcb, srb);
+ if (!start_scsi(acb, dcb, srb)) {
+ srb_going_append(dcb, srb);
+ } else {
+ srb_waiting_insert(dcb, srb);
waiting_set_timer(acb, HZ / 50);
}
}
cmd->result = 0;
/* get a free SRB */
- srb = get_srb_free(acb);
+ srb = srb_get_free(acb);
if (!srb)
{
/*
/* build srb for the command */
build_srb(cmd, dcb, srb);
- if (dcb->waiting_srb) {
+ if (!list_empty(&dcb->srb_waiting_list)) {
/* append to waiting queue */
- append_srb_waiting(dcb, srb);
+ srb_waiting_append(dcb, srb);
waiting_process_next(acb);
} else {
/* process immediately */
*/
static void reset_dev_param(struct AdapterCtlBlk *acb)
{
- struct DeviceCtlBlk *dcb = acb->link_dcb;
- struct DeviceCtlBlk *dcb_temp;
+ struct DeviceCtlBlk *dcb;
struct NvRamType *eeprom = &acb->eeprom;
- u8 period_index;
dprintkdbg(DBG_0, "reset_dev_param..............\n");
- if (dcb == NULL)
- return;
+ list_for_each_entry(dcb, &acb->dcb_list, list) {
+ u8 period_index;
- dcb_temp = dcb;
- do {
dcb->sync_mode &= ~(SYNC_NEGO_DONE + WIDE_NEGO_DONE);
dcb->sync_period = 0;
dcb->sync_offset = 0;
if (!(dcb->dev_mode & NTC_DO_WIDE_NEGO)
|| !(acb->config & HCC_WIDE_CARD))
dcb->sync_mode &= ~WIDE_NEGO_ENABLE;
-
- dcb = dcb->next;
}
- while (dcb_temp != dcb && dcb != NULL);
}
return FAILED;
}
- srb = find_cmd(cmd, dcb->waiting_srb);
+ srb = find_cmd(cmd, &dcb->srb_waiting_list);
if (srb) {
- remove_srb_waiting(dcb, srb, 0);
+ srb_waiting_remove(dcb, srb);
pci_unmap_srb_sense(acb, srb);
pci_unmap_srb(acb, 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");
cmd->result = DID_ABORT << 16;
return SUCCESS;
}
- srb = find_cmd(cmd, dcb->going_srb);
+ srb = find_cmd(cmd, &dcb->srb_going_list);
if (srb) {
dprintkl(KERN_DEBUG, "abort - command currently in progress");
/* XXX: Should abort the command here */
struct DeviceCtlBlk *dcb,
u8 tag)
{
- struct ScsiReqBlk *last_srb = dcb->going_last;
- struct ScsiReqBlk *srb = dcb->going_srb;
+ struct ScsiReqBlk *srb = NULL;
+ struct ScsiReqBlk *i;
+
+
dprintkdbg(DBG_0, "QTag Msg (SRB %p): %i\n", srb, tag);
if (!(dcb->tag_mask & (1 << tag)))
dprintkl(KERN_DEBUG,
"MsgIn_QTag: tag_mask (%08x) does not reserve tag %i!\n",
dcb->tag_mask, tag);
- if (!srb)
+ if (list_empty(&dcb->srb_going_list))
goto mingx0;
- while (srb) {
- if (srb->tag_number == tag)
+ list_for_each_entry(i, &dcb->srb_going_list, list) {
+ if (i->tag_number == tag) {
+ srb = i;
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,
srb->dcb->target_id, srb->dcb->target_lun);
if (dcb->flag & ABORT_DEV_) {
goto mingx0;
/* Tag found */
- TRACEPRINTF("[%s]*", dcb->active_srb->debugtrace);
- TRACEPRINTF("RTag*");
- /* Just for debugging ... */
- last_srb = srb;
- srb = dcb->active_srb;
- TRACEPRINTF("Found.*");
- srb = last_srb;
+ {
+ struct ScsiReqBlk *last_srb;
+
+ TRACEPRINTF("[%s]*", dcb->active_srb->debugtrace);
+ TRACEPRINTF("RTag*");
+ /* Just for debugging ... */
+
+ last_srb = srb;
+ srb = dcb->active_srb;
+ TRACEPRINTF("Found.*");
+ srb = last_srb;
+ }
memcpy(srb->msgin_buf, dcb->active_srb->msgin_buf, acb->msg_len);
srb->state |= dcb->active_srb->state;
static
void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb)
{
- u8 bval;
- u16 cnt, i;
- struct DeviceCtlBlk *dcb_temp;
+ struct DeviceCtlBlk *i;
/*
- ** set all lun device's period , offset
+ * set all lun device's period , offset
*/
- if (!(dcb->identify_msg & 0x07)) {
- if (acb->scan_devices)
- current_sync_offset = dcb->sync_offset;
- else {
- 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;
- }
- }
+ if (dcb->identify_msg & 0x07)
+ return;
+
+ if (acb->scan_devices) {
+ current_sync_offset = dcb->sync_offset;
+ return;
}
- return;
+
+ 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;
+ }
}
goto disc1;
}
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",
srb->cmd->pid);
waiting_set_timer(acb, HZ / 20);
srb->state = SRB_READY;
free_tag(dcb, srb);
- move_srb_going_to_waiting(dcb, srb);
+ srb_going_to_waiting_move(dcb, srb);
waiting_set_timer(acb, HZ / 20);
/* return; */
static
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");
- 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",
dcb->target_id, dcb->target_lun, (int) dcb,
- dcb->going_srb_count);
+ list_size(&dcb->srb_going_list));
return;
}
acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun);
acb->children[dcb->target_id][dcb->target_lun] = NULL;
- /* The first one */
- if (dcb == acb->link_dcb) {
- /* The last one */
- if (acb->last_dcb == dcb) {
- dcb->next = NULL;
- acb->last_dcb = NULL;
+ list_for_each_entry_safe(i, tmp, &acb->dcb_list, list) {
+ if (dcb == i) {
+ list_del(&i->list);
+ break;
}
- 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",
dcb->target_id, dcb->target_lun, dcb);
if (dcb == acb->active_dcb)
acb->active_dcb = NULL;
- if (dcb == acb->link_dcb)
- acb->link_dcb = dcb->next;
if (dcb == acb->dcb_run_robin)
- acb->dcb_run_robin = dcb->next;
- acb->dcb_count--;
+ acb->dcb_run_robin = dcb_get_next(&acb->dcb_list, dcb);
dc395x_kfree(dcb);
}
request_sense(acb, dcb, srb);
return;
} else if (status_byte(status) == QUEUE_FULL) {
- tempcnt = (u8) dcb->going_srb_count;
+ tempcnt = (u8)list_size(&dcb->srb_going_list);
printk
("\nDC395x: QUEUE_FULL for dev %02i-%i with %i cmnds\n",
dcb->target_id, dcb->target_lun, tempcnt);
tempcnt--;
dcb->max_command = tempcnt;
free_tag(dcb, srb);
- move_srb_going_to_waiting(dcb, srb);
+ srb_going_to_waiting_move(dcb, srb);
waiting_set_timer(acb, HZ / 20);
srb->adapter_status = 0;
srb->target_status = 0;
cmd->device->lun, srb->total_xfer_length);
}
- remove_srb_going(dcb, srb, 0);
+ srb_going_remove(dcb, srb);
/* Add to free list */
if (srb == acb->tmp_srb)
dprintkl(KERN_ERR, "ERROR! Completed Cmnd with tmp_srb!\n");
else
- insert_srb_free(acb, srb);
+ srb_free_insert(acb, srb);
dprintkdbg(DBG_0, "SRBdone: done pid %li\n", cmd->pid);
if (debug_enabled(DBG_KG)) {
Scsi_Cmnd * cmd, u8 force)
{
struct DeviceCtlBlk *dcb;
- struct ScsiReqBlk *srb;
- struct ScsiReqBlk *srb_temp;
- u16 cnt;
- Scsi_Cmnd *p;
- dcb = acb->link_dcb;
- 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--) {
+ list_for_each_entry(dcb, &acb->dcb_list, list) {
+ struct ScsiReqBlk *srb;
+ struct ScsiReqBlk *tmp;
+ Scsi_Cmnd *p;
+
+ list_for_each_entry_safe(srb, tmp, &dcb->srb_going_list, list) {
int result;
int dir;
- srb_temp = srb->next;
+
p = srb->cmd;
dir = scsi_to_pci_dma_dir(p->sc_data_direction);
result = MK_RES(0, did_flag, 0, 0);
+
/*result = MK_RES(0,DID_RESET,0,0); */
TRACEPRINTF("Reset(%li):%08x*", jiffies, result);
printk(" (G)");
p->device->id, p->device->lun);
#endif
TRACEOUT("%s\n", srb->debugtrace);
- dcb->going_srb = srb_temp;
- dcb->going_srb_count--;
- if (!srb_temp)
- dcb->going_last = NULL;
+
+ srb_going_remove(dcb, srb);
free_tag(dcb, srb);
- insert_srb_free(acb, srb);
+ srb_free_insert(acb, srb);
p->result = result;
pci_unmap_srb_sense(acb, srb);
pci_unmap_srb(acb, srb);
* as they all complete or all time out */
p->scsi_done(p);
}
- srb = srb_temp;
}
- if (dcb->going_srb)
+ if (!list_empty(&dcb->srb_going_list))
dprintkl(KERN_DEBUG,
"How could the ML send cmnds to the Going queue? (%02i-%i)!!\n",
dcb->target_id, dcb->target_lun);
"tag_mask for %02i-%i should be empty, is %08x!\n",
dcb->target_id, dcb->target_lun,
dcb->tag_mask);
- /*dcb->going_srb_count = 0;; */
- /*dcb->going_srb = NULL; dcb->going_last = NULL; */
/* Waiting queue */
- cnt = waiting_srb_count;
- srb = waiting_srb;
- while (cnt--) {
+ list_for_each_entry_safe(srb, tmp, &dcb->srb_waiting_list, list) {
int result;
- srb_temp = srb->next;
p = srb->cmd;
+
result = MK_RES(0, did_flag, 0, 0);
TRACEPRINTF("Reset(%li):%08x*", jiffies, result);
printk(" (W)");
p->device->lun);
#endif
TRACEOUT("%s\n", srb->debugtrace);
- dcb->waiting_srb = srb_temp;
- dcb->waiting_srb_count--;
- if (!srb_temp)
- dcb->wait_list = NULL;
- insert_srb_free(acb, srb);
+ srb_waiting_remove(dcb, srb);
+ srb_free_insert(acb, srb);
p->result = result;
pci_unmap_srb_sense(acb, srb);
/* For new EH, we normally don't need to give commands back,
* as they all complete or all time out */
cmd->scsi_done(cmd);
- srb = srb_temp;
}
}
- if (dcb->waiting_srb_count)
+ if (!list_empty(&dcb->srb_waiting_list))
printk
("\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);
- /* 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 = dcb->next;
}
- while (dcb != acb->link_dcb && dcb);
printk("\n");
}
"Request Sense failed for pid %li (%02i-%i)!\n",
srb->cmd->pid, dcb->target_id, dcb->target_lun);
TRACEPRINTF("?*");
- move_srb_going_to_waiting(dcb, srb);
+ srb_going_to_waiting_move(dcb, srb);
waiting_set_timer(acb, HZ / 100);
}
TRACEPRINTF(".*");
if (!dcb)
return;
- if (acb->dcb_count == 0) {
- acb->link_dcb = dcb;
+ INIT_LIST_HEAD(&dcb->srb_waiting_list);
+ INIT_LIST_HEAD(&dcb->srb_going_list);
+ if (list_empty(&acb->dcb_list))
acb->dcb_run_robin = dcb;
- } else {
- acb->last_dcb->next = dcb;
- }
-
- acb->dcb_count++;
- dcb->next = acb->link_dcb;
- acb->last_dcb = dcb;
+ list_add_tail(&dcb->list, &acb->dcb_list);
/* $$$$$$$ */
dcb->acb = acb;
dcb->target_id = target;
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->tag_mask = 0;
/* $$$$$$$ */
if (dcb->target_lun != 0) {
/* Copy settings */
- struct DeviceCtlBlk *prevDCB = acb->link_dcb;
- while (prevDCB->target_id != dcb->target_id)
- prevDCB = prevDCB->next;
+ struct DeviceCtlBlk *prevDCB;
+ list_for_each_entry(prevDCB, &acb->dcb_list, list)
+ if (prevDCB->target_id == dcb->target_id)
+ break;
dprintkdbg(DBG_KG,
"Copy settings from %02i-%02i to %02i-%02i\n",
prevDCB->target_id, prevDCB->target_lun,
int i;
for (i = 0; i < acb->srb_count - 1; i++)
- acb->srb_array[i].next = &acb->srb_array[i + 1];
- acb->srb_array[i].next = NULL;
- /*DC395x_Free_integrity (acb); */
+ srb_free_insert(acb, &acb->srb_array[i]);
}
*/
acb->scsi_host = host;
acb->IOPortBase = (u16) io_port;
- acb->link_dcb = NULL;
acb->dcb_run_robin = NULL;
acb->active_dcb = NULL;
acb->srb_count = DC395x_MAX_SRB_CNT;
acb->scsi_host->this_id = eeprom->scsi_id;
acb->hostid_bit = (1 << acb->scsi_host->this_id);
/*acb->scsi_host->this_lun = 0; */
- acb->dcb_count = 0;
acb->irq_level = irq;
acb->tag_max_num = 1 << eeprom->max_tag;
if (acb->tag_max_num > 30)
return 1;
}
#endif
+ INIT_LIST_HEAD(&acb->dcb_list);
+ INIT_LIST_HEAD(&acb->srb_free_list);
link_srb(acb);
- acb->free_srb = acb->srb_array;
+
/*
* temp SRB for Q tag used or abort command used
*/
acb->tmp_srb = &acb->srb;
- acb->srb.dcb = NULL;
- acb->srb.next = NULL;
init_timer(&acb->waiting_timer);
for (i = 0; i < DC395x_MAX_SCSI_ID; i++)
int inout)
{
struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
- int dev, spd, spd1;
+ int spd, spd1;
char *pos = buffer;
struct DeviceCtlBlk *dcb;
unsigned long flags;
+ int dev;
if (inout) /* Has data been written to the file ? */
return -EPERM;
SPRINTF(", DelayReset %is\n", acb->eeprom.delay_time);
/*SPRINTF("\n"); */
- SPRINTF("Nr of DCBs: %i\n", acb->dcb_count);
+ SPRINTF("Nr of DCBs: %i\n", list_size(&acb->dcb_list));
SPRINTF
("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],
SPRINTF
("Un ID LUN Prty Sync Wide DsCn SndS TagQ nego_period SyncFreq SyncOffs MaxCmd\n");
- dcb = acb->link_dcb;
- for (dev = 0; dev < acb->dcb_count; dev++) {
+ dev = 0;
+ list_for_each_entry(dcb, &acb->dcb_list, list) {
int nego_period;
SPRINTF("%02i %02i %02i ", dev, dcb->target_id,
dcb->target_lun);
YESNO(dcb->dev_mode & NTC_DO_DISCONNECT);
YESNO(dcb->dev_mode & NTC_DO_SEND_START);
YESNO(dcb->sync_mode & EN_TAG_QUEUEING);
- nego_period =
- clock_period[dcb->sync_period & 0x07] << 2;
+ nego_period = clock_period[dcb->sync_period & 0x07] << 2;
if (dcb->sync_offset)
SPRINTF(" %03i ns ", nego_period);
else
/* Add more info ... */
SPRINTF(" %02i\n", dcb->max_command);
- dcb = dcb->next;
+ dev++;
}
if (timer_pending(&acb->waiting_timer))
SPRINTF("Waiting queue timer running\n");
else
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;
- if (dcb->waiting_srb_count)
+ if (!list_empty(&dcb->srb_waiting_list))
SPRINTF("DCB (%02i-%i): Waiting: %i:",
dcb->target_id, dcb->target_lun,
- dcb->waiting_srb_count);
- for (srb = dcb->waiting_srb; srb; srb = srb->next)
+ list_size(&dcb->srb_waiting_list));
+ list_for_each_entry(srb, &dcb->srb_waiting_list, list)
SPRINTF(" %li", srb->cmd->pid);
- if (dcb->going_srb_count)
+ if (!list_empty(&dcb->srb_going_list))
SPRINTF("\nDCB (%02i-%i): Going : %i:",
dcb->target_id, dcb->target_lun,
- dcb->going_srb_count);
- for (srb = dcb->going_srb; srb; srb = srb->next)
+ list_size(&dcb->srb_going_list));
+ list_for_each_entry(srb, &dcb->srb_going_list, list)
#if debug_enabled(DBG_TRACE|DBG_TRACEALL)
SPRINTF("\n %s", srb->debugtrace);
#else
SPRINTF(" %li", srb->cmd->pid);
#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");
- dcb = dcb->next;
}
if (debug_enabled(DBG_DCB)) {
SPRINTF("DCB list for ACB %p:\n", acb);
- dcb = acb->link_dcb;
- SPRINTF("%p", dcb);
- for (dev = 0; dev < acb->dcb_count; dev++, dcb = dcb->next)
- SPRINTF("->%p", dcb->next);
- SPRINTF("\n");
+ list_for_each_entry(dcb, &acb->dcb_list, list) {
+ SPRINTF("%p -> ", dcb);
+ }
+ SPRINTF("END\n");
}
*start = buffer + offset;
void free_dcbs(struct AdapterCtlBlk* acb)
{
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)
- {
- dcb_next = dcb->next;
+ list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list) {
dprintkdbg(DBG_DCB, "Free DCB (ID %i, LUN %i): %p\n",
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);
}
}