Commit ab2d582d authored by Linus Torvalds's avatar Linus Torvalds

Merge SCSI update

parents 08f34001 bede2c88
...@@ -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);
/* 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)
{ {
struct ScsiReqBlk *p = start; dprintkdbg(DBG_0, "srb_going_append: srb %p\n", srb);
if (!start) list_add_tail(&srb->list, &dcb->srb_going_list);
return 0;
do {
if (p->next == srb)
return p;
p = p->next;
} while (p && p != start);
return 0;
} }
/* 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 static
void remove_srb_going(struct DeviceCtlBlk *dcb, void srb_going_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_going_remove: srb %p\n", srb);
dprintkl(KERN_ERR, "Going_remove %p!\n", srb);
if (srb == dcb->going_srb) list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list)
dcb->going_srb = srb->next; if (i == srb) {
else if (hint && hint->next == srb) list_del(&srb->list);
pre = remove_srb(srb, hint); break;
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 */ /*
* srb_waiting_remove - Remove an srb from the waiting list stored in the
* dcb.
*/
static static
void remove_srb_waiting(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 Waiting\n", srb); struct ScsiReqBlk *tmp;
if (!srb) dprintkdbg(DBG_0, "srb_waiting_remove: srb %p\n", srb);
dprintkl(KERN_ERR, "Waiting_remove %p!\n", srb);
if (srb == dcb->waiting_srb) list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list)
dcb->waiting_srb = srb->next; if (i == srb) {
else if (hint && hint->next == srb) list_del(&srb->list);
pre = remove_srb(srb, hint); break;
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 */
TRACEPRINTF("[%s]*", dcb->active_srb->debugtrace); {
TRACEPRINTF("RTag*"); struct ScsiReqBlk *last_srb;
/* Just for debugging ... */
last_srb = srb; TRACEPRINTF("[%s]*", dcb->active_srb->debugtrace);
srb = dcb->active_srb; TRACEPRINTF("RTag*");
TRACEPRINTF("Found.*"); /* Just for debugging ... */
srb = last_srb;
last_srb = srb;
srb = dcb->active_srb;
TRACEPRINTF("Found.*");
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;
current_sync_offset = dcb->sync_offset;
else { if (acb->scan_devices) {
dcb_temp = acb->link_dcb; current_sync_offset = dcb->sync_offset;
cnt = acb->dcb_count; return;
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;
}
}
} }
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;
}
} }
...@@ -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;
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 "); dprintkl(KERN_INFO, "doing_srb_done: pids ");
do { list_for_each_entry(dcb, &acb->dcb_list, list) {
/* As the ML may queue cmnds again, cache old values */ struct ScsiReqBlk *srb;
struct ScsiReqBlk *waiting_srb = dcb->waiting_srb; struct ScsiReqBlk *tmp;
/*struct ScsiReqBlk* wait_list = dcb->wait_list; */ Scsi_Cmnd *p;
u16 waiting_srb_count = dcb->waiting_srb_count;
/* Going queue */ list_for_each_entry_safe(srb, tmp, &dcb->srb_going_list, list) {
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);
} }
} }
......
...@@ -40,6 +40,16 @@ ...@@ -40,6 +40,16 @@
static int scsi_host_next_hn; /* host_no for next new host */ static int scsi_host_next_hn; /* host_no for next new host */
static void scsi_host_cls_release(struct class_device *class_dev)
{
put_device(&class_to_shost(class_dev)->shost_gendev);
}
static struct class shost_class = {
.name = "scsi_host",
.release = scsi_host_cls_release,
};
/** /**
* scsi_host_cancel - cancel outstanding IO to this host * scsi_host_cancel - cancel outstanding IO to this host
* @shost: pointer to struct Scsi_Host * @shost: pointer to struct Scsi_Host
...@@ -64,10 +74,18 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery) ...@@ -64,10 +74,18 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
**/ **/
void scsi_remove_host(struct Scsi_Host *shost) void scsi_remove_host(struct Scsi_Host *shost)
{ {
unsigned long flags;
scsi_host_cancel(shost, 0); scsi_host_cancel(shost, 0);
scsi_proc_host_rm(shost); scsi_proc_host_rm(shost);
scsi_forget_host(shost); scsi_forget_host(shost);
scsi_sysfs_remove_host(shost);
spin_lock_irqsave(shost->host_lock, flags);
set_bit(SHOST_DEL, &shost->shost_state);
spin_unlock_irqrestore(shost->host_lock, flags);
class_device_unregister(&shost->shost_classdev);
device_del(&shost->shost_gendev);
} }
/** /**
...@@ -89,21 +107,45 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) ...@@ -89,21 +107,45 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
if (!shost->can_queue) { if (!shost->can_queue) {
printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
sht->name); sht->name);
error = -EINVAL; return -EINVAL;
} }
error = scsi_sysfs_add_host(shost, dev); if (!shost->shost_gendev.parent)
if (!error) shost->shost_gendev.parent = dev ? dev : &legacy_bus;
scsi_proc_host_add(shost);
error = device_add(&shost->shost_gendev);
if (error)
goto out;
set_bit(SHOST_ADD, &shost->shost_state);
get_device(shost->shost_gendev.parent);
error = class_device_add(&shost->shost_classdev);
if (error)
goto out_del_gendev;
get_device(&shost->shost_gendev);
error = scsi_sysfs_add_host(shost);
if (error)
goto out_del_classdev;
scsi_proc_host_add(shost);
return error;
out_del_classdev:
class_device_del(&shost->shost_classdev);
out_del_gendev:
device_del(&shost->shost_gendev);
out:
return error; return error;
} }
/** static void scsi_host_dev_release(struct device *dev)
* scsi_free_sdev - free a scsi hosts resources
* @shost: scsi host to free
**/
void scsi_free_shost(struct Scsi_Host *shost)
{ {
struct Scsi_Host *shost = dev_to_shost(dev);
struct device *parent = dev->parent;
if (shost->ehandler) { if (shost->ehandler) {
DECLARE_COMPLETION(sem); DECLARE_COMPLETION(sem);
shost->eh_notify = &sem; shost->eh_notify = &sem;
...@@ -115,6 +157,8 @@ void scsi_free_shost(struct Scsi_Host *shost) ...@@ -115,6 +157,8 @@ void scsi_free_shost(struct Scsi_Host *shost)
scsi_proc_hostdir_rm(shost->hostt); scsi_proc_hostdir_rm(shost->hostt);
scsi_destroy_command_freelist(shost); scsi_destroy_command_freelist(shost);
put_device(parent);
kfree(shost); kfree(shost);
} }
...@@ -214,7 +258,16 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) ...@@ -214,7 +258,16 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
if (rval) if (rval)
goto fail; goto fail;
scsi_sysfs_init_host(shost); device_initialize(&shost->shost_gendev);
snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
shost->shost_gendev.release = scsi_host_dev_release;
class_device_initialize(&shost->shost_classdev);
shost->shost_classdev.dev = &shost->shost_gendev;
shost->shost_classdev.class = &shost_class;
snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
shost->host_no);
shost->eh_notify = &complete; shost->eh_notify = &complete;
/* XXX(hch): handle error return */ /* XXX(hch): handle error return */
...@@ -299,3 +352,13 @@ void scsi_host_put(struct Scsi_Host *shost) ...@@ -299,3 +352,13 @@ void scsi_host_put(struct Scsi_Host *shost)
{ {
put_device(&shost->shost_gendev); put_device(&shost->shost_gendev);
} }
int scsi_init_hosts(void)
{
return class_register(&shost_class);
}
void scsi_exit_hosts(void)
{
class_unregister(&shost_class);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -106,8 +106,10 @@ ...@@ -106,8 +106,10 @@
#define IPS_REMOVE_HOST(shost) #define IPS_REMOVE_HOST(shost)
#define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_pci_device(sh, (ha)->pcidev) #define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_pci_device(sh, (ha)->pcidev)
#define IPS_PRINTK(level, pcidev, format, arg...) \ #define IPS_PRINTK(level, pcidev, format, arg...) \
printk(level "%s %s:" format , (pcidev)->driver->name , \ printk(level "%s %s:" format , "ips" , \
pci_name(pcidev) , ## arg) (pcidev)->slot_name , ## arg)
#define scsi_host_alloc(sh,size) scsi_register(sh,size)
#define scsi_host_put(sh) scsi_unregister(sh)
#else #else
#define IPS_REGISTER_HOSTS(SHT) (!ips_detect(SHT)) #define IPS_REGISTER_HOSTS(SHT) (!ips_detect(SHT))
#define IPS_UNREGISTER_HOSTS(SHT) #define IPS_UNREGISTER_HOSTS(SHT)
...@@ -126,22 +128,13 @@ ...@@ -126,22 +128,13 @@
#define min(x,y) ((x) < (y) ? x : y) #define min(x,y) ((x) < (y) ? x : y)
#endif #endif
#define pci_dma_hi32(a) ((a >> 16) >> 16)
#define pci_dma_lo32(a) (a & 0xffffffff) #define pci_dma_lo32(a) (a & 0xffffffff)
#if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO) #if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO)
#define IPS_ENABLE_DMA64 (1) #define IPS_ENABLE_DMA64 (1)
#define pci_dma_hi32(a) (a >> 32)
#else #else
#define IPS_ENABLE_DMA64 (0) #define IPS_ENABLE_DMA64 (0)
#define pci_dma_hi32(a) (0)
#endif
#if defined(__ia64__)
#define IPS_ATOMIC_GFP (GFP_DMA | GFP_ATOMIC)
#define IPS_INIT_GFP GFP_DMA
#else
#define IPS_ATOMIC_GFP GFP_ATOMIC
#define IPS_INIT_GFP GFP_KERNEL
#endif #endif
/* /*
...@@ -451,9 +444,11 @@ ...@@ -451,9 +444,11 @@
* Scsi_Host Template * Scsi_Host Template
*/ */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
static int ips_proc24_info(char *, char **, off_t, int, int, int);
static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *); static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]); static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]);
#else #else
int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev, static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[]); sector_t capacity, int geom[]);
int ips_slave_configure(Scsi_Device *SDptr); int ips_slave_configure(Scsi_Device *SDptr);
...@@ -1106,7 +1101,8 @@ typedef struct ips_ha { ...@@ -1106,7 +1101,8 @@ typedef struct ips_ha {
uint16_t device_id; /* PCI device ID */ uint16_t device_id; /* PCI device ID */
uint8_t slot_num; /* PCI Slot Number */ uint8_t slot_num; /* PCI Slot Number */
uint16_t subdevice_id; /* Subsystem device ID */ uint16_t subdevice_id; /* Subsystem device ID */
uint8_t ioctl_order; /* Number of pages in ioctl */ int ioctl_len; /* size of ioctl buffer */
dma_addr_t ioctl_busaddr; /* dma address of ioctl buffer*/
uint8_t bios_version[8]; /* BIOS Revision */ uint8_t bios_version[8]; /* BIOS Revision */
uint32_t mem_addr; /* Memory mapped address */ uint32_t mem_addr; /* Memory mapped address */
uint32_t io_len; /* Size of IO Address */ uint32_t io_len; /* Size of IO Address */
...@@ -1116,8 +1112,10 @@ typedef struct ips_ha { ...@@ -1116,8 +1112,10 @@ typedef struct ips_ha {
ips_hw_func_t func; /* hw function pointers */ ips_hw_func_t func; /* hw function pointers */
struct pci_dev *pcidev; /* PCI device handle */ struct pci_dev *pcidev; /* PCI device handle */
char *flash_data; /* Save Area for flash data */ char *flash_data; /* Save Area for flash data */
u8 flash_order; /* Save Area for flash size order */ int flash_len; /* length of flash buffer */
u32 flash_datasize; /* Save Area for flash data size */ u32 flash_datasize; /* Save Area for flash data size */
dma_addr_t flash_busaddr; /* dma address of flash buffer*/
dma_addr_t enq_busaddr; /* dma address of enq struct */
uint8_t requires_esl; /* Requires an EraseStripeLock */ uint8_t requires_esl; /* Requires an EraseStripeLock */
} ips_ha_t; } ips_ha_t;
...@@ -1203,25 +1201,29 @@ typedef struct { ...@@ -1203,25 +1201,29 @@ typedef struct {
* *
*************************************************************************/ *************************************************************************/
#define IPS_VER_MAJOR 5 #define IPS_VER_MAJOR 6
#define IPS_VER_MAJOR_STRING "5" #define IPS_VER_MAJOR_STRING "6"
#define IPS_VER_MINOR 99 #define IPS_VER_MINOR 10
#define IPS_VER_MINOR_STRING "99" #define IPS_VER_MINOR_STRING "10"
#define IPS_VER_BUILD 00 #define IPS_VER_BUILD 90
#define IPS_VER_BUILD_STRING "00" #define IPS_VER_BUILD_STRING "90"
#define IPS_VER_STRING "5.99.00" #define IPS_VER_STRING "6.10.90"
#define IPS_BUILD_IDENT 1132 #define IPS_RELEASE_ID 0x00010000
#define IPS_BUILD_IDENT 364
#define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2003. All Rights Reserved."
#define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to present. All Rights Reserved."
#define IPS_NT_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2003."
/* Version numbers for various adapters */ /* Version numbers for various adapters */
#define IPS_VER_SERVERAID1 "2.25.01" #define IPS_VER_SERVERAID1 "2.25.01"
#define IPS_VER_SERVERAID2 "2.88.13" #define IPS_VER_SERVERAID2 "2.88.13"
#define IPS_VER_NAVAJO "2.88.13" #define IPS_VER_NAVAJO "2.88.13"
#define IPS_VER_SERVERAID3 "5.11.05" #define IPS_VER_SERVERAID3 "6.10.24"
#define IPS_VER_SERVERAID4H "5.11.05" #define IPS_VER_SERVERAID4H "6.10.24"
#define IPS_VER_SERVERAID4MLx "5.11.05" #define IPS_VER_SERVERAID4MLx "6.10.24"
#define IPS_VER_SARASOTA "5.11.05" #define IPS_VER_SARASOTA "6.10.24"
#define IPS_VER_MARCO "0.00.00" #define IPS_VER_MARCO "6.10.24"
#define IPS_VER_SEBRING "0.00.00" #define IPS_VER_SEBRING "6.10.24"
/* Compatability IDs for various adapters */ /* Compatability IDs for various adapters */
#define IPS_COMPAT_UNKNOWN "" #define IPS_COMPAT_UNKNOWN ""
...@@ -1230,17 +1232,17 @@ typedef struct { ...@@ -1230,17 +1232,17 @@ typedef struct {
#define IPS_COMPAT_SERVERAID2 "2.88.13" #define IPS_COMPAT_SERVERAID2 "2.88.13"
#define IPS_COMPAT_NAVAJO "2.88.13" #define IPS_COMPAT_NAVAJO "2.88.13"
#define IPS_COMPAT_KIOWA "2.88.13" #define IPS_COMPAT_KIOWA "2.88.13"
#define IPS_COMPAT_SERVERAID3H "SA510" #define IPS_COMPAT_SERVERAID3H "SB610"
#define IPS_COMPAT_SERVERAID3L "SA510" #define IPS_COMPAT_SERVERAID3L "SB610"
#define IPS_COMPAT_SERVERAID4H "SA510" #define IPS_COMPAT_SERVERAID4H "SB610"
#define IPS_COMPAT_SERVERAID4M "SA510" #define IPS_COMPAT_SERVERAID4M "SB610"
#define IPS_COMPAT_SERVERAID4L "SA510" #define IPS_COMPAT_SERVERAID4L "SB610"
#define IPS_COMPAT_SERVERAID4Mx "SA510" #define IPS_COMPAT_SERVERAID4Mx "SB610"
#define IPS_COMPAT_SERVERAID4Lx "SA510" #define IPS_COMPAT_SERVERAID4Lx "SB610"
#define IPS_COMPAT_SARASOTA "SA510" #define IPS_COMPAT_SARASOTA "SB610"
#define IPS_COMPAT_MARCO "SA000" #define IPS_COMPAT_MARCO "SB610"
#define IPS_COMPAT_SEBRING "SA000" #define IPS_COMPAT_SEBRING "SB610"
#define IPS_COMPAT_BIOS "SA510" #define IPS_COMPAT_BIOS "SB610"
#define IPS_COMPAT_MAX_ADAPTER_TYPE 16 #define IPS_COMPAT_MAX_ADAPTER_TYPE 16
#define IPS_COMPAT_ID_LENGTH 8 #define IPS_COMPAT_ID_LENGTH 8
......
...@@ -86,14 +86,10 @@ lasi700_driver_callback(struct parisc_device *dev) ...@@ -86,14 +86,10 @@ lasi700_driver_callback(struct parisc_device *dev)
struct NCR_700_Host_Parameters *hostdata; struct NCR_700_Host_Parameters *hostdata;
struct Scsi_Host *host; struct Scsi_Host *host;
snprintf(dev->dev.name, sizeof(dev->dev.name), "%s",
(dev->id.sversion == LASI_700_SVERSION) ?
"lasi700" : "lasi710");
hostdata = kmalloc(sizeof(*hostdata), GFP_KERNEL); hostdata = kmalloc(sizeof(*hostdata), GFP_KERNEL);
if (!hostdata) { if (!hostdata) {
printk(KERN_ERR "%s: Failed to allocate host data\n", printk(KERN_ERR "%s: Failed to allocate host data\n",
dev->dev.name); dev->dev.bus_id);
return 1; return 1;
} }
memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
...@@ -121,9 +117,9 @@ lasi700_driver_callback(struct parisc_device *dev) ...@@ -121,9 +117,9 @@ lasi700_driver_callback(struct parisc_device *dev)
host->irq = dev->irq; host->irq = dev->irq;
if (request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, if (request_irq(dev->irq, NCR_700_intr, SA_SHIRQ,
dev->dev.name, host)) { dev->dev.bus_id, host)) {
printk(KERN_ERR "%s: irq problem, detaching\n", printk(KERN_ERR "%s: irq problem, detaching\n",
dev->dev.name); dev->dev.bus_id);
goto out_put_host; goto out_put_host;
} }
......
...@@ -177,13 +177,8 @@ static void aha152x_detach(dev_link_t *link) ...@@ -177,13 +177,8 @@ static void aha152x_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
aha152x_release_cs(link); aha152x_release_cs(link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -302,9 +297,6 @@ static void aha152x_release_cs(dev_link_t *link) ...@@ -302,9 +297,6 @@ static void aha152x_release_cs(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
scsi_unregister(info->host); scsi_unregister(info->host);
if (link->state & DEV_STALE_LINK)
aha152x_detach(link);
} }
static int aha152x_event(event_t event, int priority, static int aha152x_event(event_t event, int priority,
......
...@@ -166,13 +166,8 @@ static void fdomain_detach(dev_link_t *link) ...@@ -166,13 +166,8 @@ static void fdomain_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
fdomain_release(link); fdomain_release(link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -283,9 +278,7 @@ static void fdomain_release(dev_link_t *link) ...@@ -283,9 +278,7 @@ static void fdomain_release(dev_link_t *link)
scsi_unregister(info->host); scsi_unregister(info->host);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK) }
fdomain_detach(link);
} /* fdomain_release */
/*====================================================================*/ /*====================================================================*/
......
...@@ -1553,18 +1553,12 @@ static void nsp_cs_detach(dev_link_t *link) ...@@ -1553,18 +1553,12 @@ static void nsp_cs_detach(dev_link_t *link)
return; return;
} }
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
nsp_cs_release(link); nsp_cs_release(link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
/* Break the link with Card Services */ /* Break the link with Card Services */
if (link->handle) { if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
}
/* Unlink device structure, free bits */ /* Unlink device structure, free bits */
*linkp = link->next; *linkp = link->next;
...@@ -1792,17 +1786,6 @@ static void nsp_cs_release(dev_link_t *link) ...@@ -1792,17 +1786,6 @@ static void nsp_cs_release(dev_link_t *link)
DEBUG(0, "%s(0x%p)\n", __FUNCTION__, link); DEBUG(0, "%s(0x%p)\n", __FUNCTION__, link);
/*
* If the device is currently in use, we won't release until it
* is actually closed.
*/
if (link->open) {
DEBUG(1, "nsp_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
/* Unlink the device chain */ /* Unlink the device chain */
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,2)) #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,2))
scsi_unregister_module(MODULE_SCSI_HA, &nsp_driver_template); scsi_unregister_module(MODULE_SCSI_HA, &nsp_driver_template);
...@@ -1824,11 +1807,7 @@ static void nsp_cs_release(dev_link_t *link) ...@@ -1824,11 +1807,7 @@ static void nsp_cs_release(dev_link_t *link)
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
} }
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
}
if (link->state & DEV_STALE_LINK) {
nsp_cs_detach(link);
}
} /* nsp_cs_release */
/*====================================================================== /*======================================================================
......
...@@ -165,13 +165,8 @@ static void qlogic_detach(dev_link_t * link) ...@@ -165,13 +165,8 @@ static void qlogic_detach(dev_link_t * link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
qlogic_release(link); qlogic_release(link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -296,9 +291,7 @@ static void qlogic_release(dev_link_t *link) ...@@ -296,9 +291,7 @@ static void qlogic_release(dev_link_t *link)
scsi_unregister(info->host); scsi_unregister(info->host);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK) }
qlogic_detach(link);
} /* qlogic_release */
/*====================================================================*/ /*====================================================================*/
......
...@@ -76,6 +76,7 @@ int ppa_release(struct Scsi_Host *host) ...@@ -76,6 +76,7 @@ int ppa_release(struct Scsi_Host *host)
int host_no = host->unique_id; int host_no = host->unique_id;
printk("Releasing ppa%i\n", host_no); printk("Releasing ppa%i\n", host_no);
scsi_unregister(host);
parport_unregister_device(ppa_hosts[host_no].dev); parport_unregister_device(ppa_hosts[host_no].dev);
return 0; return 0;
} }
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
* General Public License for more details. * General Public License for more details.
* *
******************************************************************************/ ******************************************************************************/
#define QLA1280_VERSION "3.23.34" #define QLA1280_VERSION "3.23.35"
/***************************************************************************** /*****************************************************************************
Revision History: Revision History:
Rev 3.23.35 August 14, 2003, Jes Sorensen
- Build against 2.6
Rev 3.23.34 July 23, 2003, Jes Sorensen Rev 3.23.34 July 23, 2003, Jes Sorensen
- Remove pointless TRUE/FALSE macros - Remove pointless TRUE/FALSE macros
- Clean up vchan handling - Clean up vchan handling
...@@ -296,14 +298,12 @@ ...@@ -296,14 +298,12 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/blk.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -312,7 +312,10 @@ ...@@ -312,7 +312,10 @@
#include <asm/system.h> #include <asm/system.h>
#if LINUX_VERSION_CODE < 0x020545 #if LINUX_VERSION_CODE < 0x020545
#include <linux/blk.h>
#include "sd.h" #include "sd.h"
#else
#include <scsi/scsi_host.h>
#endif #endif
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -634,11 +637,14 @@ static int ql_debug_level = 1; ...@@ -634,11 +637,14 @@ static int ql_debug_level = 1;
*************************************************************************/ *************************************************************************/
#define PROC_BUF &qla1280_buffer[len] #define PROC_BUF &qla1280_buffer[len]
int #if LINUX_VERSION_CODE < 0x020600
qla1280_proc_info(char *buffer, char **start, off_t offset, int length, int qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
int hostno, int inout) int hostno, int inout)
#else
int qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start,
off_t offset, int length, int inout)
#endif
{ {
struct Scsi_Host *host;
struct scsi_qla_host *ha; struct scsi_qla_host *ha;
int size = 0; int size = 0;
int len = 0; int len = 0;
...@@ -647,7 +653,10 @@ qla1280_proc_info(char *buffer, char **start, off_t offset, int length, ...@@ -647,7 +653,10 @@ qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
struct scsi_lu *up; struct scsi_lu *up;
uint32_t b, t, l; uint32_t b, t, l;
#endif #endif
#if LINUX_VERSION_CODE >= 0x020600
ha = (struct scsi_qla_host *)host->hostdata;
#else
struct Scsi_Host *host;
/* Find the host that was specified */ /* Find the host that was specified */
for (ha = qla1280_hostlist; (ha != NULL) for (ha = qla1280_hostlist; (ha != NULL)
&& ha->host->host_no != hostno; ha = ha->next) ; && ha->host->host_no != hostno; ha = ha->next) ;
...@@ -664,6 +673,7 @@ qla1280_proc_info(char *buffer, char **start, off_t offset, int length, ...@@ -664,6 +673,7 @@ qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
} }
host = ha->host; host = ha->host;
#endif
if (inout) if (inout)
return -ENOSYS; return -ENOSYS;
...@@ -1828,7 +1838,7 @@ qla1280_done(struct scsi_qla_host *ha, struct srb ** done_q_first, ...@@ -1828,7 +1838,7 @@ qla1280_done(struct scsi_qla_host *ha, struct srb ** done_q_first,
CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE; CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE;
ha->actthreads--; ha->actthreads--;
#if LINUX_KERNEL_VERSION < 0x020500 #if LINUX_VERSION_CODE < 0x020500
if (cmd->cmnd[0] == INQUIRY) if (cmd->cmnd[0] == INQUIRY)
qla1280_get_target_options(cmd, ha); qla1280_get_target_options(cmd, ha);
#endif #endif
...@@ -4497,7 +4507,7 @@ qla1280_rst_aen(struct scsi_qla_host *ha) ...@@ -4497,7 +4507,7 @@ qla1280_rst_aen(struct scsi_qla_host *ha)
} }
#if LINUX_KERNEL_VERSION < 0x020500 #if LINUX_VERSION_CODE < 0x020500
/* /*
* *
*/ */
......
...@@ -1111,7 +1111,11 @@ struct scsi_qla_host { ...@@ -1111,7 +1111,11 @@ struct scsi_qla_host {
/* /*
* Linux - SCSI Driver Interface Function Prototypes. * Linux - SCSI Driver Interface Function Prototypes.
*/ */
#if LINUX_VERSION_CODE < 0x020600
int qla1280_proc_info(char *, char **, off_t, int, int, int); int qla1280_proc_info(char *, char **, off_t, int, int, int);
#else
int qla1280_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
#endif
const char *qla1280_info(struct Scsi_Host *host); const char *qla1280_info(struct Scsi_Host *host);
int qla1280_detect(Scsi_Host_Template *); int qla1280_detect(Scsi_Host_Template *);
int qla1280_release(struct Scsi_Host *); int qla1280_release(struct Scsi_Host *);
...@@ -1147,8 +1151,6 @@ int qla1280_eh_adapter_reset(struct scsi_cmnd *cmd); ...@@ -1147,8 +1151,6 @@ int qla1280_eh_adapter_reset(struct scsi_cmnd *cmd);
.detect = qla1280_detect, \ .detect = qla1280_detect, \
.release = qla1280_release, \ .release = qla1280_release, \
.info = qla1280_info, \ .info = qla1280_info, \
.ioctl = NULL, \
.command = NULL, \
.queuecommand = qla1280_queuecommand, \ .queuecommand = qla1280_queuecommand, \
.eh_strategy_handler = NULL, \ .eh_strategy_handler = NULL, \
.eh_abort_handler = qla1280_eh_abort, \ .eh_abort_handler = qla1280_eh_abort, \
......
...@@ -1003,9 +1003,12 @@ static int __init init_scsi(void) ...@@ -1003,9 +1003,12 @@ static int __init init_scsi(void)
error = scsi_init_devinfo(); error = scsi_init_devinfo();
if (error) if (error)
goto cleanup_procfs; goto cleanup_procfs;
error = scsi_sysfs_register(); error = scsi_init_hosts();
if (error) if (error)
goto cleanup_devlist; goto cleanup_devlist;
error = scsi_sysfs_register();
if (error)
goto cleanup_hosts;
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
INIT_LIST_HEAD(&done_q[i]); INIT_LIST_HEAD(&done_q[i]);
...@@ -1015,6 +1018,8 @@ static int __init init_scsi(void) ...@@ -1015,6 +1018,8 @@ static int __init init_scsi(void)
printk(KERN_NOTICE "SCSI subsystem initialized\n"); printk(KERN_NOTICE "SCSI subsystem initialized\n");
return 0; return 0;
cleanup_hosts:
scsi_exit_hosts();
cleanup_devlist: cleanup_devlist:
scsi_exit_devinfo(); scsi_exit_devinfo();
cleanup_procfs: cleanup_procfs:
...@@ -1029,6 +1034,7 @@ static int __init init_scsi(void) ...@@ -1029,6 +1034,7 @@ static int __init init_scsi(void)
static void __exit exit_scsi(void) static void __exit exit_scsi(void)
{ {
scsi_sysfs_unregister(); scsi_sysfs_unregister();
scsi_exit_hosts();
scsi_exit_devinfo(); scsi_exit_devinfo();
devfs_remove("scsi"); devfs_remove("scsi");
scsi_exit_procfs(); scsi_exit_procfs();
......
...@@ -1285,7 +1285,12 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) ...@@ -1285,7 +1285,12 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
maybe_retry: maybe_retry:
if ((++scmd->retries) < scmd->allowed) { /* we requeue for retry because the error was retryable, and
* the request was not marked fast fail. Note that above,
* even if the request is marked fast fail, we still requeue
* for queue congestion conditions (QUEUE_FULL or BUSY) */
if ((++scmd->retries) < scmd->allowed
&& !blk_noretry_request(scmd->request)) {
return NEEDS_RETRY; return NEEDS_RETRY;
} else { } else {
/* /*
......
...@@ -502,14 +502,22 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, ...@@ -502,14 +502,22 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
* to queue the remainder of them. * to queue the remainder of them.
*/ */
if (end_that_request_first(req, uptodate, sectors)) { if (end_that_request_first(req, uptodate, sectors)) {
if (requeue) { int leftover = req->hard_nr_sectors - sectors;
/*
* Bleah. Leftovers again. Stick the leftovers in /* kill remainder if no retrys */
* the front of the queue, and goose the queue again. if (!uptodate && blk_noretry_request(req))
*/ end_that_request_first(req, 0, leftover);
scsi_requeue_command(q, cmd); else {
if (requeue)
/*
* Bleah. Leftovers again. Stick the
* leftovers in the front of the
* queue, and goose the queue again.
*/
scsi_requeue_command(q, cmd);
return cmd;
} }
return cmd;
} }
add_disk_randomness(req->rq_disk); add_disk_randomness(req->rq_disk);
......
...@@ -41,6 +41,12 @@ ...@@ -41,6 +41,12 @@
#define SCSI_SENSE_VALID(scmd) \ #define SCSI_SENSE_VALID(scmd) \
(((scmd)->sense_buffer[0] & 0x70) == 0x70) (((scmd)->sense_buffer[0] & 0x70) == 0x70)
/*
* Special value for scanning to specify scanning or rescanning of all
* possible channels, (target) ids, or luns on a given shost.
*/
#define SCAN_WILD_CARD ~0
/* /*
* scsi_target: representation of a scsi target, for now, this is only * scsi_target: representation of a scsi target, for now, this is only
* used for single_lun devices. If no one has active IO to the target, * used for single_lun devices. If no one has active IO to the target,
...@@ -51,6 +57,9 @@ struct scsi_target { ...@@ -51,6 +57,9 @@ struct scsi_target {
unsigned int starget_refcnt; unsigned int starget_refcnt;
}; };
/* hosts.c */
extern int scsi_init_hosts(void);
extern void scsi_exit_hosts(void);
/* scsi.c */ /* scsi.c */
extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
...@@ -106,20 +115,18 @@ extern void scsi_exit_procfs(void); ...@@ -106,20 +115,18 @@ extern void scsi_exit_procfs(void);
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
/* scsi_scan.c */ /* scsi_scan.c */
int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, unsigned int,
unsigned int, int);
extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_forget_host(struct Scsi_Host *);
extern void scsi_free_sdev(struct scsi_device *); extern void scsi_free_sdev(struct scsi_device *);
extern void scsi_free_shost(struct Scsi_Host *);
extern void scsi_rescan_device(struct device *); extern void scsi_rescan_device(struct device *);
/* scsi_sysfs.c */ /* scsi_sysfs.c */
extern int scsi_device_register(struct scsi_device *); extern int scsi_device_register(struct scsi_device *);
extern void scsi_sysfs_init_host(struct Scsi_Host *); extern int scsi_sysfs_add_host(struct Scsi_Host *);
extern int scsi_sysfs_add_host(struct Scsi_Host *, struct device *);
extern void scsi_sysfs_remove_host(struct Scsi_Host *);
extern int scsi_sysfs_register(void); extern int scsi_sysfs_register(void);
extern void scsi_sysfs_unregister(void); extern void scsi_sysfs_unregister(void);
extern struct class shost_class;
extern struct class sdev_class; extern struct class sdev_class;
extern struct bus_type scsi_bus_type; extern struct bus_type scsi_bus_type;
......
...@@ -81,6 +81,9 @@ static int proc_scsi_write_proc(struct file *file, const char *buf, ...@@ -81,6 +81,9 @@ static int proc_scsi_write_proc(struct file *file, const char *buf,
void scsi_proc_hostdir_add(struct scsi_host_template *sht) void scsi_proc_hostdir_add(struct scsi_host_template *sht)
{ {
if (!sht->proc_info)
return;
down(&global_host_template_sem); down(&global_host_template_sem);
if (!sht->present++) { if (!sht->present++) {
sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
...@@ -96,6 +99,9 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) ...@@ -96,6 +99,9 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
void scsi_proc_hostdir_rm(struct scsi_host_template *sht) void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
{ {
if (!sht->proc_info)
return;
down(&global_host_template_sem); down(&global_host_template_sem);
if (!--sht->present && sht->proc_dir) { if (!--sht->present && sht->proc_dir) {
remove_proc_entry(sht->proc_name, proc_scsi); remove_proc_entry(sht->proc_name, proc_scsi);
...@@ -189,21 +195,13 @@ static int proc_print_scsidevice(struct device *dev, void *data) ...@@ -189,21 +195,13 @@ static int proc_print_scsidevice(struct device *dev, void *data)
static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
{ {
struct Scsi_Host *shost; struct Scsi_Host *shost;
struct scsi_device *sdev;
int error = -ENXIO; int error = -ENXIO;
shost = scsi_host_lookup(host); shost = scsi_host_lookup(host);
if (IS_ERR(shost)) if (IS_ERR(shost))
return PTR_ERR(shost); return PTR_ERR(shost);
if (!scsi_find_device(shost, channel, id, lun)) { error = scsi_scan_host_selected(shost, channel, id, lun, 1);
sdev = scsi_add_device(shost, channel, id, lun);
if (IS_ERR(sdev))
error = PTR_ERR(sdev);
else
error = 0;
}
scsi_host_put(shost); scsi_host_put(shost);
return error; return error;
} }
......
...@@ -656,13 +656,32 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) ...@@ -656,13 +656,32 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
**/ **/
static int scsi_probe_and_add_lun(struct Scsi_Host *host, static int scsi_probe_and_add_lun(struct Scsi_Host *host,
uint channel, uint id, uint lun, int *bflagsp, uint channel, uint id, uint lun, int *bflagsp,
struct scsi_device **sdevp) struct scsi_device **sdevp, int rescan)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
struct scsi_request *sreq; struct scsi_request *sreq;
unsigned char *result; unsigned char *result;
int bflags, res = SCSI_SCAN_NO_RESPONSE; int bflags, res = SCSI_SCAN_NO_RESPONSE;
/*
* The rescan flag is used as an optimization, the first scan of a
* host adapter calls into here with rescan == 0.
*/
if (rescan) {
sdev = scsi_find_device(host, channel, id, lun);
if (sdev) {
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
"scsi scan: device exists on <%d:%d:%d:%d>\n",
host->host_no, channel, id, lun));
if (sdevp)
*sdevp = sdev;
if (bflagsp)
*bflagsp = scsi_get_device_flags(sdev->vendor,
sdev->model);
return SCSI_SCAN_LUN_PRESENT;
}
}
sdev = scsi_alloc_sdev(host, channel, id, lun); sdev = scsi_alloc_sdev(host, channel, id, lun);
if (!sdev) if (!sdev)
goto out; goto out;
...@@ -737,7 +756,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host, ...@@ -737,7 +756,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
* Modifies sdevscan->lun. * Modifies sdevscan->lun.
**/ **/
static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel, static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel,
uint id, int bflags, int lun0_res, int scsi_level) uint id, int bflags, int lun0_res, int scsi_level, int rescan)
{ {
unsigned int sparse_lun, lun, max_dev_lun; unsigned int sparse_lun, lun, max_dev_lun;
...@@ -806,7 +825,8 @@ static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel, ...@@ -806,7 +825,8 @@ static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel,
*/ */
for (lun = 1; lun < max_dev_lun; ++lun) for (lun = 1; lun < max_dev_lun; ++lun)
if ((scsi_probe_and_add_lun(shost, channel, id, lun, if ((scsi_probe_and_add_lun(shost, channel, id, lun,
NULL, NULL) != SCSI_SCAN_LUN_PRESENT) && !sparse_lun) NULL, NULL, rescan) != SCSI_SCAN_LUN_PRESENT) &&
!sparse_lun)
return; return;
} }
...@@ -857,7 +877,8 @@ static int scsilun_to_int(struct scsi_lun *scsilun) ...@@ -857,7 +877,8 @@ static int scsilun_to_int(struct scsi_lun *scsilun)
* 0: scan completed (or no memory, so further scanning is futile) * 0: scan completed (or no memory, so further scanning is futile)
* 1: no report lun scan, or not configured * 1: no report lun scan, or not configured
**/ **/
static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags) static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
int rescan)
{ {
char devname[64]; char devname[64];
unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned char scsi_cmd[MAX_COMMAND_SIZE];
...@@ -1011,7 +1032,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags) ...@@ -1011,7 +1032,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags)
int res; int res;
res = scsi_probe_and_add_lun(sdev->host, sdev->channel, res = scsi_probe_and_add_lun(sdev->host, sdev->channel,
sdev->id, lun, NULL, NULL); sdev->id, lun, NULL, NULL, rescan);
if (res == SCSI_SCAN_NO_RESPONSE) { if (res == SCSI_SCAN_NO_RESPONSE) {
/* /*
* Got some results, but now none, abort. * Got some results, but now none, abort.
...@@ -1037,7 +1058,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags) ...@@ -1037,7 +1058,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags)
return 0; return 0;
} }
#else #else
# define scsi_report_lun_scan(sdev, blags) (1) # define scsi_report_lun_scan(sdev, blags, rescan) (1)
#endif /* CONFIG_SCSI_REPORT_LUNS */ #endif /* CONFIG_SCSI_REPORT_LUNS */
struct scsi_device *scsi_add_device(struct Scsi_Host *shost, struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
...@@ -1046,7 +1067,7 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost, ...@@ -1046,7 +1067,7 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
struct scsi_device *sdev; struct scsi_device *sdev;
int res; int res;
res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev); res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1);
if (res != SCSI_SCAN_LUN_PRESENT) if (res != SCSI_SCAN_LUN_PRESENT)
sdev = ERR_PTR(-ENODEV); sdev = ERR_PTR(-ENODEV);
return sdev; return sdev;
...@@ -1083,7 +1104,7 @@ void scsi_rescan_device(struct device *dev) ...@@ -1083,7 +1104,7 @@ void scsi_rescan_device(struct device *dev)
* sequential scan of LUNs on the target id. * sequential scan of LUNs on the target id.
**/ **/
static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel, static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
unsigned int id) unsigned int id, unsigned int lun, int rescan)
{ {
int bflags = 0; int bflags = 0;
int res; int res;
...@@ -1095,19 +1116,29 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel, ...@@ -1095,19 +1116,29 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
*/ */
return; return;
if (lun != SCAN_WILD_CARD) {
/*
* Scan for a specific host/chan/id/lun.
*/
scsi_probe_and_add_lun(shost, channel, id, lun, NULL, NULL,
rescan);
return;
}
/* /*
* Scan LUN 0, if there is some response, scan further. Ideally, we * Scan LUN 0, if there is some response, scan further. Ideally, we
* would not configure LUN 0 until all LUNs are scanned. * would not configure LUN 0 until all LUNs are scanned.
*/ */
res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev); res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev,
rescan);
if (res == SCSI_SCAN_LUN_PRESENT) { if (res == SCSI_SCAN_LUN_PRESENT) {
if (scsi_report_lun_scan(sdev, bflags) != 0) if (scsi_report_lun_scan(sdev, bflags, rescan) != 0)
/* /*
* The REPORT LUN did not scan the target, * The REPORT LUN did not scan the target,
* do a sequential scan. * do a sequential scan.
*/ */
scsi_sequential_lun_scan(shost, channel, id, bflags, scsi_sequential_lun_scan(shost, channel, id, bflags,
res, sdev->scsi_level); res, sdev->scsi_level, rescan);
} else if (res == SCSI_SCAN_TARGET_PRESENT) { } else if (res == SCSI_SCAN_TARGET_PRESENT) {
/* /*
* There's a target here, but lun 0 is offline so we * There's a target here, but lun 0 is offline so we
...@@ -1116,37 +1147,26 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel, ...@@ -1116,37 +1147,26 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
* a default scsi level of SCSI_2 * a default scsi level of SCSI_2
*/ */
scsi_sequential_lun_scan(shost, channel, id, BLIST_SPARSELUN, scsi_sequential_lun_scan(shost, channel, id, BLIST_SPARSELUN,
SCSI_SCAN_TARGET_PRESENT, SCSI_2); SCSI_SCAN_TARGET_PRESENT, SCSI_2, rescan);
} }
} }
/** static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
* scsi_scan_host - scan the given adapter unsigned int id, unsigned int lun, int rescan)
* @shost: adapter to scan
*
* Description:
* Iterate and call scsi_scan_target to scan all possible target id's
* on all possible channels.
**/
void scsi_scan_host(struct Scsi_Host *shost)
{ {
uint channel, id, order_id; uint order_id;
/* if (id == SCAN_WILD_CARD)
* The sdevscan host, channel, id and lun are filled in as
* needed to scan.
*/
for (channel = 0; channel <= shost->max_channel; channel++) {
/*
* XXX adapter drivers when possible (FCP, iSCSI)
* could modify max_id to match the current max,
* not the absolute max.
*
* XXX add a shost id iterator, so for example,
* the FC ID can be the same as a target id
* without a huge overhead of sparse id's.
*/
for (id = 0; id < shost->max_id; ++id) { for (id = 0; id < shost->max_id; ++id) {
/*
* XXX adapter drivers when possible (FCP, iSCSI)
* could modify max_id to match the current max,
* not the absolute max.
*
* XXX add a shost id iterator, so for example,
* the FC ID can be the same as a target id
* without a huge overhead of sparse id's.
*/
if (shost->reverse_ordering) if (shost->reverse_ordering)
/* /*
* Scan from high to low id. * Scan from high to low id.
...@@ -1154,9 +1174,39 @@ void scsi_scan_host(struct Scsi_Host *shost) ...@@ -1154,9 +1174,39 @@ void scsi_scan_host(struct Scsi_Host *shost)
order_id = shost->max_id - id - 1; order_id = shost->max_id - id - 1;
else else
order_id = id; order_id = id;
scsi_scan_target(shost, channel, order_id); scsi_scan_target(shost, channel, order_id, lun, rescan);
} }
} else
scsi_scan_target(shost, channel, id, lun, rescan);
}
int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun, int rescan)
{
SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "%s: <%u:%u:%u:%u>\n",
__FUNCTION__, shost->host_no, channel, id, lun));
if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
((id != SCAN_WILD_CARD) && (id > shost->max_id)) ||
((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
return -EINVAL;
if (channel == SCAN_WILD_CARD)
for (channel = 0; channel <= shost->max_channel; channel++)
scsi_scan_channel(shost, channel, id, lun, rescan);
else
scsi_scan_channel(shost, channel, id, lun, rescan);
return 0;
}
/**
* scsi_scan_host - scan the given adapter
* @shost: adapter to scan
**/
void scsi_scan_host(struct Scsi_Host *shost)
{
scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
SCAN_WILD_CARD, 0);
} }
void scsi_forget_host(struct Scsi_Host *shost) void scsi_forget_host(struct Scsi_Host *shost)
......
...@@ -15,6 +15,43 @@ ...@@ -15,6 +15,43 @@
#include "hosts.h" #include "hosts.h"
#include "scsi_priv.h" #include "scsi_priv.h"
#include "scsi_logging.h"
static int check_set(unsigned int *val, char *src)
{
char *last;
if (strncmp(src, "-", 20) == 0) {
*val = SCAN_WILD_CARD;
} else {
/*
* Doesn't check for int overflow
*/
*val = simple_strtoul(src, &last, 0);
if (*last != '\0')
return 1;
}
return 0;
}
static int scsi_scan(struct Scsi_Host *shost, const char *str)
{
char s1[15], s2[15], s3[15], junk;
unsigned int channel, id, lun;
int res;
res = sscanf(str, "%10s %10s %10s %c", s1, s2, s3, &junk);
if (res != 3)
return -EINVAL;
if (check_set(&channel, s1))
return -EINVAL;
if (check_set(&id, s2))
return -EINVAL;
if (check_set(&lun, s3))
return -EINVAL;
res = scsi_scan_host_selected(shost, channel, id, lun, 1);
return res;
}
/* /*
* shost_show_function: macro to create an attr function that can be used to * shost_show_function: macro to create an attr function that can be used to
...@@ -39,6 +76,20 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) ...@@ -39,6 +76,20 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL)
/* /*
* Create the actual show/store functions and data structures. * Create the actual show/store functions and data structures.
*/ */
static ssize_t store_scan(struct class_device *class_dev, const char *buf,
size_t count)
{
struct Scsi_Host *shost = class_to_shost(class_dev);
int res;
res = scsi_scan(shost, buf);
if (res == 0)
res = count;
return res;
};
static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
shost_rd_attr(unique_id, "%u\n"); shost_rd_attr(unique_id, "%u\n");
shost_rd_attr(host_busy, "%hu\n"); shost_rd_attr(host_busy, "%hu\n");
shost_rd_attr(cmd_per_lun, "%hd\n"); shost_rd_attr(cmd_per_lun, "%hd\n");
...@@ -51,33 +102,10 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { ...@@ -51,33 +102,10 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
&class_device_attr_cmd_per_lun, &class_device_attr_cmd_per_lun,
&class_device_attr_sg_tablesize, &class_device_attr_sg_tablesize,
&class_device_attr_unchecked_isa_dma, &class_device_attr_unchecked_isa_dma,
&class_device_attr_scan,
NULL NULL
}; };
static void scsi_host_cls_release(struct class_device *class_dev)
{
struct Scsi_Host *shost;
shost = class_to_shost(class_dev);
put_device(&shost->shost_gendev);
}
static void scsi_host_dev_release(struct device *dev)
{
struct Scsi_Host *shost;
struct device *parent;
parent = dev->parent;
shost = dev_to_shost(dev);
scsi_free_shost(shost);
put_device(parent);
}
struct class shost_class = {
.name = "scsi_host",
.release = scsi_host_cls_release,
};
static void scsi_device_cls_release(struct class_device *class_dev) static void scsi_device_cls_release(struct class_device *class_dev)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
...@@ -113,33 +141,23 @@ struct bus_type scsi_bus_type = { ...@@ -113,33 +141,23 @@ struct bus_type scsi_bus_type = {
.match = scsi_bus_match, .match = scsi_bus_match,
}; };
int scsi_sysfs_register(void) int scsi_sysfs_register(void)
{ {
int error; int error;
error = bus_register(&scsi_bus_type); error = bus_register(&scsi_bus_type);
if (error) if (!error) {
return error; error = class_register(&sdev_class);
error = class_register(&shost_class); if (error)
if (error) bus_unregister(&scsi_bus_type);
goto bus_unregister; }
error = class_register(&sdev_class);
if (error)
goto class_unregister;
return 0;
class_unregister:
class_unregister(&shost_class);
bus_unregister:
bus_unregister(&scsi_bus_type);
return error; return error;
} }
void scsi_sysfs_unregister(void) void scsi_sysfs_unregister(void)
{ {
class_unregister(&sdev_class); class_unregister(&sdev_class);
class_unregister(&shost_class);
bus_unregister(&scsi_bus_type); bus_unregister(&scsi_bus_type);
} }
...@@ -243,6 +261,24 @@ store_rescan_field (struct device *dev, const char *buf, size_t count) ...@@ -243,6 +261,24 @@ store_rescan_field (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field) static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field)
static ssize_t sdev_store_delete(struct device *dev, const char *buf,
size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
int res = count;
if (sdev->access_count)
/*
* FIXME and scsi_proc.c: racey use of access_count,
* possibly add a new arg to scsi_remove_device.
*/
res = -EBUSY;
else
scsi_remove_device(sdev);
return res;
};
static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
/* Default template for device attributes. May NOT be modified */ /* Default template for device attributes. May NOT be modified */
static struct device_attribute *scsi_sysfs_sdev_attrs[] = { static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
&dev_attr_device_blocked, &dev_attr_device_blocked,
...@@ -255,6 +291,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = { ...@@ -255,6 +291,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
&dev_attr_rev, &dev_attr_rev,
&dev_attr_online, &dev_attr_online,
&dev_attr_rescan, &dev_attr_rescan,
&dev_attr_delete,
NULL NULL
}; };
...@@ -403,20 +440,6 @@ int scsi_register_interface(struct class_interface *intf) ...@@ -403,20 +440,6 @@ int scsi_register_interface(struct class_interface *intf)
} }
void scsi_sysfs_init_host(struct Scsi_Host *shost)
{
device_initialize(&shost->shost_gendev);
snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
shost->shost_gendev.release = scsi_host_dev_release;
class_device_initialize(&shost->shost_classdev);
shost->shost_classdev.dev = &shost->shost_gendev;
shost->shost_classdev.class = &shost_class;
snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
shost->host_no);
}
static struct class_device_attribute *class_attr_overridden( static struct class_device_attribute *class_attr_overridden(
struct class_device_attribute **attrs, struct class_device_attribute **attrs,
struct class_device_attribute *attr) struct class_device_attribute *attr)
...@@ -459,31 +482,16 @@ static int class_attr_add(struct class_device *classdev, ...@@ -459,31 +482,16 @@ static int class_attr_add(struct class_device *classdev,
* @shost: scsi host struct to add to subsystem * @shost: scsi host struct to add to subsystem
* @dev: parent struct device pointer * @dev: parent struct device pointer
**/ **/
int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) int scsi_sysfs_add_host(struct Scsi_Host *shost)
{ {
int error, i; int error, i;
if (!shost->shost_gendev.parent)
shost->shost_gendev.parent = dev ? dev : &legacy_bus;
error = device_add(&shost->shost_gendev);
if (error)
return error;
set_bit(SHOST_ADD, &shost->shost_state);
get_device(shost->shost_gendev.parent);
error = class_device_add(&shost->shost_classdev);
if (error)
goto clean_device;
get_device(&shost->shost_gendev);
if (shost->hostt->shost_attrs) { if (shost->hostt->shost_attrs) {
for (i = 0; shost->hostt->shost_attrs[i]; i++) { for (i = 0; shost->hostt->shost_attrs[i]; i++) {
error = class_attr_add(&shost->shost_classdev, error = class_attr_add(&shost->shost_classdev,
shost->hostt->shost_attrs[i]); shost->hostt->shost_attrs[i]);
if (error) if (error)
goto clean_class; return error;
} }
} }
...@@ -493,31 +501,9 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) ...@@ -493,31 +501,9 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev)
error = class_device_create_file(&shost->shost_classdev, error = class_device_create_file(&shost->shost_classdev,
scsi_sysfs_shost_attrs[i]); scsi_sysfs_shost_attrs[i]);
if (error) if (error)
goto clean_class; return error;
} }
} }
return error; return 0;
clean_class:
class_device_del(&shost->shost_classdev);
clean_device:
device_del(&shost->shost_gendev);
return error;
}
/**
* scsi_sysfs_remove_host - remove scsi host from subsystem
* @shost: scsi host to remove from subsystem
**/
void scsi_sysfs_remove_host(struct Scsi_Host *shost)
{
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
set_bit(SHOST_DEL, &shost->shost_state);
spin_unlock_irqrestore(shost->host_lock, flags);
class_device_unregister(&shost->shost_classdev);
device_del(&shost->shost_gendev);
} }
...@@ -308,6 +308,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) ...@@ -308,6 +308,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[4] = (unsigned char) this_count; SCpnt->cmnd[4] = (unsigned char) this_count;
SCpnt->cmnd[5] = 0; SCpnt->cmnd[5] = 0;
} }
SCpnt->request_bufflen = SCpnt->bufflen =
this_count * sdp->sector_size;
/* /*
* We shouldn't disconnect in the middle of a sector, so with a dumb * We shouldn't disconnect in the middle of a sector, so with a dumb
...@@ -1353,10 +1355,14 @@ static int sd_remove(struct device *dev) ...@@ -1353,10 +1355,14 @@ static int sd_remove(struct device *dev)
static void sd_shutdown(struct device *dev) static void sd_shutdown(struct device *dev)
{ {
struct scsi_device *sdp = to_scsi_device(dev); struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp = dev_get_drvdata(dev); struct scsi_disk *sdkp;
struct scsi_request *sreq; struct scsi_request *sreq;
int retries, res; int retries, res;
sdkp = dev_get_drvdata(dev);
if (!sdkp)
return; /* this can happen */
if (!sdp->online || !sdkp->WCE) if (!sdp->online || !sdkp->WCE)
return; return;
......
...@@ -340,6 +340,20 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) ...@@ -340,6 +340,20 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
return 0; return 0;
} }
{
struct scatterlist *sg = SCpnt->request_buffer;
int i, size = 0;
for (i = 0; i < SCpnt->use_sg; i++)
size += sg[i].length;
if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
printk(KERN_ERR "sr: mismatch count %d, bytes %d\n",
size, SCpnt->request_bufflen);
if (SCpnt->request_bufflen > size)
SCpnt->request_bufflen = SCpnt->bufflen = size;
}
}
/* /*
* request doesn't start on hw block boundary, add scatter pads * request doesn't start on hw block boundary, add scatter pads
*/ */
...@@ -361,8 +375,11 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) ...@@ -361,8 +375,11 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[1] = 0; SCpnt->cmnd[1] = 0;
block = (unsigned int)SCpnt->request->sector / (s_size >> 9); block = (unsigned int)SCpnt->request->sector / (s_size >> 9);
if (this_count > 0xffff) if (this_count > 0xffff) {
this_count = 0xffff; this_count = 0xffff;
SCpnt->request_bufflen = SCpnt->bufflen =
this_count * s_size;
}
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
...@@ -390,18 +407,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) ...@@ -390,18 +407,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
*/ */
SCpnt->done = rw_intr; SCpnt->done = rw_intr;
{
struct scatterlist *sg = SCpnt->request_buffer;
int i, size = 0;
for (i = 0; i < SCpnt->use_sg; i++)
size += sg[i].length;
if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
printk("sr: mismatch count %d, bytes %d\n", size, SCpnt->request_bufflen);
SCpnt->request_bufflen = size;
}
}
/* /*
* This indicates that the command is ready from our end to be * This indicates that the command is ready from our end to be
* queued. * queued.
......
...@@ -2029,7 +2029,7 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) ...@@ -2029,7 +2029,7 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
printf_info("%s: giving up ...\n", sym_name(np)); printf_info("%s: giving up ...\n", sym_name(np));
if (np) if (np)
sym_free_resources(np); sym_free_resources(np);
scsi_unregister(instance); scsi_host_put(instance);
return -1; return -1;
} }
......
...@@ -5942,14 +5942,7 @@ int sym_hcb_attach(hcb_p np, struct sym_fw *fw) ...@@ -5942,14 +5942,7 @@ int sym_hcb_attach(hcb_p np, struct sym_fw *fw)
*/ */
return 0; return 0;
/*
* We have failed.
* We will try to free all the resources we have
* allocated, but if we are a boot device, this
* will not help that much.;)
*/
attach_failed: attach_failed:
sym_hcb_free(np);
return -ENXIO; return -ENXIO;
} }
......
...@@ -135,11 +135,9 @@ zalon_scsi_callback(struct parisc_device *dev) ...@@ -135,11 +135,9 @@ zalon_scsi_callback(struct parisc_device *dev)
if(!host) if(!host)
goto fail; goto fail;
strlcpy(dev->dev.name, "zalon7xx", sizeof(dev->dev.name)); if(request_irq(irq, ncr53c8xx_intr, SA_SHIRQ, dev->dev.bus_id, host)) {
if(request_irq(irq, ncr53c8xx_intr, SA_SHIRQ, dev->dev.name, host)) {
printk(KERN_ERR "%s: irq problem with %d, detaching\n ", printk(KERN_ERR "%s: irq problem with %d, detaching\n ",
dev->dev.name, irq); dev->dev.bus_id, irq);
goto fail; goto fail;
} }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
*/ */
#include <linux/types.h>
/* /*
* SCSI command lengths * SCSI command lengths
*/ */
......
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