summaryrefslogtreecommitdiff
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c99
1 files changed, 63 insertions, 36 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1e1f9153000c..12de1fdaa6c6 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -96,6 +96,8 @@ static const struct pci_device_id cciss_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B},
{PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
{0,}
@@ -133,6 +135,8 @@ static struct board_type products[] = {
{0x3245103C, "Smart Array P410i", &SA5_access},
{0x3247103C, "Smart Array P411", &SA5_access},
{0x3249103C, "Smart Array P812", &SA5_access},
+ {0x324A103C, "Smart Array P712m", &SA5_access},
+ {0x324B103C, "Smart Array P711m", &SA5_access},
{0xFFFF103C, "Unknown Smart Array", &SA5_access},
};
@@ -152,9 +156,9 @@ static ctlr_info_t *hba[MAX_CTLR];
static void do_cciss_request(struct request_queue *q);
static irqreturn_t do_cciss_intr(int irq, void *dev_id);
-static int cciss_open(struct inode *inode, struct file *filep);
-static int cciss_release(struct inode *inode, struct file *filep);
-static int cciss_ioctl(struct inode *inode, struct file *filep,
+static int cciss_open(struct block_device *bdev, fmode_t mode);
+static int cciss_release(struct gendisk *disk, fmode_t mode);
+static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg);
static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
@@ -192,14 +196,15 @@ static void cciss_procinit(int i)
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_COMPAT
-static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+static int cciss_compat_ioctl(struct block_device *, fmode_t,
+ unsigned, unsigned long);
#endif
static struct block_device_operations cciss_fops = {
.owner = THIS_MODULE,
.open = cciss_open,
.release = cciss_release,
- .ioctl = cciss_ioctl,
+ .locked_ioctl = cciss_ioctl,
.getgeo = cciss_getgeo,
#ifdef CONFIG_COMPAT
.compat_ioctl = cciss_compat_ioctl,
@@ -547,13 +552,13 @@ static inline drive_info_struct *get_drv(struct gendisk *disk)
/*
* Open. Make sure the device is really there.
*/
-static int cciss_open(struct inode *inode, struct file *filep)
+static int cciss_open(struct block_device *bdev, fmode_t mode)
{
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
- drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk);
+ ctlr_info_t *host = get_host(bdev->bd_disk);
+ drive_info_struct *drv = get_drv(bdev->bd_disk);
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
+ printk(KERN_DEBUG "cciss_open %s\n", bdev->bd_disk->disk_name);
#endif /* CCISS_DEBUG */
if (host->busy_initializing || drv->busy_configuring)
@@ -567,9 +572,9 @@ static int cciss_open(struct inode *inode, struct file *filep)
* for "raw controller".
*/
if (drv->heads == 0) {
- if (iminor(inode) != 0) { /* not node 0? */
+ if (MINOR(bdev->bd_dev) != 0) { /* not node 0? */
/* if not node 0 make sure it is a partition = 0 */
- if (iminor(inode) & 0x0f) {
+ if (MINOR(bdev->bd_dev) & 0x0f) {
return -ENXIO;
/* if it is, make sure we have a LUN ID */
} else if (drv->LunID == 0) {
@@ -587,14 +592,13 @@ static int cciss_open(struct inode *inode, struct file *filep)
/*
* Close. Sync first.
*/
-static int cciss_release(struct inode *inode, struct file *filep)
+static int cciss_release(struct gendisk *disk, fmode_t mode)
{
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
- drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk);
+ ctlr_info_t *host = get_host(disk);
+ drive_info_struct *drv = get_drv(disk);
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "cciss_release %s\n",
- inode->i_bdev->bd_disk->disk_name);
+ printk(KERN_DEBUG "cciss_release %s\n", disk->disk_name);
#endif /* CCISS_DEBUG */
drv->usage_count--;
@@ -604,21 +608,23 @@ static int cciss_release(struct inode *inode, struct file *filep)
#ifdef CONFIG_COMPAT
-static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+static int do_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
int ret;
lock_kernel();
- ret = cciss_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
+ ret = cciss_ioctl(bdev, mode, cmd, arg);
unlock_kernel();
return ret;
}
-static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
- unsigned long arg);
-static int cciss_ioctl32_big_passthru(struct file *f, unsigned cmd,
- unsigned long arg);
+static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg);
+static int cciss_ioctl32_big_passthru(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg);
-static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+static int cciss_compat_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
switch (cmd) {
case CCISS_GETPCIINFO:
@@ -636,20 +642,20 @@ static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
case CCISS_REGNEWD:
case CCISS_RESCANDISK:
case CCISS_GETLUNINFO:
- return do_ioctl(f, cmd, arg);
+ return do_ioctl(bdev, mode, cmd, arg);
case CCISS_PASSTHRU32:
- return cciss_ioctl32_passthru(f, cmd, arg);
+ return cciss_ioctl32_passthru(bdev, mode, cmd, arg);
case CCISS_BIG_PASSTHRU32:
- return cciss_ioctl32_big_passthru(f, cmd, arg);
+ return cciss_ioctl32_big_passthru(bdev, mode, cmd, arg);
default:
return -ENOIOCTLCMD;
}
}
-static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
- unsigned long arg)
+static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
IOCTL32_Command_struct __user *arg32 =
(IOCTL32_Command_struct __user *) arg;
@@ -676,7 +682,7 @@ static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
if (err)
return -EFAULT;
- err = do_ioctl(f, CCISS_PASSTHRU, (unsigned long)p);
+ err = do_ioctl(bdev, mode, CCISS_PASSTHRU, (unsigned long)p);
if (err)
return err;
err |=
@@ -687,8 +693,8 @@ static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
return err;
}
-static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd,
- unsigned long arg)
+static int cciss_ioctl32_big_passthru(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
BIG_IOCTL32_Command_struct __user *arg32 =
(BIG_IOCTL32_Command_struct __user *) arg;
@@ -717,7 +723,7 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd,
if (err)
return -EFAULT;
- err = do_ioctl(file, CCISS_BIG_PASSTHRU, (unsigned long)p);
+ err = do_ioctl(bdev, mode, CCISS_BIG_PASSTHRU, (unsigned long)p);
if (err)
return err;
err |=
@@ -745,10 +751,9 @@ static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
/*
* ioctl
*/
-static int cciss_ioctl(struct inode *inode, struct file *filep,
+static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
ctlr_info_t *host = get_host(disk);
drive_info_struct *drv = get_drv(disk);
@@ -1232,7 +1237,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
case SG_EMULATED_HOST:
case SG_IO:
case SCSI_IOCTL_SEND_COMMAND:
- return scsi_cmd_ioctl(filep, disk->queue, disk, cmd, argp);
+ return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
/* scsi_cmd_ioctl would normally handle these, below, but */
/* they aren't a good fit for cciss, as CD-ROMs are */
@@ -1365,6 +1370,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
disk->first_minor = drv_index << NWD_SHIFT;
disk->fops = &cciss_fops;
disk->private_data = &h->drv[drv_index];
+ disk->driverfs_dev = &h->pdev->dev;
/* Set up queue information */
blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
@@ -3403,7 +3409,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
int i;
int j = 0;
int rc;
- int dac;
+ int dac, return_code;
+ InquiryData_struct *inq_buff = NULL;
i = alloc_cciss_hba();
if (i < 0)
@@ -3509,6 +3516,25 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
/* Turn the interrupts on so we can service requests */
hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
+ /* Get the firmware version */
+ inq_buff = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL);
+ if (inq_buff == NULL) {
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto clean4;
+ }
+
+ return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff,
+ sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD);
+ if (return_code == IO_OK) {
+ hba[i]->firm_ver[0] = inq_buff->data_byte[32];
+ hba[i]->firm_ver[1] = inq_buff->data_byte[33];
+ hba[i]->firm_ver[2] = inq_buff->data_byte[34];
+ hba[i]->firm_ver[3] = inq_buff->data_byte[35];
+ } else { /* send command failed */
+ printk(KERN_WARNING "cciss: unable to determine firmware"
+ " version of controller\n");
+ }
+
cciss_procinit(i);
hba[i]->cciss_max_sectors = 2048;
@@ -3519,6 +3545,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
return 1;
clean4:
+ kfree(inq_buff);
#ifdef CONFIG_CISS_SCSI_TAPE
kfree(hba[i]->scsi_rejects.complete);
#endif