Commit 3aee2f2f authored by Andrew Morton's avatar Andrew Morton Committed by Jens Axboe

[PATCH] cciss driver update

Patch from: steve cameron <steve.cameron@hp.com>

Steve sent out a nice series of 11 broken-out patches.  I have lumped them
all together.

- Makes the cciss driver compile in 2.5.60  (from tony@cantech.net.au)

- From randy.dunlap@verizon.net, fix memory leaks in cciss driver

- Allow cciss driver attached disks other than the first to be accessed.

- Zero out cylinders when zeroing out other disk info in cciss driver.

- Remove unused variable from cciss_scsi.c

- This patch makes scsi commands to tape drives have no timeouts.
  Previously the timeout was 1000 seconds, too short, and nothing good
  happens when the timeout expires.  Better to have no timeout.  e.g.  mt -f
  /dev/st0 erase may take about 2 hours 30 min on AIT 100.

- Remove unneeded cciss_scsi init code from cciss driver.

- Remove udelay in command polling routine
- extend timeout to 20 seconds (need for certain multiport storage box)
- Remove unneeded init time code in cciss_scsi.c (thus allowing removal
  of udelay in command polling code.)

- Factor out duplicated read capacity code into common routine in cciss
  driver.

- factor duplicated geometry inquiry code into common routine in cciss
  driver.
