Commit 8e43e12d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block

* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
  xen-blkfront.c: make blkif_ioctl() static
  bio: make use of bvec_nr_vecs
  cciss: fix bug if scsi tape support is disabled
  cciss: add support for multi lun tape devices
  cciss: change the way we notify scsi midlayer of tape drives
  cciss: fix negative logical drive count in procfs
  cciss: remove redundant code
  cciss: make rebuild_lun_table behave better
  cciss: return -EFAULT if copy_from_user() fails
parents 01b09b6c 62aa0054
...@@ -112,27 +112,18 @@ Hot plug support for SCSI tape drives ...@@ -112,27 +112,18 @@ Hot plug support for SCSI tape drives
Hot plugging of SCSI tape drives is supported, with some caveats. Hot plugging of SCSI tape drives is supported, with some caveats.
The cciss driver must be informed that changes to the SCSI bus The cciss driver must be informed that changes to the SCSI bus
have been made, in addition to and prior to informing the SCSI have been made. This may be done via the /proc filesystem.
mid layer. This may be done via the /proc filesystem. For example: For example:
echo "rescan" > /proc/scsi/cciss0/1 echo "rescan" > /proc/scsi/cciss0/1
This causes the adapter to query the adapter about changes to the This causes the driver to query the adapter about changes to the
physical SCSI buses and/or fibre channel arbitrated loop and the physical SCSI buses and/or fibre channel arbitrated loop and the
driver to make note of any new or removed sequential access devices driver to make note of any new or removed sequential access devices
or medium changers. The driver will output messages indicating what or medium changers. The driver will output messages indicating what
devices have been added or removed and the controller, bus, target and devices have been added or removed and the controller, bus, target and
lun used to address the device. Once this is done, the SCSI mid layer lun used to address the device. It then notifies the SCSI mid layer
can be informed of changes to the virtual SCSI bus which the driver of these changes.
presents to it in the usual way. For example:
echo scsi add-single-device 3 2 1 0 > /proc/scsi/scsi
to add a device on controller 3, bus 2, target 1, lun 0. Note that
the driver makes an effort to preserve the devices positions
in the virtual SCSI bus, so if you are only moving tape drives
around on the same adapter and not adding or removing tape drives
from the adapter, informing the SCSI mid layer may not be necessary.
Note that the naming convention of the /proc filesystem entries Note that the naming convention of the /proc filesystem entries
contains a number in addition to the driver name. (E.g. "cciss0" contains a number in addition to the driver name. (E.g. "cciss0"
......
...@@ -159,7 +159,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, ...@@ -159,7 +159,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int cciss_revalidate(struct gendisk *disk); static int cciss_revalidate(struct gendisk *disk);
static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk); static int rebuild_lun_table(ctlr_info_t *h, int first_time);
static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
int clear_all); int clear_all);
...@@ -171,7 +171,6 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, ...@@ -171,7 +171,6 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
int withirq, sector_t total_size, int withirq, sector_t total_size,
unsigned int block_size, InquiryData_struct *inq_buff, unsigned int block_size, InquiryData_struct *inq_buff,
drive_info_struct *drv); drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
__u32); __u32);
static void start_io(ctlr_info_t *h); static void start_io(ctlr_info_t *h);
...@@ -929,8 +928,10 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, ...@@ -929,8 +928,10 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
return 0; return 0;
} }
case CCISS_DEREGDISK:
case CCISS_REGNEWD:
case CCISS_REVALIDVOLS: case CCISS_REVALIDVOLS:
return rebuild_lun_table(host, NULL); return rebuild_lun_table(host, 0);
case CCISS_GETLUNINFO:{ case CCISS_GETLUNINFO:{
LogvolInfo_struct luninfo; LogvolInfo_struct luninfo;
...@@ -943,12 +944,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, ...@@ -943,12 +944,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case CCISS_DEREGDISK:
return rebuild_lun_table(host, disk);
case CCISS_REGNEWD:
return rebuild_lun_table(host, NULL);
case CCISS_PASSTHRU: case CCISS_PASSTHRU:
{ {
IOCTL_Command_struct iocommand; IOCTL_Command_struct iocommand;
...@@ -1134,7 +1129,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, ...@@ -1134,7 +1129,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
if (ioc->Request.Type.Direction == XFER_WRITE) { if (ioc->Request.Type.Direction == XFER_WRITE) {
if (copy_from_user if (copy_from_user
(buff[sg_used], data_ptr, sz)) { (buff[sg_used], data_ptr, sz)) {
status = -ENOMEM; status = -EFAULT;
goto cleanup1; goto cleanup1;
} }
} else { } else {
...@@ -1330,15 +1325,84 @@ static void cciss_softirq_done(struct request *rq) ...@@ -1330,15 +1325,84 @@ static void cciss_softirq_done(struct request *rq)
spin_unlock_irqrestore(&h->lock, flags); spin_unlock_irqrestore(&h->lock, flags);
} }
/* This function gets the serial number of a logical drive via
* inquiry page 0x83. Serial no. is 16 bytes. If the serial
* number cannot be had, for whatever reason, 16 bytes of 0xff
* are returned instead.
*/
static void cciss_get_serial_no(int ctlr, int logvol, int withirq,
unsigned char *serial_no, int buflen)
{
#define PAGE_83_INQ_BYTES 64
int rc;
unsigned char *buf;
if (buflen > 16)
buflen = 16;
memset(serial_no, 0xff, buflen);
buf = kzalloc(PAGE_83_INQ_BYTES, GFP_KERNEL);
if (!buf)
return;
memset(serial_no, 0, buflen);
if (withirq)
rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf,
PAGE_83_INQ_BYTES, 1, logvol, 0x83, TYPE_CMD);
else
rc = sendcmd(CISS_INQUIRY, ctlr, buf,
PAGE_83_INQ_BYTES, 1, logvol, 0x83, NULL, TYPE_CMD);
if (rc == IO_OK)
memcpy(serial_no, &buf[8], buflen);
kfree(buf);
return;
}
static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
int drv_index)
{
disk->queue = blk_init_queue(do_cciss_request, &h->lock);
sprintf(disk->disk_name, "cciss/c%dd%d", h->ctlr, drv_index);
disk->major = h->major;
disk->first_minor = drv_index << NWD_SHIFT;
disk->fops = &cciss_fops;
disk->private_data = &h->drv[drv_index];
/* Set up queue information */
blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
/* This is a hardware imposed limit. */
blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
/* This is a limit in the driver and could be eliminated. */
blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
blk_queue_max_sectors(disk->queue, h->cciss_max_sectors);
blk_queue_softirq_done(disk->queue, cciss_softirq_done);
disk->queue->queuedata = h;
blk_queue_hardsect_size(disk->queue,
h->drv[drv_index].block_size);
/* Make sure all queue data is written out before */
/* setting h->drv[drv_index].queue, as setting this */
/* allows the interrupt handler to start the queue */
wmb();
h->drv[drv_index].queue = disk->queue;
add_disk(disk);
}
/* This function will check the usage_count of the drive to be updated/added. /* This function will check the usage_count of the drive to be updated/added.
* If the usage_count is zero then the drive information will be updated and * If the usage_count is zero and it is a heretofore unknown drive, or,
* the disk will be re-registered with the kernel. If not then it will be * the drive's capacity, geometry, or serial number has changed,
* left alone for the next reboot. The exception to this is disk 0 which * then the drive information will be updated and the disk will be
* will always be left registered with the kernel since it is also the * re-registered with the kernel. If these conditions don't hold,
* controller node. Any changes to disk 0 will show up on the next * then it will be left alone for the next reboot. The exception to this
* reboot. * is disk 0 which will always be left registered with the kernel since it
* is also the controller node. Any changes to disk 0 will show up on
* the next reboot.
*/ */
static void cciss_update_drive_info(int ctlr, int drv_index) static void cciss_update_drive_info(int ctlr, int drv_index, int first_time)
{ {
ctlr_info_t *h = hba[ctlr]; ctlr_info_t *h = hba[ctlr];
struct gendisk *disk; struct gendisk *disk;
...@@ -1347,16 +1411,81 @@ static void cciss_update_drive_info(int ctlr, int drv_index) ...@@ -1347,16 +1411,81 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
sector_t total_size; sector_t total_size;
unsigned long flags = 0; unsigned long flags = 0;
int ret = 0; int ret = 0;
drive_info_struct *drvinfo;
int was_only_controller_node;
/* Get information about the disk and modify the driver structure */
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
drvinfo = kmalloc(sizeof(*drvinfo), GFP_KERNEL);
if (inq_buff == NULL || drvinfo == NULL)
goto mem_msg;
/* See if we're trying to update the "controller node"
* this will happen the when the first logical drive gets
* created by ACU.
*/
was_only_controller_node = (drv_index == 0 &&
h->drv[0].raid_level == -1);
/* if the disk already exists then deregister it before proceeding */ /* testing to see if 16-byte CDBs are already being used */
if (h->drv[drv_index].raid_level != -1) { if (h->cciss_read == CCISS_READ_16) {
cciss_read_capacity_16(h->ctlr, drv_index, 1,
&total_size, &block_size);
} else {
cciss_read_capacity(ctlr, drv_index, 1,
&total_size, &block_size);
/* if read_capacity returns all F's this volume is >2TB */
/* in size so we switch to 16-byte CDB's for all */
/* read/write ops */
if (total_size == 0xFFFFFFFFULL) {
cciss_read_capacity_16(ctlr, drv_index, 1,
&total_size, &block_size);
h->cciss_read = CCISS_READ_16;
h->cciss_write = CCISS_WRITE_16;
} else {
h->cciss_read = CCISS_READ_10;
h->cciss_write = CCISS_WRITE_10;
}
}
cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
inq_buff, drvinfo);
drvinfo->block_size = block_size;
drvinfo->nr_blocks = total_size + 1;
cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no,
sizeof(drvinfo->serial_no));
/* Is it the same disk we already know, and nothing's changed? */
if (h->drv[drv_index].raid_level != -1 &&
((memcmp(drvinfo->serial_no,
h->drv[drv_index].serial_no, 16) == 0) &&
drvinfo->block_size == h->drv[drv_index].block_size &&
drvinfo->nr_blocks == h->drv[drv_index].nr_blocks &&
drvinfo->heads == h->drv[drv_index].heads &&
drvinfo->sectors == h->drv[drv_index].sectors &&
drvinfo->cylinders == h->drv[drv_index].cylinders))
/* The disk is unchanged, nothing to update */
goto freeret;
/* If we get here it's not the same disk, or something's changed,
* so we need to * deregister it, and re-register it, if it's not
* in use.
* If the disk already exists then deregister it before proceeding
* (unless it's the first disk (for the controller node).
*/
if (h->drv[drv_index].raid_level != -1 && drv_index != 0) {
printk(KERN_WARNING "disk %d has changed.\n", drv_index);
spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
h->drv[drv_index].busy_configuring = 1; h->drv[drv_index].busy_configuring = 1;
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
/* deregister_disk sets h->drv[drv_index].queue = NULL */ /* deregister_disk sets h->drv[drv_index].queue = NULL
/* which keeps the interrupt handler from starting */ * which keeps the interrupt handler from starting
/* the queue. */ * the queue.
*/
ret = deregister_disk(h->gendisk[drv_index], ret = deregister_disk(h->gendisk[drv_index],
&h->drv[drv_index], 0); &h->drv[drv_index], 0);
h->drv[drv_index].busy_configuring = 0; h->drv[drv_index].busy_configuring = 0;
...@@ -1364,81 +1493,37 @@ static void cciss_update_drive_info(int ctlr, int drv_index) ...@@ -1364,81 +1493,37 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
/* If the disk is in use return */ /* If the disk is in use return */
if (ret) if (ret)
return; goto freeret;
/* Get information about the disk and modify the driver structure */ /* Save the new information from cciss_geometry_inquiry
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); * and serial number inquiry.
if (inq_buff == NULL) */
goto mem_msg; h->drv[drv_index].block_size = drvinfo->block_size;
h->drv[drv_index].nr_blocks = drvinfo->nr_blocks;
/* testing to see if 16-byte CDBs are already being used */ h->drv[drv_index].heads = drvinfo->heads;
if (h->cciss_read == CCISS_READ_16) { h->drv[drv_index].sectors = drvinfo->sectors;
cciss_read_capacity_16(h->ctlr, drv_index, 1, h->drv[drv_index].cylinders = drvinfo->cylinders;
&total_size, &block_size); h->drv[drv_index].raid_level = drvinfo->raid_level;
goto geo_inq; memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16);
}
cciss_read_capacity(ctlr, drv_index, 1,
&total_size, &block_size);
/* if read_capacity returns all F's this volume is >2TB in size */
/* so we switch to 16-byte CDB's for all read/write ops */
if (total_size == 0xFFFFFFFFULL) {
cciss_read_capacity_16(ctlr, drv_index, 1,
&total_size, &block_size);
h->cciss_read = CCISS_READ_16;
h->cciss_write = CCISS_WRITE_16;
} else {
h->cciss_read = CCISS_READ_10;
h->cciss_write = CCISS_WRITE_10;
}
geo_inq:
cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
inq_buff, &h->drv[drv_index]);
++h->num_luns; ++h->num_luns;
disk = h->gendisk[drv_index]; disk = h->gendisk[drv_index];
set_capacity(disk, h->drv[drv_index].nr_blocks); set_capacity(disk, h->drv[drv_index].nr_blocks);
/* if it's the controller it's already added */ /* If it's not disk 0 (drv_index != 0)
if (drv_index) { * or if it was disk 0, but there was previously
disk->queue = blk_init_queue(do_cciss_request, &h->lock); * no actual corresponding configured logical drive
sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index); * (raid_leve == -1) then we want to update the
disk->major = h->major; * logical drive's information.
disk->first_minor = drv_index << NWD_SHIFT; */
disk->fops = &cciss_fops; if (drv_index || first_time)
disk->private_data = &h->drv[drv_index]; cciss_add_disk(h, disk, drv_index);
/* Set up queue information */
blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask);
/* This is a hardware imposed limit. */
blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
/* This is a limit in the driver and could be eliminated. */
blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
blk_queue_max_sectors(disk->queue, h->cciss_max_sectors);
blk_queue_softirq_done(disk->queue, cciss_softirq_done);
disk->queue->queuedata = hba[ctlr];
blk_queue_hardsect_size(disk->queue,
hba[ctlr]->drv[drv_index].block_size);
/* Make sure all queue data is written out before */
/* setting h->drv[drv_index].queue, as setting this */
/* allows the interrupt handler to start the queue */
wmb();
h->drv[drv_index].queue = disk->queue;
add_disk(disk);
}
freeret: freeret:
kfree(inq_buff); kfree(inq_buff);
kfree(drvinfo);
return; return;
mem_msg: mem_msg:
printk(KERN_ERR "cciss: out of memory\n"); printk(KERN_ERR "cciss: out of memory\n");
goto freeret; goto freeret;
} }
...@@ -1448,21 +1533,91 @@ static void cciss_update_drive_info(int ctlr, int drv_index) ...@@ -1448,21 +1533,91 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
* where new drives will be added. If the index to be returned is greater * where new drives will be added. If the index to be returned is greater
* than the highest_lun index for the controller then highest_lun is set * than the highest_lun index for the controller then highest_lun is set
* to this new index. If there are no available indexes then -1 is returned. * to this new index. If there are no available indexes then -1 is returned.
* "controller_node" is used to know if this is a real logical drive, or just
* the controller node, which determines if this counts towards highest_lun.
*/ */
static int cciss_find_free_drive_index(int ctlr) static int cciss_find_free_drive_index(int ctlr, int controller_node)
{ {
int i; int i;
for (i = 0; i < CISS_MAX_LUN; i++) { for (i = 0; i < CISS_MAX_LUN; i++) {
if (hba[ctlr]->drv[i].raid_level == -1) { if (hba[ctlr]->drv[i].raid_level == -1) {
if (i > hba[ctlr]->highest_lun) if (i > hba[ctlr]->highest_lun)
hba[ctlr]->highest_lun = i; if (!controller_node)
hba[ctlr]->highest_lun = i;
return i; return i;
} }
} }
return -1; return -1;
} }
/* cciss_add_gendisk finds a free hba[]->drv structure
* and allocates a gendisk if needed, and sets the lunid
* in the drvinfo structure. It returns the index into
* the ->drv[] array, or -1 if none are free.
* is_controller_node indicates whether highest_lun should
* count this disk, or if it's only being added to provide
* a means to talk to the controller in case no logical
* drives have yet been configured.
*/
static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node)
{
int drv_index;
drv_index = cciss_find_free_drive_index(h->ctlr, controller_node);
if (drv_index == -1)
return -1;
/*Check if the gendisk needs to be allocated */
if (!h->gendisk[drv_index]) {
h->gendisk[drv_index] =
alloc_disk(1 << NWD_SHIFT);
if (!h->gendisk[drv_index]) {
printk(KERN_ERR "cciss%d: could not "
"allocate a new disk %d\n",
h->ctlr, drv_index);
return -1;
}
}
h->drv[drv_index].LunID = lunid;
/* Don't need to mark this busy because nobody */
/* else knows about this disk yet to contend */
/* for access to it. */
h->drv[drv_index].busy_configuring = 0;
wmb();
return drv_index;
}
/* This is for the special case of a controller which
* has no logical drives. In this case, we still need
* to register a disk so the controller can be accessed
* by the Array Config Utility.
*/
static void cciss_add_controller_node(ctlr_info_t *h)
{
struct gendisk *disk;
int drv_index;
if (h->gendisk[0] != NULL) /* already did this? Then bail. */
return;
drv_index = cciss_add_gendisk(h, 0, 1);
if (drv_index == -1) {
printk(KERN_WARNING "cciss%d: could not "
"add disk 0.\n", h->ctlr);
return;
}
h->drv[drv_index].block_size = 512;
h->drv[drv_index].nr_blocks = 0;
h->drv[drv_index].heads = 0;
h->drv[drv_index].sectors = 0;
h->drv[drv_index].cylinders = 0;
h->drv[drv_index].raid_level = -1;
memset(h->drv[drv_index].serial_no, 0, 16);
disk = h->gendisk[drv_index];
cciss_add_disk(h, disk, drv_index);
}
/* This function will add and remove logical drives from the Logical /* This function will add and remove logical drives from the Logical
* drive array of the controller and maintain persistency of ordering * drive array of the controller and maintain persistency of ordering
* so that mount points are preserved until the next reboot. This allows * so that mount points are preserved until the next reboot. This allows
...@@ -1470,15 +1625,12 @@ static int cciss_find_free_drive_index(int ctlr) ...@@ -1470,15 +1625,12 @@ static int cciss_find_free_drive_index(int ctlr)
* without a re-ordering of those drives. * without a re-ordering of those drives.
* INPUT * INPUT
* h = The controller to perform the operations on * h = The controller to perform the operations on
* del_disk = The disk to remove if specified. If the value given
* is NULL then no disk is removed.
*/ */
static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) static int rebuild_lun_table(ctlr_info_t *h, int first_time)
{ {
int ctlr = h->ctlr; int ctlr = h->ctlr;
int num_luns; int num_luns;
ReportLunData_struct *ld_buff = NULL; ReportLunData_struct *ld_buff = NULL;
drive_info_struct *drv = NULL;
int return_code; int return_code;
int listlength = 0; int listlength = 0;
int i; int i;
...@@ -1487,6 +1639,9 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) ...@@ -1487,6 +1639,9 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
__u32 lunid = 0; __u32 lunid = 0;
unsigned long flags; unsigned long flags;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
/* Set busy_configuring flag for this operation */ /* Set busy_configuring flag for this operation */
spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
if (h->busy_configuring) { if (h->busy_configuring) {
...@@ -1494,100 +1649,100 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) ...@@ -1494,100 +1649,100 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
return -EBUSY; return -EBUSY;
} }
h->busy_configuring = 1; h->busy_configuring = 1;
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
/* if del_disk is NULL then we are being called to add a new disk ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
* and update the logical drive table. If it is not NULL then if (ld_buff == NULL)
* we will check if the disk is in use or not. goto mem_msg;
*/
if (del_disk != NULL) {
drv = get_drv(del_disk);
drv->busy_configuring = 1;
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return_code = deregister_disk(del_disk, drv, 1);
drv->busy_configuring = 0;
h->busy_configuring = 0;
return return_code;
} else {
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
if (ld_buff == NULL) sizeof(ReportLunData_struct), 0,
goto mem_msg; 0, 0, TYPE_CMD);
return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
sizeof(ReportLunData_struct), 0,
0, 0, TYPE_CMD);
if (return_code == IO_OK) {
listlength =
be32_to_cpu(*(__be32 *) ld_buff->LUNListLength);
} else { /* reading number of logical volumes failed */
printk(KERN_WARNING "cciss: report logical volume"
" command failed\n");
listlength = 0;
goto freeret;
}
num_luns = listlength / 8; /* 8 bytes per entry */ if (return_code == IO_OK)
if (num_luns > CISS_MAX_LUN) { listlength = be32_to_cpu(*(__be32 *) ld_buff->LUNListLength);
num_luns = CISS_MAX_LUN; else { /* reading number of logical volumes failed */
printk(KERN_WARNING "cciss: more luns configured" printk(KERN_WARNING "cciss: report logical volume"
" on controller than can be handled by" " command failed\n");
" this driver.\n"); listlength = 0;
goto freeret;
}
num_luns = listlength / 8; /* 8 bytes per entry */
if (num_luns > CISS_MAX_LUN) {
num_luns = CISS_MAX_LUN;
printk(KERN_WARNING "cciss: more luns configured"
" on controller than can be handled by"
" this driver.\n");
}
if (num_luns == 0)
cciss_add_controller_node(h);
/* Compare controller drive array to driver's drive array
* to see if any drives are missing on the controller due
* to action of Array Config Utility (user deletes drive)
* and deregister logical drives which have disappeared.
*/
for (i = 0; i <= h->highest_lun; i++) {
int j;
drv_found = 0;
for (j = 0; j < num_luns; j++) {
memcpy(&lunid, &ld_buff->LUN[j][0], 4);
lunid = le32_to_cpu(lunid);
if (h->drv[i].LunID == lunid) {
drv_found = 1;
break;
}
} }
if (!drv_found) {
/* Deregister it from the OS, it's gone. */
spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
h->drv[i].busy_configuring = 1;
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return_code = deregister_disk(h->gendisk[i],
&h->drv[i], 1);
h->drv[i].busy_configuring = 0;
}
}
/* Compare controller drive array to driver's drive array.
* Check for updates in the drive information and any new drives
* on the controller due to ACU adding logical drives, or changing
* a logical drive's size, etc. Reregister any new/changed drives
*/
for (i = 0; i < num_luns; i++) {
int j;
/* Compare controller drive array to drivers drive array. drv_found = 0;
* Check for updates in the drive information and any new drives
* on the controller. memcpy(&lunid, &ld_buff->LUN[i][0], 4);
lunid = le32_to_cpu(lunid);
/* Find if the LUN is already in the drive array
* of the driver. If so then update its info
* if not in use. If it does not exist then find
* the first free index and add it.
*/ */
for (i = 0; i < num_luns; i++) { for (j = 0; j <= h->highest_lun; j++) {
int j; if (h->drv[j].raid_level != -1 &&
h->drv[j].LunID == lunid) {
drv_found = 0; drv_index = j;
drv_found = 1;
lunid = (0xff & break;
(unsigned int)(ld_buff->LUN[i][3])) << 24;
lunid |= (0xff &
(unsigned int)(ld_buff->LUN[i][2])) << 16;
lunid |= (0xff &
(unsigned int)(ld_buff->LUN[i][1])) << 8;
lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
/* Find if the LUN is already in the drive array
* of the controller. If so then update its info
* if not is use. If it does not exist then find
* the first free index and add it.
*/
for (j = 0; j <= h->highest_lun; j++) {
if (h->drv[j].LunID == lunid) {
drv_index = j;
drv_found = 1;
}
} }
}
/* check if the drive was found already in the array */ /* check if the drive was found already in the array */
if (!drv_found) { if (!drv_found) {
drv_index = cciss_find_free_drive_index(ctlr); drv_index = cciss_add_gendisk(h, lunid, 0);
if (drv_index == -1) if (drv_index == -1)
goto freeret; goto freeret;
}
/*Check if the gendisk needs to be allocated */ cciss_update_drive_info(ctlr, drv_index, first_time);
if (!h->gendisk[drv_index]){ } /* end for */
h->gendisk[drv_index] = alloc_disk(1 << NWD_SHIFT);
if (!h->gendisk[drv_index]){
printk(KERN_ERR "cciss: could not allocate new disk %d\n", drv_index);
goto mem_msg;
}
}
}
h->drv[drv_index].LunID = lunid;
cciss_update_drive_info(ctlr, drv_index);
} /* end for */
} /* end else */
freeret: freeret:
kfree(ld_buff); kfree(ld_buff);
h->busy_configuring = 0; h->busy_configuring = 0;
/* We return -1 here to tell the ACU that we have registered/updated /* We return -1 here to tell the ACU that we have registered/updated
...@@ -1595,8 +1750,9 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) ...@@ -1595,8 +1750,9 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
* additional times. * additional times.
*/ */
return -1; return -1;
mem_msg: mem_msg:
printk(KERN_ERR "cciss: out of memory\n"); printk(KERN_ERR "cciss: out of memory\n");
h->busy_configuring = 0;
goto freeret; goto freeret;
} }
...@@ -1652,15 +1808,15 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, ...@@ -1652,15 +1808,15 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
* other than disk 0 we will call put_disk. We do not * other than disk 0 we will call put_disk. We do not
* do this for disk 0 as we need it to be able to * do this for disk 0 as we need it to be able to
* configure the controller. * configure the controller.
*/ */
if (clear_all){ if (clear_all){
/* This isn't pretty, but we need to find the /* This isn't pretty, but we need to find the
* disk in our array and NULL our the pointer. * disk in our array and NULL our the pointer.
* This is so that we will call alloc_disk if * This is so that we will call alloc_disk if
* this index is used again later. * this index is used again later.
*/ */
for (i=0; i < CISS_MAX_LUN; i++){ for (i=0; i < CISS_MAX_LUN; i++){
if(h->gendisk[i] == disk){ if (h->gendisk[i] == disk) {
h->gendisk[i] = NULL; h->gendisk[i] = NULL;
break; break;
} }
...@@ -1688,7 +1844,7 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, ...@@ -1688,7 +1844,7 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
if (drv == h->drv + h->highest_lun) { if (drv == h->drv + h->highest_lun) {
/* if so, find the new hightest lun */ /* if so, find the new hightest lun */
int i, newhighest = -1; int i, newhighest = -1;
for (i = 0; i < h->highest_lun; i++) { for (i = 0; i <= h->highest_lun; i++) {
/* if the disk has size > 0, it is available */ /* if the disk has size > 0, it is available */
if (h->drv[i].heads) if (h->drv[i].heads)
newhighest = i; newhighest = i;
...@@ -3199,136 +3355,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) ...@@ -3199,136 +3355,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
return err; return err;
} }
/* /* Function to find the first free pointer into our hba[] array
* Gets information about the local volumes attached to the controller. * Returns -1 if no free entries are left.
*/ */
static void cciss_getgeometry(int cntl_num)
{
ReportLunData_struct *ld_buff;
InquiryData_struct *inq_buff;
int return_code;
int i;
int listlength = 0;
__u32 lunid = 0;
unsigned block_size;
sector_t total_size;
ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
if (ld_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
return;
}
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 firmware version */
return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
sizeof(InquiryData_struct), 0, 0, 0, NULL,
TYPE_CMD);
if (return_code == IO_OK) {
hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32];
hba[cntl_num]->firm_ver[1] = inq_buff->data_byte[33];
hba[cntl_num]->firm_ver[2] = inq_buff->data_byte[34];
hba[cntl_num]->firm_ver[3] = inq_buff->data_byte[35];
} else { /* send command failed */
printk(KERN_WARNING "cciss: unable to determine firmware"
" version of controller\n");
}
/* Get the number of logical volumes */
return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff,
sizeof(ReportLunData_struct), 0, 0, 0, NULL,
TYPE_CMD);
if (return_code == IO_OK) {
#ifdef CCISS_DEBUG
printk("LUN Data\n--------------------------\n");
#endif /* CCISS_DEBUG */
listlength |=
(0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
listlength |=
(0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
listlength |=
(0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
} else { /* reading number of logical volumes failed */
printk(KERN_WARNING "cciss: report logical volume"
" command failed\n");
listlength = 0;
}
hba[cntl_num]->num_luns = listlength / 8; // 8 bytes pre entry
if (hba[cntl_num]->num_luns > CISS_MAX_LUN) {
printk(KERN_ERR
"ciss: only %d number of logical volumes supported\n",
CISS_MAX_LUN);
hba[cntl_num]->num_luns = CISS_MAX_LUN;
}
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "Length = %x %x %x %x = %d\n",
ld_buff->LUNListLength[0], ld_buff->LUNListLength[1],
ld_buff->LUNListLength[2], ld_buff->LUNListLength[3],
hba[cntl_num]->num_luns);
#endif /* CCISS_DEBUG */
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1;
for (i = 0; i < CISS_MAX_LUN; i++) {
if (i < hba[cntl_num]->num_luns) {
lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
<< 24;
lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
<< 16;
lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
<< 8;
lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
hba[cntl_num]->drv[i].LunID = lunid;
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i,
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);
#endif /* CCISS_DEBUG */
/* testing to see if 16-byte CDBs are already being used */
if(hba[cntl_num]->cciss_read == CCISS_READ_16) {
cciss_read_capacity_16(cntl_num, i, 0,
&total_size, &block_size);
goto geo_inq;
}
cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
/* If read_capacity returns all F's the logical is >2TB */
/* so we switch to 16-byte CDBs for all read/write ops */
if(total_size == 0xFFFFFFFFULL) {
cciss_read_capacity_16(cntl_num, i, 0,
&total_size, &block_size);
hba[cntl_num]->cciss_read = CCISS_READ_16;
hba[cntl_num]->cciss_write = CCISS_WRITE_16;
} else {
hba[cntl_num]->cciss_read = CCISS_READ_10;
hba[cntl_num]->cciss_write = CCISS_WRITE_10;
}
geo_inq:
cciss_geometry_inquiry(cntl_num, i, 0, total_size,
block_size, inq_buff,
&hba[cntl_num]->drv[i]);
} else {
/* initialize raid_level to indicate a free space */
hba[cntl_num]->drv[i].raid_level = -1;
}
}
kfree(ld_buff);
kfree(inq_buff);
}
/* Function to find the first free pointer into our hba[] array */
/* Returns -1 if no free entries are left. */
static int alloc_cciss_hba(void) static int alloc_cciss_hba(void)
{ {
int i; int i;
...@@ -3340,11 +3369,6 @@ static int alloc_cciss_hba(void) ...@@ -3340,11 +3369,6 @@ static int alloc_cciss_hba(void)
p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
if (!p) if (!p)
goto Enomem; goto Enomem;
p->gendisk[0] = alloc_disk(1 << NWD_SHIFT);
if (!p->gendisk[0]) {
kfree(p);
goto Enomem;
}
hba[i] = p; hba[i] = p;
return i; return i;
} }
...@@ -3472,11 +3496,13 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ...@@ -3472,11 +3496,13 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
((hba[i]->nr_cmds + BITS_PER_LONG - ((hba[i]->nr_cmds + BITS_PER_LONG -
1) / BITS_PER_LONG) * sizeof(unsigned long)); 1) / BITS_PER_LONG) * sizeof(unsigned long));
#ifdef CCISS_DEBUG hba[i]->num_luns = 0;
printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n", i); hba[i]->highest_lun = -1;
#endif /* CCISS_DEBUG */ for (j = 0; j < CISS_MAX_LUN; j++) {
hba[i]->drv[j].raid_level = -1;
cciss_getgeometry(i); hba[i]->drv[j].queue = NULL;
hba[i]->gendisk[j] = NULL;
}
cciss_scsi_setup(i); cciss_scsi_setup(i);
...@@ -3489,76 +3515,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ...@@ -3489,76 +3515,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->busy_initializing = 0; hba[i]->busy_initializing = 0;
do { rebuild_lun_table(hba[i], 1);
drive_info_struct *drv = &(hba[i]->drv[j]);
struct gendisk *disk = hba[i]->gendisk[j];
struct request_queue *q;
/* Check if the disk was allocated already */
if (!disk){
hba[i]->gendisk[j] = alloc_disk(1 << NWD_SHIFT);
disk = hba[i]->gendisk[j];
}
/* Check that the disk was able to be allocated */
if (!disk) {
printk(KERN_ERR "cciss: unable to allocate memory for disk %d\n", j);
goto clean4;
}
q = blk_init_queue(do_cciss_request, &hba[i]->lock);
if (!q) {
printk(KERN_ERR
"cciss: unable to allocate queue for disk %d\n",
j);
goto clean4;
}
drv->queue = q;
blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
/* This is a hardware imposed limit. */
blk_queue_max_hw_segments(q, MAXSGENTRIES);
/* This is a limit in the driver and could be eliminated. */
blk_queue_max_phys_segments(q, MAXSGENTRIES);
blk_queue_max_sectors(q, hba[i]->cciss_max_sectors);
blk_queue_softirq_done(q, cciss_softirq_done);
q->queuedata = hba[i];
sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
disk->major = hba[i]->major;
disk->first_minor = j << NWD_SHIFT;
disk->fops = &cciss_fops;
disk->queue = q;
disk->private_data = drv;
disk->driverfs_dev = &pdev->dev;
/* we must register the controller even if no disks exist */
/* this is for the online array utilities */
if (!drv->heads && j)
continue;
blk_queue_hardsect_size(q, drv->block_size);
set_capacity(disk, drv->nr_blocks);
j++;
} while (j <= hba[i]->highest_lun);
/* Make sure all queue data is written out before */
/* interrupt handler, triggered by add_disk, */
/* is allowed to start them. */
wmb();
for (j = 0; j <= hba[i]->highest_lun; j++)
add_disk(hba[i]->gendisk[j]);
/* we must register the controller even if no disks exist */
if (hba[i]->highest_lun == -1)
add_disk(hba[i]->gendisk[0]);
return 1; return 1;
clean4: clean4:
#ifdef CONFIG_CISS_SCSI_TAPE #ifdef CONFIG_CISS_SCSI_TAPE
kfree(hba[i]->scsi_rejects.complete); kfree(hba[i]->scsi_rejects.complete);
#endif #endif
...@@ -3573,9 +3533,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ...@@ -3573,9 +3533,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->errinfo_pool, hba[i]->errinfo_pool,
hba[i]->errinfo_pool_dhandle); hba[i]->errinfo_pool_dhandle);
free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]); free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]);
clean2: clean2:
unregister_blkdev(hba[i]->major, hba[i]->devname); unregister_blkdev(hba[i]->major, hba[i]->devname);
clean1: clean1:
hba[i]->busy_initializing = 0; hba[i]->busy_initializing = 0;
/* cleanup any queues that may have been initialized */ /* cleanup any queues that may have been initialized */
for (j=0; j <= hba[i]->highest_lun; j++){ for (j=0; j <= hba[i]->highest_lun; j++){
...@@ -3654,7 +3614,9 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) ...@@ -3654,7 +3614,9 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
} }
} }
#ifdef CONFIG_CISS_SCSI_TAPE
cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ cciss_unregister_scsi(i); /* unhook from SCSI subsystem */
#endif
cciss_shutdown(pdev); cciss_shutdown(pdev);
......
...@@ -39,6 +39,8 @@ typedef struct _drive_info_struct ...@@ -39,6 +39,8 @@ typedef struct _drive_info_struct
*to prevent it from being opened or it's queue *to prevent it from being opened or it's queue
*from being started. *from being started.
*/ */
__u8 serial_no[16]; /* from inquiry page 0x83, */
/* not necc. null terminated. */
} drive_info_struct; } drive_info_struct;
#ifdef CONFIG_CISS_SCSI_TAPE #ifdef CONFIG_CISS_SCSI_TAPE
......
...@@ -358,23 +358,68 @@ find_bus_target_lun(int ctlr, int *bus, int *target, int *lun) ...@@ -358,23 +358,68 @@ find_bus_target_lun(int ctlr, int *bus, int *target, int *lun)
} }
return (!found); return (!found);
} }
struct scsi2map {
char scsi3addr[8];
int bus, target, lun;
};
static int static int
cciss_scsi_add_entry(int ctlr, int hostno, cciss_scsi_add_entry(int ctlr, int hostno,
unsigned char *scsi3addr, int devtype) unsigned char *scsi3addr, int devtype,
struct scsi2map *added, int *nadded)
{ {
/* assumes hba[ctlr]->scsi_ctlr->lock is held */ /* assumes hba[ctlr]->scsi_ctlr->lock is held */
int n = ccissscsi[ctlr].ndevices; int n = ccissscsi[ctlr].ndevices;
struct cciss_scsi_dev_t *sd; struct cciss_scsi_dev_t *sd;
int i, bus, target, lun;
unsigned char addr1[8], addr2[8];
if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) { if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
printk("cciss%d: Too many devices, " printk("cciss%d: Too many devices, "
"some will be inaccessible.\n", ctlr); "some will be inaccessible.\n", ctlr);
return -1; return -1;
} }
bus = target = -1;
lun = 0;
/* Is this device a non-zero lun of a multi-lun device */
/* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
if (scsi3addr[4] != 0) {
/* Search through our list and find the device which */
/* has the same 8 byte LUN address, excepting byte 4. */
/* Assign the same bus and target for this new LUN. */
/* Use the logical unit number from the firmware. */
memcpy(addr1, scsi3addr, 8);
addr1[4] = 0;
for (i = 0; i < n; i++) {
sd = &ccissscsi[ctlr].dev[i];
memcpy(addr2, sd->scsi3addr, 8);
addr2[4] = 0;
/* differ only in byte 4? */
if (memcmp(addr1, addr2, 8) == 0) {
bus = sd->bus;
target = sd->target;
lun = scsi3addr[4];
break;
}
}
}
sd = &ccissscsi[ctlr].dev[n]; sd = &ccissscsi[ctlr].dev[n];
if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0) if (lun == 0) {
return -1; if (find_bus_target_lun(ctlr,
&sd->bus, &sd->target, &sd->lun) != 0)
return -1;
} else {
sd->bus = bus;
sd->target = target;
sd->lun = lun;
}
added[*nadded].bus = sd->bus;
added[*nadded].target = sd->target;
added[*nadded].lun = sd->lun;
(*nadded)++;
memcpy(&sd->scsi3addr[0], scsi3addr, 8); memcpy(&sd->scsi3addr[0], scsi3addr, 8);
sd->devtype = devtype; sd->devtype = devtype;
ccissscsi[ctlr].ndevices++; ccissscsi[ctlr].ndevices++;
...@@ -390,7 +435,8 @@ cciss_scsi_add_entry(int ctlr, int hostno, ...@@ -390,7 +435,8 @@ cciss_scsi_add_entry(int ctlr, int hostno,
} }
static void static void
cciss_scsi_remove_entry(int ctlr, int hostno, int entry) cciss_scsi_remove_entry(int ctlr, int hostno, int entry,
struct scsi2map *removed, int *nremoved)
{ {
/* assumes hba[ctlr]->scsi_ctlr->lock is held */ /* assumes hba[ctlr]->scsi_ctlr->lock is held */
int i; int i;
...@@ -398,6 +444,10 @@ cciss_scsi_remove_entry(int ctlr, int hostno, int entry) ...@@ -398,6 +444,10 @@ cciss_scsi_remove_entry(int ctlr, int hostno, int entry)
if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return; if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return;
sd = ccissscsi[ctlr].dev[entry]; sd = ccissscsi[ctlr].dev[entry];
removed[*nremoved].bus = sd.bus;
removed[*nremoved].target = sd.target;
removed[*nremoved].lun = sd.lun;
(*nremoved)++;
for (i=entry;i<ccissscsi[ctlr].ndevices-1;i++) for (i=entry;i<ccissscsi[ctlr].ndevices-1;i++)
ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1]; ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1];
ccissscsi[ctlr].ndevices--; ccissscsi[ctlr].ndevices--;
...@@ -417,6 +467,26 @@ cciss_scsi_remove_entry(int ctlr, int hostno, int entry) ...@@ -417,6 +467,26 @@ cciss_scsi_remove_entry(int ctlr, int hostno, int entry)
(a)[1] == (b)[1] && \ (a)[1] == (b)[1] && \
(a)[0] == (b)[0]) (a)[0] == (b)[0])
static void fixup_botched_add(int ctlr, char *scsi3addr)
{
/* called when scsi_add_device fails in order to re-adjust */
/* ccissscsi[] to match the mid layer's view. */
unsigned long flags;
int i, j;
CPQ_TAPE_LOCK(ctlr, flags);
for (i = 0; i < ccissscsi[ctlr].ndevices; i++) {
if (memcmp(scsi3addr,
ccissscsi[ctlr].dev[i].scsi3addr, 8) == 0) {
for (j = i; j < ccissscsi[ctlr].ndevices-1; j++)
ccissscsi[ctlr].dev[j] =
ccissscsi[ctlr].dev[j+1];
ccissscsi[ctlr].ndevices--;
break;
}
}
CPQ_TAPE_UNLOCK(ctlr, flags);
}
static int static int
adjust_cciss_scsi_table(int ctlr, int hostno, adjust_cciss_scsi_table(int ctlr, int hostno,
struct cciss_scsi_dev_t sd[], int nsds) struct cciss_scsi_dev_t sd[], int nsds)
...@@ -429,13 +499,33 @@ adjust_cciss_scsi_table(int ctlr, int hostno, ...@@ -429,13 +499,33 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
int i,j, found, changes=0; int i,j, found, changes=0;
struct cciss_scsi_dev_t *csd; struct cciss_scsi_dev_t *csd;
unsigned long flags; unsigned long flags;
struct scsi2map *added, *removed;
int nadded, nremoved;
struct Scsi_Host *sh = NULL;
added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA,
GFP_KERNEL);
removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA,
GFP_KERNEL);
if (!added || !removed) {
printk(KERN_WARNING "cciss%d: Out of memory in "
"adjust_cciss_scsi_table\n", ctlr);
goto free_and_out;
}
CPQ_TAPE_LOCK(ctlr, flags); CPQ_TAPE_LOCK(ctlr, flags);
if (hostno != -1) /* if it's not the first time... */
sh = ((struct cciss_scsi_adapter_data_t *)
hba[ctlr]->scsi_ctlr)->scsi_host;
/* find any devices in ccissscsi[] that are not in /* find any devices in ccissscsi[] that are not in
sd[] and remove them from ccissscsi[] */ sd[] and remove them from ccissscsi[] */
i = 0; i = 0;
nremoved = 0;
nadded = 0;
while(i<ccissscsi[ctlr].ndevices) { while(i<ccissscsi[ctlr].ndevices) {
csd = &ccissscsi[ctlr].dev[i]; csd = &ccissscsi[ctlr].dev[i];
found=0; found=0;
...@@ -455,8 +545,9 @@ adjust_cciss_scsi_table(int ctlr, int hostno, ...@@ -455,8 +545,9 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
/* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n",
ctlr, scsi_device_type(csd->devtype), hostno, ctlr, scsi_device_type(csd->devtype), hostno,
csd->bus, csd->target, csd->lun); */ csd->bus, csd->target, csd->lun); */
cciss_scsi_remove_entry(ctlr, hostno, i); cciss_scsi_remove_entry(ctlr, hostno, i,
/* note, i not incremented */ removed, &nremoved);
/* remove ^^^, hence i not incremented */
} }
else if (found == 1) { /* device is different kind */ else if (found == 1) { /* device is different kind */
changes++; changes++;
...@@ -464,8 +555,15 @@ adjust_cciss_scsi_table(int ctlr, int hostno, ...@@ -464,8 +555,15 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
"(device type now %s).\n", "(device type now %s).\n",
ctlr, hostno, csd->bus, csd->target, csd->lun, ctlr, hostno, csd->bus, csd->target, csd->lun,
scsi_device_type(csd->devtype)); scsi_device_type(csd->devtype));
cciss_scsi_remove_entry(ctlr, hostno, i,
removed, &nremoved);
/* remove ^^^, hence i not incremented */
if (cciss_scsi_add_entry(ctlr, hostno,
&sd[j].scsi3addr[0], sd[j].devtype,
added, &nadded) != 0)
/* we just removed one, so add can't fail. */
BUG();
csd->devtype = sd[j].devtype; csd->devtype = sd[j].devtype;
i++; /* so just move along. */
} else /* device is same as it ever was, */ } else /* device is same as it ever was, */
i++; /* so just move along. */ i++; /* so just move along. */
} }
...@@ -489,7 +587,9 @@ adjust_cciss_scsi_table(int ctlr, int hostno, ...@@ -489,7 +587,9 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
if (!found) { if (!found) {
changes++; changes++;
if (cciss_scsi_add_entry(ctlr, hostno, if (cciss_scsi_add_entry(ctlr, hostno,
&sd[i].scsi3addr[0], sd[i].devtype) != 0)
&sd[i].scsi3addr[0], sd[i].devtype,
added, &nadded) != 0)
break; break;
} else if (found == 1) { } else if (found == 1) {
/* should never happen... */ /* should never happen... */
...@@ -501,9 +601,50 @@ adjust_cciss_scsi_table(int ctlr, int hostno, ...@@ -501,9 +601,50 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
} }
CPQ_TAPE_UNLOCK(ctlr, flags); CPQ_TAPE_UNLOCK(ctlr, flags);
if (!changes) /* Don't notify scsi mid layer of any changes the first time through */
printk("cciss%d: No device changes detected.\n", ctlr); /* (or if there are no changes) scsi_scan_host will do it later the */
/* first time through. */
if (hostno == -1 || !changes)
goto free_and_out;
/* Notify scsi mid layer of any removed devices */
for (i = 0; i < nremoved; i++) {
struct scsi_device *sdev =
scsi_device_lookup(sh, removed[i].bus,
removed[i].target, removed[i].lun);
if (sdev != NULL) {
scsi_remove_device(sdev);
scsi_device_put(sdev);
} else {
/* We don't expect to get here. */
/* future cmds to this device will get selection */
/* timeout as if the device was gone. */
printk(KERN_WARNING "cciss%d: didn't find "
"c%db%dt%dl%d\n for removal.",
ctlr, hostno, removed[i].bus,
removed[i].target, removed[i].lun);
}
}
/* Notify scsi mid layer of any added devices */
for (i = 0; i < nadded; i++) {
int rc;
rc = scsi_add_device(sh, added[i].bus,
added[i].target, added[i].lun);
if (rc == 0)
continue;
printk(KERN_WARNING "cciss%d: scsi_add_device "
"c%db%dt%dl%d failed, device not added.\n",
ctlr, hostno,
added[i].bus, added[i].target, added[i].lun);
/* now we have to remove it from ccissscsi, */
/* since it didn't get added to scsi mid layer */
fixup_botched_add(ctlr, added[i].scsi3addr);
}
free_and_out:
kfree(added);
kfree(removed);
return 0; return 0;
} }
...@@ -1354,32 +1495,6 @@ cciss_unregister_scsi(int ctlr) ...@@ -1354,32 +1495,6 @@ cciss_unregister_scsi(int ctlr)
kfree(sa); kfree(sa);
} }
static int
cciss_register_scsi(int ctlr)
{
unsigned long flags;
CPQ_TAPE_LOCK(ctlr, flags);
/* Since this is really a block driver, the SCSI core may not be
initialized at init time, in which case, calling scsi_register_host
would hang. Instead, we do it later, via /proc filesystem
and rc scripts, when we know SCSI core is good to go. */
/* Only register if SCSI devices are detected. */
if (ccissscsi[ctlr].ndevices != 0) {
((struct cciss_scsi_adapter_data_t *)
hba[ctlr]->scsi_ctlr)->registered = 1;
CPQ_TAPE_UNLOCK(ctlr, flags);
return cciss_scsi_detect(ctlr);
}
CPQ_TAPE_UNLOCK(ctlr, flags);
printk(KERN_INFO
"cciss%d: No appropriate SCSI device detected, "
"SCSI subsystem not engaged.\n", ctlr);
return 0;
}
static int static int
cciss_engage_scsi(int ctlr) cciss_engage_scsi(int ctlr)
{ {
...@@ -1391,15 +1506,15 @@ cciss_engage_scsi(int ctlr) ...@@ -1391,15 +1506,15 @@ cciss_engage_scsi(int ctlr)
sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr;
stk = &sa->cmd_stack; stk = &sa->cmd_stack;
if (((struct cciss_scsi_adapter_data_t *) if (sa->registered) {
hba[ctlr]->scsi_ctlr)->registered) {
printk("cciss%d: SCSI subsystem already engaged.\n", ctlr); printk("cciss%d: SCSI subsystem already engaged.\n", ctlr);
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
return ENXIO; return ENXIO;
} }
sa->registered = 1;
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); cciss_scsi_detect(ctlr);
return 0; return 0;
} }
...@@ -1493,7 +1608,5 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd) ...@@ -1493,7 +1608,5 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
/* If no tape support, then these become defined out of existence */ /* If no tape support, then these become defined out of existence */
#define cciss_scsi_setup(cntl_num) #define cciss_scsi_setup(cntl_num)
#define cciss_unregister_scsi(ctlr)
#define cciss_register_scsi(ctlr)
#endif /* CONFIG_CISS_SCSI_TAPE */ #endif /* CONFIG_CISS_SCSI_TAPE */
...@@ -154,8 +154,8 @@ static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg) ...@@ -154,8 +154,8 @@ static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
return 0; return 0;
} }
int blkif_ioctl(struct inode *inode, struct file *filep, static int blkif_ioctl(struct inode *inode, struct file *filep,
unsigned command, unsigned long argument) unsigned command, unsigned long argument)
{ {
struct blkfront_info *info = struct blkfront_info *info =
inode->i_bdev->bd_disk->private_data; inode->i_bdev->bd_disk->private_data;
......
...@@ -77,11 +77,8 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct ...@@ -77,11 +77,8 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct
*/ */
bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask); bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
if (bvl) { if (bvl)
struct biovec_slab *bp = bvec_slabs + *idx; memset(bvl, 0, bvec_nr_vecs(*idx) * sizeof(struct bio_vec));
memset(bvl, 0, bp->nr_vecs * sizeof(struct bio_vec));
}
return bvl; return bvl;
} }
...@@ -149,7 +146,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) ...@@ -149,7 +146,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
goto out; goto out;
} }
bio->bi_flags |= idx << BIO_POOL_OFFSET; bio->bi_flags |= idx << BIO_POOL_OFFSET;
bio->bi_max_vecs = bvec_slabs[idx].nr_vecs; bio->bi_max_vecs = bvec_nr_vecs(idx);
} }
bio->bi_io_vec = bvl; bio->bi_io_vec = bvl;
} }
......
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