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
...@@ -114,6 +114,9 @@ static void cciss_getgeometry(int cntl_num); ...@@ -114,6 +114,9 @@ static void cciss_getgeometry(int cntl_num);
static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c); static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c);
static void start_io( ctlr_info_t *h); static void start_io( ctlr_info_t *h);
static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
unsigned char *scsi3addr);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int cciss_proc_get_info(char *buffer, char **start, off_t offset, static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
...@@ -353,7 +356,7 @@ static int cciss_open(struct inode *inode, struct file *filep) ...@@ -353,7 +356,7 @@ static int cciss_open(struct inode *inode, struct file *filep)
* but I'm already using way to many device nodes to claim another one * but I'm already using way to many device nodes to claim another one
* for "raw controller". * for "raw controller".
*/ */
if (inode->i_bdev->bd_inode->i_size == 0) { if (hba[ctlr]->drv[dsk].nr_blocks == 0) {
if (minor(inode->i_rdev) != 0) if (minor(inode->i_rdev) != 0)
return -ENXIO; return -ENXIO;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
...@@ -809,6 +812,7 @@ static int deregister_disk(int ctlr, int logvol) ...@@ -809,6 +812,7 @@ static int deregister_disk(int ctlr, int logvol)
/* zero out the disk size info */ /* zero out the disk size info */
h->drv[logvol].nr_blocks = 0; h->drv[logvol].nr_blocks = 0;
h->drv[logvol].block_size = 0; h->drv[logvol].block_size = 0;
h->drv[logvol].cylinders = 0;
h->drv[logvol].LunID = 0; h->drv[logvol].LunID = 0;
return(0); return(0);
} }
...@@ -1002,6 +1006,73 @@ case CMD_HARDWARE_ERR: ...@@ -1002,6 +1006,73 @@ case CMD_HARDWARE_ERR:
return(return_status); return(return_status);
} }
static void cciss_geometry_inquiry(int ctlr, int logvol,
int withirq, unsigned int total_size,
unsigned int block_size, InquiryData_struct *inq_buff,
drive_info_struct *drv)
{
int return_code;
memset(inq_buff, 0, sizeof(InquiryData_struct));
if (withirq)
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1);
else
return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,
sizeof(*inq_buff), 1, logvol ,0xC1, NULL);
if (return_code == IO_OK) {
if(inq_buff->data_byte[8] == 0xFF) {
printk(KERN_WARNING
"cciss: reading geometry failed, volume "
"does not support reading geometry\n");
drv->block_size = block_size;
drv->nr_blocks = total_size;
drv->heads = 255;
drv->sectors = 32; // Sectors per track
drv->cylinders = total_size / 255 / 32;
} else {
drv->block_size = block_size;
drv->nr_blocks = total_size;
drv->heads = inq_buff->data_byte[6];
drv->sectors = inq_buff->data_byte[7];
drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8;
drv->cylinders += inq_buff->data_byte[5];
}
} else { /* Get geometry failed */
printk(KERN_WARNING "cciss: reading geometry failed, "
"continuing with default geometry\n");
drv->block_size = block_size;
drv->nr_blocks = total_size;
drv->heads = 255;
drv->sectors = 32; // Sectors per track
drv->cylinders = total_size / 255 / 32;
}
printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n",
drv->heads, drv->sectors, drv->cylinders);
}
static void
cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
int withirq, unsigned int *total_size, unsigned int *block_size)
{
int return_code;
memset(buf, 0, sizeof(*buf));
if (withirq)
return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
ctlr, buf, sizeof(*buf), 1, logvol, 0 );
else
return_code = sendcmd(CCISS_READ_CAPACITY,
ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL );
if (return_code == IO_OK) {
*total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1;
*block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0]));
} else { /* read capacity command failed */
printk(KERN_WARNING "cciss: read capacity failed\n");
*total_size = 0;
*block_size = BLOCK_SIZE;
}
printk(KERN_INFO " blocks= %d block_size= %d\n",
*total_size, *block_size);
return;
}
static int register_new_disk(int ctlr) static int register_new_disk(int ctlr)
{ {
struct gendisk *disk; struct gendisk *disk;
...@@ -1013,9 +1084,9 @@ static int register_new_disk(int ctlr) ...@@ -1013,9 +1084,9 @@ static int register_new_disk(int ctlr)
int new_lun_index = 0; int new_lun_index = 0;
int free_index_found = 0; int free_index_found = 0;
int free_index = 0; int free_index = 0;
ReportLunData_struct *ld_buff; ReportLunData_struct *ld_buff = NULL;
ReadCapdata_struct *size_buff; ReadCapdata_struct *size_buff = NULL;
InquiryData_struct *inq_buff; InquiryData_struct *inq_buff = NULL;
int return_code; int return_code;
int listlength = 0; int listlength = 0;
__u32 lunid = 0; __u32 lunid = 0;
...@@ -1030,26 +1101,14 @@ static int register_new_disk(int ctlr) ...@@ -1030,26 +1101,14 @@ static int register_new_disk(int ctlr)
ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
if (ld_buff == NULL) if (ld_buff == NULL)
{ goto mem_msg;
printk(KERN_ERR "cciss: out of memory\n");
return -1;
}
memset(ld_buff, 0, sizeof(ReportLunData_struct)); memset(ld_buff, 0, sizeof(ReportLunData_struct));
size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
if (size_buff == NULL) if (size_buff == NULL)
{ goto mem_msg;
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
return -1;
}
inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) if (inq_buff == NULL)
{ goto mem_msg;
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
kfree(size_buff);
return -1;
}
return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
sizeof(ReportLunData_struct), 0, 0, 0 ); sizeof(ReportLunData_struct), 0, 0, 0 );
...@@ -1068,7 +1127,7 @@ static int register_new_disk(int ctlr) ...@@ -1068,7 +1127,7 @@ static int register_new_disk(int ctlr)
printk(KERN_WARNING "cciss: report logical volume" printk(KERN_WARNING "cciss: report logical volume"
" command failed\n"); " command failed\n");
listlength = 0; listlength = 0;
return -1; goto free_err;
} }
num_luns = listlength / 8; // 8 bytes pre entry num_luns = listlength / 8; // 8 bytes pre entry
if (num_luns > CISS_MAX_LUN) if (num_luns > CISS_MAX_LUN)
...@@ -1119,7 +1178,7 @@ static int register_new_disk(int ctlr) ...@@ -1119,7 +1178,7 @@ static int register_new_disk(int ctlr)
if (!new_lun_found) if (!new_lun_found)
{ {
printk(KERN_WARNING "cciss: New Logical Volume not found\n"); printk(KERN_WARNING "cciss: New Logical Volume not found\n");
return -1; goto free_err;
} }
/* Now find the free index */ /* Now find the free index */
for(i=0; i <CISS_MAX_LUN; i++) for(i=0; i <CISS_MAX_LUN; i++)
...@@ -1140,7 +1199,7 @@ static int register_new_disk(int ctlr) ...@@ -1140,7 +1199,7 @@ static int register_new_disk(int ctlr)
if (!free_index_found) if (!free_index_found)
{ {
printk(KERN_WARNING "cciss: unable to find free slot for disk\n"); printk(KERN_WARNING "cciss: unable to find free slot for disk\n");
return -1; goto free_err;
} }
logvol = free_index; logvol = free_index;
...@@ -1148,113 +1207,44 @@ static int register_new_disk(int ctlr) ...@@ -1148,113 +1207,44 @@ static int register_new_disk(int ctlr)
/* there could be gaps in lun numbers, track hightest */ /* there could be gaps in lun numbers, track hightest */
if(hba[ctlr]->highest_lun < lunid) if(hba[ctlr]->highest_lun < lunid)
hba[ctlr]->highest_lun = logvol; hba[ctlr]->highest_lun = logvol;
cciss_read_capacity(ctlr, logvol, size_buff, 1,
memset(size_buff, 0, sizeof(ReadCapdata_struct)); &total_size, &block_size);
return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, size_buff, cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,
sizeof( ReadCapdata_struct), 1, logvol, 0 ); inq_buff, &hba[ctlr]->drv[logvol]);
if (return_code == IO_OK)
{
total_size = (0xff &
(unsigned int)(size_buff->total_size[0])) << 24;
total_size |= (0xff &
(unsigned int)(size_buff->total_size[1])) << 16;
total_size |= (0xff &
(unsigned int)(size_buff->total_size[2])) << 8;
total_size |= (0xff & (unsigned int)
(size_buff->total_size[3]));
total_size++; // command returns highest block address
block_size = (0xff &
(unsigned int)(size_buff->block_size[0])) << 24;
block_size |= (0xff &
(unsigned int)(size_buff->block_size[1])) << 16;
block_size |= (0xff &
(unsigned int)(size_buff->block_size[2])) << 8;
block_size |= (0xff &
(unsigned int)(size_buff->block_size[3]));
} else /* read capacity command failed */
{
printk(KERN_WARNING "cciss: read capacity failed\n");
total_size = 0;
block_size = BLOCK_SIZE;
}
printk(KERN_INFO " blocks= %u block_size= %d\n",
total_size, block_size);
/* Execute the command to read the disk geometry */
memset(inq_buff, 0, sizeof(InquiryData_struct));
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff,
sizeof(InquiryData_struct), 1, logvol ,0xC1 );
if (return_code == IO_OK)
{
if(inq_buff->data_byte[8] == 0xFF)
{
printk(KERN_WARNING "cciss: reading geometry failed, "
"volume does not support reading geometry\n");
hba[ctlr]->drv[logvol].block_size = block_size;
hba[ctlr]->drv[logvol].nr_blocks = total_size;
hba[ctlr]->drv[logvol].heads = 255;
hba[ctlr]->drv[logvol].sectors = 32; // Sectors per track
hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32;
} else
{
hba[ctlr]->drv[logvol].block_size = block_size;
hba[ctlr]->drv[logvol].nr_blocks = total_size;
hba[ctlr]->drv[logvol].heads =
inq_buff->data_byte[6];
hba[ctlr]->drv[logvol].sectors =
inq_buff->data_byte[7];
hba[ctlr]->drv[logvol].cylinders =
(inq_buff->data_byte[4] & 0xff) << 8;
hba[ctlr]->drv[logvol].cylinders +=
inq_buff->data_byte[5];
}
}
else /* Get geometry failed */
{
printk(KERN_WARNING "cciss: reading geometry failed, "
"continuing with default geometry\n");
hba[ctlr]->drv[logvol].block_size = block_size;
hba[ctlr]->drv[logvol].nr_blocks = total_size;
hba[ctlr]->drv[logvol].heads = 255;
hba[ctlr]->drv[logvol].sectors = 32; // Sectors per track
hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32;
}
printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n",
hba[ctlr]->drv[logvol].heads,
hba[ctlr]->drv[logvol].sectors,
hba[ctlr]->drv[logvol].cylinders);
hba[ctlr]->drv[logvol].usage_count = 0; hba[ctlr]->drv[logvol].usage_count = 0;
++hba[ctlr]->num_luns; ++hba[ctlr]->num_luns;
/* setup partitions per disk */ /* setup partitions per disk */
disk = hba[ctlr]->gendisk[logvol]; disk = hba[ctlr]->gendisk[logvol];
set_capacity(disk, hba[ctlr]->drv[logvol].nr_blocks); set_capacity(disk, hba[ctlr]->drv[logvol].nr_blocks);
add_disk(disk); add_disk(disk);
freeret:
kfree(ld_buff); kfree(ld_buff);
kfree(size_buff); kfree(size_buff);
kfree(inq_buff); kfree(inq_buff);
return (logvol); return (logvol);
mem_msg:
printk(KERN_ERR "cciss: out of memory\n");
free_err:
logvol = -1;
goto freeret;
} }
/* /*
* Wait polling for a command to complete. * Wait polling for a command to complete.
* The memory mapped FIFO is polled for the completion. * The memory mapped FIFO is polled for the completion.
* Used only at init time, interrupts disabled. * Used only at init time, interrupts from the HBA are disabled.
*/ */
static unsigned long pollcomplete(int ctlr) static unsigned long pollcomplete(int ctlr)
{ {
unsigned long done; unsigned long done;
int i; int i;
/* Wait (up to 2 seconds) for a command to complete */ /* Wait (up to 20 seconds) for a command to complete */
for (i = 200000; i > 0; i--) { for (i = 20 * HZ; i > 0; i--) {
done = hba[ctlr]->access.command_completed(hba[ctlr]); done = hba[ctlr]->access.command_completed(hba[ctlr]);
if (done == FIFO_EMPTY) { if (done == FIFO_EMPTY) {
udelay(10); /* a short fixed delay */ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
} else } else
return (done); return (done);
} }
...@@ -2174,83 +2164,10 @@ static void cciss_getgeometry(int cntl_num) ...@@ -2174,83 +2164,10 @@ static void cciss_getgeometry(int cntl_num)
ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2],
ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID); ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);
#endif /* CCISS_DEBUG */ #endif /* CCISS_DEBUG */
cciss_read_capacity(cntl_num, i, size_buff, 0,
memset(size_buff, 0, sizeof(ReadCapdata_struct)); &total_size, &block_size);
return_code = sendcmd(CCISS_READ_CAPACITY, cntl_num, size_buff, cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size,
sizeof( ReadCapdata_struct), 1, i, 0, NULL ); inq_buff, &hba[cntl_num]->drv[i]);
if (return_code == IO_OK)
{
total_size = (0xff &
(unsigned int)(size_buff->total_size[0])) << 24;
total_size |= (0xff &
(unsigned int)(size_buff->total_size[1])) << 16;
total_size |= (0xff &
(unsigned int)(size_buff->total_size[2])) << 8;
total_size |= (0xff & (unsigned int)
(size_buff->total_size[3]));
total_size++; // command returns highest block address
block_size = (0xff &
(unsigned int)(size_buff->block_size[0])) << 24;
block_size |= (0xff &
(unsigned int)(size_buff->block_size[1])) << 16;
block_size |= (0xff &
(unsigned int)(size_buff->block_size[2])) << 8;
block_size |= (0xff &
(unsigned int)(size_buff->block_size[3]));
} else /* read capacity command failed */
{
printk(KERN_WARNING "cciss: read capacity failed\n");
total_size = 0;
block_size = BLOCK_SIZE;
}
printk(KERN_INFO " blocks= %d block_size= %d\n",
total_size, block_size);
/* Execute the command to read the disk geometry */
memset(inq_buff, 0, sizeof(InquiryData_struct));
return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
sizeof(InquiryData_struct), 1, i ,0xC1, NULL );
if (return_code == IO_OK)
{
if(inq_buff->data_byte[8] == 0xFF)
{
printk(KERN_WARNING "cciss: reading geometry failed, volume does not support reading geometry\n");
hba[cntl_num]->drv[i].block_size = block_size;
hba[cntl_num]->drv[i].nr_blocks = total_size;
hba[cntl_num]->drv[i].heads = 255;
hba[cntl_num]->drv[i].sectors = 32; // Sectors per track
hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32; } else
{
hba[cntl_num]->drv[i].block_size = block_size;
hba[cntl_num]->drv[i].nr_blocks = total_size;
hba[cntl_num]->drv[i].heads =
inq_buff->data_byte[6];
hba[cntl_num]->drv[i].sectors =
inq_buff->data_byte[7];
hba[cntl_num]->drv[i].cylinders =
(inq_buff->data_byte[4] & 0xff) << 8;
hba[cntl_num]->drv[i].cylinders +=
inq_buff->data_byte[5];
}
}
else /* Get geometry failed */
{
printk(KERN_WARNING "cciss: reading geometry failed, continuing with default geometry\n");
hba[cntl_num]->drv[i].block_size = block_size;
hba[cntl_num]->drv[i].nr_blocks = total_size;
hba[cntl_num]->drv[i].heads = 255;
hba[cntl_num]->drv[i].sectors = 32; // Sectors per track
hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32;
}
printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n",
hba[cntl_num]->drv[i].heads,
hba[cntl_num]->drv[i].sectors,
hba[cntl_num]->drv[i].cylinders);
} }
kfree(ld_buff); kfree(ld_buff);
kfree(size_buff); kfree(size_buff);
...@@ -2408,7 +2325,7 @@ static int __init cciss_init_one(struct pci_dev *pdev, ...@@ -2408,7 +2325,7 @@ static int __init cciss_init_one(struct pci_dev *pdev,
cciss_getgeometry(i); cciss_getgeometry(i);
cciss_find_non_disk_devices(i); /* find our tape drives, if any */ cciss_scsi_setup(i);
/* Turn the interrupts on so we can service requests */ /* Turn the interrupts on so we can service requests */
hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
...@@ -2446,9 +2363,6 @@ static int __init cciss_init_one(struct pci_dev *pdev, ...@@ -2446,9 +2363,6 @@ static int __init cciss_init_one(struct pci_dev *pdev,
set_capacity(disk, drv->nr_blocks); set_capacity(disk, drv->nr_blocks);
add_disk(disk); add_disk(disk);
} }
cciss_register_scsi(i, 1); /* hook ourself into SCSI subsystem */
return(1); return(1);
} }
......
...@@ -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