parent ecc3f712
This diff is collapsed.
...@@ -89,8 +89,10 @@ static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { ...@@ -89,8 +89,10 @@ static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = {
working even with the SCSI system. It's so working even with the SCSI system. It's so
scsi_unregister_host will differentiate the controllers. scsi_unregister_host will differentiate the controllers.
When register_scsi_module is called, each host template is When register_scsi_module is called, each host template is
customized (name change) in cciss_register_scsi() customized (name change) in cciss_register_scsi() (that's
(that's called from cciss.c:cciss_init_one()) */ called from cciss_engage_scsi, called from
cciss.c:cciss_proc_write(), on "engage scsi" being received
from user space.) */
static static
Scsi_Host_Template driver_template[MAX_CTLR] = Scsi_Host_Template driver_template[MAX_CTLR] =
...@@ -199,14 +201,12 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd) ...@@ -199,14 +201,12 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd)
} }
static int static int
scsi_cmd_stack_setup(int ctlr) scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa)
{ {
int i; int i;
struct cciss_scsi_adapter_data_t *sa;
struct cciss_scsi_cmd_stack_t *stk; struct cciss_scsi_cmd_stack_t *stk;
size_t size; size_t size;
sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr;
stk = &sa->cmd_stack; stk = &sa->cmd_stack;
size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
...@@ -535,126 +535,24 @@ lookup_scsi3addr(int ctlr, int bus, int target, int lun, char *scsi3addr) ...@@ -535,126 +535,24 @@ lookup_scsi3addr(int ctlr, int bus, int target, int lun, char *scsi3addr)
return -1; return -1;
} }
static void static void
cciss_find_non_disk_devices(int cntl_num) cciss_scsi_setup(int cntl_num)
{ {
ReportLunData_struct *ld_buff; struct cciss_scsi_adapter_data_t * shba;
InquiryData_struct *inq_buff;
int return_code;
int i;
int listlength = 0;
int num_luns;
unsigned char scsi3addr[8];
unsigned long flags;
int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
hba[cntl_num]->scsi_ctlr = (void *)
kmalloc(sizeof(struct cciss_scsi_adapter_data_t),
GFP_KERNEL);
if (hba[cntl_num]->scsi_ctlr == NULL)
return;
((struct cciss_scsi_adapter_data_t *)
hba[cntl_num]->scsi_ctlr)->scsi_host = NULL;
((struct cciss_scsi_adapter_data_t *)
hba[cntl_num]->scsi_ctlr)->lock = SPIN_LOCK_UNLOCKED;
((struct cciss_scsi_adapter_data_t *)
hba[cntl_num]->scsi_ctlr)->registered = 0;
if (scsi_cmd_stack_setup(cntl_num) != 0) {
printk("Trouble, returned non-zero!\n");
return;
}
ld_buff = kmalloc(reportlunsize, GFP_KERNEL);
if (ld_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
return;
}
memset(ld_buff, 0, sizeof(ReportLunData_struct));
inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
return;
}
/* Get the physical luns */
return_code = sendcmd(CISS_REPORT_PHYS, cntl_num, ld_buff,
reportlunsize, 0, 0, 0, NULL );
if( return_code == IO_OK) {
unsigned char *c = &ld_buff->LUNListLength[0];
listlength = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}
else { /* getting report of physical luns failed */
printk(KERN_WARNING "cciss: report physical luns"
" command failed\n");
listlength = 0;
}
CPQ_TAPE_LOCK(cntl_num, flags);
ccissscsi[cntl_num].ndevices = 0; ccissscsi[cntl_num].ndevices = 0;
num_luns = listlength / 8; // 8 bytes pre entry shba = (struct cciss_scsi_adapter_data_t *)
/* printk("Found %d LUNs\n", num_luns); */ kmalloc(sizeof(*shba), GFP_KERNEL);
if (shba == NULL)
if (num_luns > CISS_MAX_PHYS_LUN) return;
{ shba->scsi_host = NULL;
printk(KERN_WARNING shba->lock = SPIN_LOCK_UNLOCKED;
"cciss: Maximum physical LUNs (%d) exceeded. " shba->registered = 0;
"%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, if (scsi_cmd_stack_setup(cntl_num, shba) != 0) {
num_luns - CISS_MAX_PHYS_LUN); kfree(shba);
num_luns = CISS_MAX_PHYS_LUN; shba = NULL;
}
for(i=0; i<num_luns; i++) {
/* Execute an inquiry to figure the device type */
memset(inq_buff, 0, sizeof(InquiryData_struct));
memcpy(scsi3addr, ld_buff->LUN[i], 8); /* ugly... */
return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
sizeof(InquiryData_struct), 2, 0 ,0, scsi3addr );
if (return_code == IO_OK) {
if(inq_buff->data_byte[8] == 0xFF)
{
printk(KERN_WARNING "cciss: inquiry failed\n");
} else {
int devtype;
/* printk("Inquiry...\n");
print_bytes((unsigned char *) inq_buff, 36, 1, 1); */
devtype = (inq_buff->data_byte[0] & 0x1f);
switch (devtype)
{
case 0x01: /* sequential access, (tape) */
case 0x08: /* medium changer */
/* this is the only kind of dev */
/* we want to expose here. */
if (cciss_scsi_add_entry(cntl_num, -1,
(unsigned char *) ld_buff->LUN[i],
devtype) != 0)
i=num_luns; // leave loop
break;
default:
break;
}
}
}
else printk("cciss: inquiry failed.\n");
} }
#if 0 hba[cntl_num]->scsi_ctlr = (void *) shba;
for (i=0;i<ccissscsi[cntl_num].ndevices;i++)
printk("Tape device presented at c%db%dt%dl%d\n",
cntl_num, // <-- this is wrong
ccissscsi[cntl_num].dev[i].bus,
ccissscsi[cntl_num].dev[i].target,
ccissscsi[cntl_num].dev[i].lun);
#endif
CPQ_TAPE_UNLOCK(cntl_num, flags);
kfree(ld_buff);
kfree(inq_buff);
return; return;
} }
...@@ -913,7 +811,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c, ...@@ -913,7 +811,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c,
memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
memcpy(cp->Request.CDB, cdb, cdblen); memcpy(cp->Request.CDB, cdb, cdblen);
cp->Request.Timeout = 1000; // guarantee completion. cp->Request.Timeout = 0;
cp->Request.CDBLen = cdblen; cp->Request.CDBLen = cdblen;
cp->Request.Type.Type = TYPE_CMD; cp->Request.Type.Type = TYPE_CMD;
cp->Request.Type.Attribute = ATTR_SIMPLE; cp->Request.Type.Attribute = ATTR_SIMPLE;
...@@ -1262,7 +1160,6 @@ cciss_scsi_proc_info(char *buffer, /* data buffer */ ...@@ -1262,7 +1160,6 @@ cciss_scsi_proc_info(char *buffer, /* data buffer */
int buflen, datalen; int buflen, datalen;
struct Scsi_Host *sh; struct Scsi_Host *sh;
int found;
ctlr_info_t *ci; ctlr_info_t *ci;
int cntl_num; int cntl_num;
...@@ -1382,8 +1279,8 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) ...@@ -1382,8 +1279,8 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
c = (ctlr_info_t **) &cmd->device->host->hostdata[0]; c = (ctlr_info_t **) &cmd->device->host->hostdata[0];
ctlr = (*c)->ctlr; ctlr = (*c)->ctlr;
rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id, cmd->device->lun, rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id,
scsi3addr); cmd->device->lun, scsi3addr);
if (rc != 0) { if (rc != 0) {
/* the scsi nexus does not match any that we presented... */ /* the scsi nexus does not match any that we presented... */
/* pretend to mid layer that we got selection timeout */ /* pretend to mid layer that we got selection timeout */
...@@ -1428,7 +1325,7 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) ...@@ -1428,7 +1325,7 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
// Fill in the request block... // Fill in the request block...
cp->Request.Timeout = 1000; // guarantee completion cp->Request.Timeout = 0;
memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG(); if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG();
cp->Request.CDBLen = cmd->cmd_len; cp->Request.CDBLen = cmd->cmd_len;
...@@ -1531,7 +1428,7 @@ cciss_unregister_scsi(int ctlr) ...@@ -1531,7 +1428,7 @@ cciss_unregister_scsi(int ctlr)
} }
static int static int
cciss_register_scsi(int ctlr, int this_is_init_time) cciss_register_scsi(int ctlr)
{ {
unsigned long flags; unsigned long flags;
...@@ -1541,15 +1438,10 @@ cciss_register_scsi(int ctlr, int this_is_init_time) ...@@ -1541,15 +1438,10 @@ cciss_register_scsi(int ctlr, int this_is_init_time)
driver_template[ctlr].module = THIS_MODULE;; driver_template[ctlr].module = THIS_MODULE;;
/* Since this is really a block driver, the SCSI core may not be /* Since this is really a block driver, the SCSI core may not be
initialized yet, in which case, calling scsi_register_host initialized at init time, in which case, calling scsi_register_host
would hang. instead, we will do it later, via /proc filesystem would hang. Instead, we do it later, via /proc filesystem
and rc scripts, when we know SCSI core is good to go. */ and rc scripts, when we know SCSI core is good to go. */
if (this_is_init_time) {
CPQ_TAPE_UNLOCK(ctlr, flags);
return 0;
}
/* Only register if SCSI devices are detected. */ /* Only register if SCSI devices are detected. */
if (ccissscsi[ctlr].ndevices != 0) { if (ccissscsi[ctlr].ndevices != 0) {
((struct cciss_scsi_adapter_data_t *) ((struct cciss_scsi_adapter_data_t *)
...@@ -1583,7 +1475,7 @@ cciss_engage_scsi(int ctlr) ...@@ -1583,7 +1475,7 @@ cciss_engage_scsi(int ctlr)
} }
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
cciss_update_non_disk_devices(ctlr, -1); cciss_update_non_disk_devices(ctlr, -1);
cciss_register_scsi(ctlr, 0); cciss_register_scsi(ctlr);
return 0; return 0;
} }
...@@ -1607,9 +1499,9 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) ...@@ -1607,9 +1499,9 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len)
/* If no tape support, then these become defined out of existence */ /* If no tape support, then these become defined out of existence */
#define cciss_find_non_disk_devices(cntl_num) #define cciss_scsi_setup(cntl_num)
#define cciss_unregister_scsi(ctlr) #define cciss_unregister_scsi(ctlr)
#define cciss_register_scsi(ctlr, this_is_init_time) #define cciss_register_scsi(ctlr)
#define cciss_proc_tape_report(ctlr, buffer, pos, len) #define cciss_proc_tape_report(ctlr, buffer, pos, len)
#endif /* CONFIG_CISS_SCSI_TAPE */ #endif /* CONFIG_CISS_SCSI_TAPE */
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