diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 15:22:42 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 15:22:42 -0700 |
commit | 2f9e825d3e0e2b407ae8f082de5c00afcf7378fb (patch) | |
tree | f8b3ee40674ce4acd5508a0a0bf52a30904caf6c /drivers/block/cciss.c | |
parent | 7ae0dea900b027cd90e8a3e14deca9a19e17638b (diff) | |
parent | de75d60d5ea235e6e09f4962ab22541ce0fe176a (diff) |
Merge branch 'for-2.6.36' of git://git.kernel.dk/linux-2.6-block
* 'for-2.6.36' of git://git.kernel.dk/linux-2.6-block: (149 commits)
block: make sure that REQ_* types are seen even with CONFIG_BLOCK=n
xen-blkfront: fix missing out label
blkdev: fix blkdev_issue_zeroout return value
block: update request stacking methods to support discards
block: fix missing export of blk_types.h
writeback: fix bad _bh spinlock nesting
drbd: revert "delay probes", feature is being re-implemented differently
drbd: Initialize all members of sync_conf to their defaults [Bugz 315]
drbd: Disable delay probes for the upcomming release
writeback: cleanup bdi_register
writeback: add new tracepoints
writeback: remove unnecessary init_timer call
writeback: optimize periodic bdi thread wakeups
writeback: prevent unnecessary bdi threads wakeups
writeback: move bdi threads exiting logic to the forker thread
writeback: restructure bdi forker loop a little
writeback: move last_active to bdi
writeback: do not remove bdi from bdi_list
writeback: simplify bdi code a little
writeback: do not lose wake-ups in bdi threads
...
Fixed up pretty trivial conflicts in drivers/block/virtio_blk.c and
drivers/scsi/scsi_error.c as per Jens.
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 2165 |
1 files changed, 1281 insertions, 884 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e1e7143ca1e3..31064df1370a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -56,16 +56,14 @@ #include <linux/kthread.h> #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 3.6.20)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(3, 6, 20) +#define DRIVER_NAME "HP CISS Driver (v 3.6.26)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(3, 6, 26) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); MODULE_DESCRIPTION("Driver for HP Smart Array Controllers"); -MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" - " SA6i P600 P800 P400 P400i E200 E200i E500 P700m" - " Smart Array G2 Series SAS/SATA Controllers"); -MODULE_VERSION("3.6.20"); +MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers"); +MODULE_VERSION("3.6.26"); MODULE_LICENSE("GPL"); static int cciss_allow_hpsa; @@ -107,6 +105,11 @@ static const struct pci_device_id cciss_pci_device_id[] = { {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_DEVICE_ID_HP_CISSE, 0x103C, 0x3250}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3251}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3252}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3253}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3254}, {0,} }; @@ -146,6 +149,11 @@ static struct board_type products[] = { {0x3249103C, "Smart Array P812", &SA5_access}, {0x324A103C, "Smart Array P712m", &SA5_access}, {0x324B103C, "Smart Array P711m", &SA5_access}, + {0x3250103C, "Smart Array", &SA5_access}, + {0x3251103C, "Smart Array", &SA5_access}, + {0x3252103C, "Smart Array", &SA5_access}, + {0x3253103C, "Smart Array", &SA5_access}, + {0x3254103C, "Smart Array", &SA5_access}, }; /* How long to wait (in milliseconds) for board to go into simple mode */ @@ -167,9 +175,13 @@ static DEFINE_MUTEX(scan_mutex); static LIST_HEAD(scan_q); static void do_cciss_request(struct request_queue *q); -static irqreturn_t do_cciss_intr(int irq, void *dev_id); +static irqreturn_t do_cciss_intx(int irq, void *dev_id); +static irqreturn_t do_cciss_msix_intr(int irq, void *dev_id); static int cciss_open(struct block_device *bdev, fmode_t mode); +static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode); static int cciss_release(struct gendisk *disk, fmode_t mode); +static int do_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg); 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); @@ -179,25 +191,23 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time, int via_ioctl); static int deregister_disk(ctlr_info_t *h, int drv_index, int clear_all, int via_ioctl); -static void cciss_read_capacity(int ctlr, int logvol, +static void cciss_read_capacity(ctlr_info_t *h, int logvol, sector_t *total_size, unsigned int *block_size); -static void cciss_read_capacity_16(int ctlr, int logvol, +static void cciss_read_capacity_16(ctlr_info_t *h, int logvol, sector_t *total_size, unsigned int *block_size); -static void cciss_geometry_inquiry(int ctlr, int logvol, +static void cciss_geometry_inquiry(ctlr_info_t *h, int logvol, sector_t total_size, unsigned int block_size, InquiryData_struct *inq_buff, drive_info_struct *drv); -static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, - __u32); +static void __devinit cciss_interrupt_mode(ctlr_info_t *); static void start_io(ctlr_info_t *h); -static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, +static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, __u8 page_code, unsigned char scsi3addr[], int cmd_type); static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c, int attempt_retry); static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c); -static void fail_all_cmds(unsigned long ctlr); static int add_to_scan_list(struct ctlr_info *h); static int scan_thread(void *data); static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c); @@ -205,11 +215,23 @@ static void cciss_hba_release(struct device *dev); static void cciss_device_release(struct device *dev); static void cciss_free_gendisk(ctlr_info_t *h, int drv_index); static void cciss_free_drive_info(ctlr_info_t *h, int drv_index); +static inline u32 next_command(ctlr_info_t *h); +static int __devinit cciss_find_cfg_addrs(struct pci_dev *pdev, + void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index, + u64 *cfg_offset); +static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev, + unsigned long *memory_bar); + + +/* performant mode helper functions */ +static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, + int *bucket_map); +static void cciss_put_controller_into_performant_mode(ctlr_info_t *h); #ifdef CONFIG_PROC_FS -static void cciss_procinit(int i); +static void cciss_procinit(ctlr_info_t *h); #else -static void cciss_procinit(int i) +static void cciss_procinit(ctlr_info_t *h) { } #endif /* CONFIG_PROC_FS */ @@ -221,9 +243,9 @@ static int cciss_compat_ioctl(struct block_device *, fmode_t, static const struct block_device_operations cciss_fops = { .owner = THIS_MODULE, - .open = cciss_open, + .open = cciss_unlocked_open, .release = cciss_release, - .locked_ioctl = cciss_ioctl, + .ioctl = do_ioctl, .getgeo = cciss_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = cciss_compat_ioctl, @@ -231,6 +253,16 @@ static const struct block_device_operations cciss_fops = { .revalidate_disk = cciss_revalidate, }; +/* set_performant_mode: Modify the tag for cciss performant + * set bit 0 for pull model, bits 3-1 for block fetch + * register number + */ +static void set_performant_mode(ctlr_info_t *h, CommandList_struct *c) +{ + if (likely(h->transMethod == CFGTBL_Trans_Performant)) + c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); +} + /* * Enqueuing and dequeuing functions for cmdlists. */ @@ -257,6 +289,18 @@ static inline void removeQ(CommandList_struct *c) hlist_del_init(&c->list); } +static void enqueue_cmd_and_start_io(ctlr_info_t *h, + CommandList_struct *c) +{ + unsigned long flags; + set_performant_mode(h, c); + spin_lock_irqsave(&h->lock, flags); + addQ(&h->reqQ, c); + h->Qdepth++; + start_io(h); + spin_unlock_irqrestore(&h->lock, flags); +} + static void cciss_free_sg_chain_blocks(SGDescriptor_struct **cmd_sg_list, int nr_cmds) { @@ -366,32 +410,31 @@ static void cciss_seq_show_header(struct seq_file *seq) h->product_name, (unsigned long)h->board_id, h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], - h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT], + h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT], h->num_luns, h->Qdepth, h->commands_outstanding, h->maxQsinceinit, h->max_outstanding, h->maxSG); #ifdef CONFIG_CISS_SCSI_TAPE - cciss_seq_tape_report(seq, h->ctlr); + cciss_seq_tape_report(seq, h); #endif /* CONFIG_CISS_SCSI_TAPE */ } static void *cciss_seq_start(struct seq_file *seq, loff_t *pos) { ctlr_info_t *h = seq->private; - unsigned ctlr = h->ctlr; unsigned long flags; /* prevent displaying bogus info during configuration * or deconfiguration of a logical volume */ - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + spin_lock_irqsave(&h->lock, flags); if (h->busy_configuring) { - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); return ERR_PTR(-EBUSY); } h->busy_configuring = 1; - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); if (*pos == 0) cciss_seq_show_header(seq); @@ -499,7 +542,7 @@ cciss_proc_write(struct file *file, const char __user *buf, struct seq_file *seq = file->private_data; ctlr_info_t *h = seq->private; - err = cciss_engage_scsi(h->ctlr); + err = cciss_engage_scsi(h); if (err == 0) err = length; } else @@ -522,7 +565,7 @@ static const struct file_operations cciss_proc_fops = { .write = cciss_proc_write, }; -static void __devinit cciss_procinit(int i) +static void __devinit cciss_procinit(ctlr_info_t *h) { struct proc_dir_entry *pde; @@ -530,9 +573,9 @@ static void __devinit cciss_procinit(int i) proc_cciss = proc_mkdir("driver/cciss", NULL); if (!proc_cciss) return; - pde = proc_create_data(hba[i]->devname, S_IWUSR | S_IRUSR | S_IRGRP | + pde = proc_create_data(h->devname, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, proc_cciss, - &cciss_proc_fops, hba[i]); + &cciss_proc_fops, h); } #endif /* CONFIG_PROC_FS */ @@ -565,12 +608,12 @@ static ssize_t dev_show_unique_id(struct device *dev, unsigned long flags; int ret = 0; - spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); + spin_lock_irqsave(&h->lock, flags); if (h->busy_configuring) ret = -EBUSY; else memcpy(sn, drv->serial_no, sizeof(sn)); - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); if (ret) return ret; @@ -595,12 +638,12 @@ static ssize_t dev_show_vendor(struct device *dev, unsigned long flags; int ret = 0; - spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); + spin_lock_irqsave(&h->lock, flags); if (h->busy_configuring) ret = -EBUSY; else memcpy(vendor, drv->vendor, VENDOR_LEN + 1); - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); if (ret) return ret; @@ -619,12 +662,12 @@ static ssize_t dev_show_model(struct device *dev, unsigned long flags; int ret = 0; - spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); + spin_lock_irqsave(&h->lock, flags); if (h->busy_configuring) ret = -EBUSY; else memcpy(model, drv->model, MODEL_LEN + 1); - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); if (ret) return ret; @@ -643,12 +686,12 @@ static ssize_t dev_show_rev(struct device *dev, unsigned long flags; int ret = 0; - spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); + spin_lock_irqsave(&h->lock, flags); if (h->busy_configuring) ret = -EBUSY; else memcpy(rev, drv->rev, REV_LEN + 1); - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); if (ret) return ret; @@ -665,17 +708,17 @@ static ssize_t cciss_show_lunid(struct device *dev, unsigned long flags; unsigned char lunid[8]; - spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); + spin_lock_irqsave(&h->lock, flags); if (h->busy_configuring) { - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); return -EBUSY; } if (!drv->heads) { - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); return -ENOTTY; } memcpy(lunid, drv->LunID, sizeof(lunid)); - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); return snprintf(buf, 20, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", lunid[0], lunid[1], lunid[2], lunid[3], lunid[4], lunid[5], lunid[6], lunid[7]); @@ -690,13 +733,13 @@ static ssize_t cciss_show_raid_level(struct device *dev, int raid; unsigned long flags; - spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); + spin_lock_irqsave(&h->lock, flags); if (h->busy_configuring) { - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); return -EBUSY; } raid = drv->raid_level; - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); if (raid < 0 || raid > RAID_UNKNOWN) raid = RAID_UNKNOWN; @@ -713,13 +756,13 @@ static ssize_t cciss_show_usage_count(struct device *dev, unsigned long flags; int count; - spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); + spin_lock_irqsave(&h->lock, flags); if (h->busy_configuring) { - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); return -EBUSY; } count = drv->usage_count; - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); return snprintf(buf, 20, "%d\n", count); } static DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL); @@ -864,60 +907,70 @@ static void cciss_destroy_ld_sysfs_entry(struct ctlr_info *h, int drv_index, /* * For operations that cannot sleep, a command block is allocated at init, * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track - * which ones are free or in use. For operations that can wait for kmalloc - * to possible sleep, this routine can be called with get_from_pool set to 0. - * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was. + * which ones are free or in use. */ -static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool) +static CommandList_struct *cmd_alloc(ctlr_info_t *h) { CommandList_struct *c; int i; u64bit temp64; dma_addr_t cmd_dma_handle, err_dma_handle; - if (!get_from_pool) { - c = (CommandList_struct *) pci_alloc_consistent(h->pdev, - sizeof(CommandList_struct), &cmd_dma_handle); - if (c == NULL) + do { + i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); + if (i == h->nr_cmds) return NULL; - memset(c, 0, sizeof(CommandList_struct)); + } while (test_and_set_bit(i & (BITS_PER_LONG - 1), + h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0); + c = h->cmd_pool + i; + memset(c, 0, sizeof(CommandList_struct)); + cmd_dma_handle = h->cmd_pool_dhandle + i * sizeof(CommandList_struct); + c->err_info = h->errinfo_pool + i; + memset(c->err_info, 0, sizeof(ErrorInfo_struct)); + err_dma_handle = h->errinfo_pool_dhandle + + i * sizeof(ErrorInfo_struct); + h->nr_allocs++; - c->cmdindex = -1; + c->cmdindex = i; - c->err_info = (ErrorInfo_struct *) - pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct), - &err_dma_handle); + INIT_HLIST_NODE(&c->list); + c->busaddr = (__u32) cmd_dma_handle; + temp64.val = (__u64) err_dma_handle; + c->ErrDesc.Addr.lower = temp64.val32.lower; + c->ErrDesc.Addr.upper = temp64.val32.upper; + c->ErrDesc.Len = sizeof(ErrorInfo_struct); - if (c->err_info == NULL) { - pci_free_consistent(h->pdev, - sizeof(CommandList_struct), c, cmd_dma_handle); - return NULL; - } - memset(c->err_info, 0, sizeof(ErrorInfo_struct)); - } else { /* get it out of the controllers pool */ - - do { - i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); - if (i == h->nr_cmds) - return NULL; - } while (test_and_set_bit - (i & (BITS_PER_LONG - 1), - h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0); -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: using command buffer %d\n", i); -#endif - c = h->cmd_pool + i; - memset(c, 0, sizeof(CommandList_struct)); - cmd_dma_handle = h->cmd_pool_dhandle - + i * sizeof(CommandList_struct); - c->err_info = h->errinfo_pool + i; - memset(c->err_info, 0, sizeof(ErrorInfo_struct)); - err_dma_handle = h->errinfo_pool_dhandle - + i * sizeof(ErrorInfo_struct); - h->nr_allocs++; + c->ctlr = h->ctlr; + return c; +} - c->cmdindex = i; +/* allocate a command using pci_alloc_consistent, used for ioctls, + * etc., not for the main i/o path. + */ +static CommandList_struct *cmd_special_alloc(ctlr_info_t *h) +{ + CommandList_struct *c; + u64bit temp64; + dma_addr_t cmd_dma_handle, err_dma_handle; + + c = (CommandList_struct *) pci_alloc_consistent(h->pdev, + sizeof(CommandList_struct), &cmd_dma_handle); + if (c == NULL) + return NULL; + memset(c, 0, sizeof(CommandList_struct)); + + c->cmdindex = -1; + + c->err_info = (ErrorInfo_struct *) + pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct), + &err_dma_handle); + + if (c->err_info == NULL) { + pci_free_consistent(h->pdev, + sizeof(CommandList_struct), c, cmd_dma_handle); + return NULL; } + memset(c->err_info, 0, sizeof(ErrorInfo_struct)); INIT_HLIST_NODE(&c->list); c->busaddr = (__u32) cmd_dma_handle; @@ -930,27 +983,26 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool) return c; } -/* - * Frees a command block that was previously allocated with cmd_alloc(). - */ -static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool) +static void cmd_free(ctlr_info_t *h, CommandList_struct *c) { int i; + + i = c - h->cmd_pool; + clear_bit(i & (BITS_PER_LONG - 1), + h->cmd_pool_bits + (i / BITS_PER_LONG)); + h->nr_frees++; +} + +static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c) +{ u64bit temp64; - if (!got_from_pool) { - temp64.val32.lower = c->ErrDesc.Addr.lower; - temp64.val32.upper = c->ErrDesc.Addr.upper; - pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), - c->err_info, (dma_addr_t) temp64.val); - pci_free_consistent(h->pdev, sizeof(CommandList_struct), - c, (dma_addr_t) c->busaddr); - } else { - i = c - h->cmd_pool; - clear_bit(i & (BITS_PER_LONG - 1), - h->cmd_pool_bits + (i / BITS_PER_LONG)); - h->nr_frees++; - } + temp64.val32.lower = c->ErrDesc.Addr.lower; + temp64.val32.upper = c->ErrDesc.Addr.upper; + pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), + c->err_info, (dma_addr_t) temp64.val); + pci_free_consistent(h->pdev, sizeof(CommandList_struct), + c, (dma_addr_t) c->busaddr); } static inline ctlr_info_t *get_host(struct gendisk *disk) @@ -968,13 +1020,10 @@ static inline drive_info_struct *get_drv(struct gendisk *disk) */ static int cciss_open(struct block_device *bdev, fmode_t mode) { - ctlr_info_t *host = get_host(bdev->bd_disk); + ctlr_info_t *h = get_host(bdev->bd_disk); drive_info_struct *drv = get_drv(bdev->bd_disk); -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_open %s\n", bdev->bd_disk->disk_name); -#endif /* CCISS_DEBUG */ - + dev_dbg(&h->pdev->dev, "cciss_open %s\n", bdev->bd_disk->disk_name); if (drv->busy_configuring) return -EBUSY; /* @@ -1000,29 +1049,39 @@ static int cciss_open(struct block_device *bdev, fmode_t mode) return -EPERM; } drv->usage_count++; - host->usage_count++; + h->usage_count++; return 0; } +static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = cciss_open(bdev, mode); + unlock_kernel(); + + return ret; +} + /* * Close. Sync first. */ static int cciss_release(struct gendisk *disk, fmode_t mode) { - ctlr_info_t *host = get_host(disk); - drive_info_struct *drv = get_drv(disk); - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_release %s\n", disk->disk_name); -#endif /* CCISS_DEBUG */ + ctlr_info_t *h; + drive_info_struct *drv; + lock_kernel(); + h = get_host(disk); + drv = get_drv(disk); + dev_dbg(&h->pdev->dev, "cciss_release %s\n", disk->disk_name); drv->usage_count--; - host->usage_count--; + h->usage_count--; + unlock_kernel(); return 0; } -#ifdef CONFIG_COMPAT - static int do_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { @@ -1033,6 +1092,8 @@ static int do_ioctl(struct block_device *bdev, fmode_t mode, return ret; } +#ifdef CONFIG_COMPAT + 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, @@ -1163,11 +1224,11 @@ static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static void check_ioctl_unit_attention(ctlr_info_t *host, CommandList_struct *c) +static void check_ioctl_unit_attention(ctlr_info_t *h, CommandList_struct *c) { if (c->err_info->CommandStatus == CMD_TARGET_STATUS && c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) - (void)check_for_unit_attention(host, c); + (void)check_for_unit_attention(h, c); } /* * ioctl @@ -1176,15 +1237,12 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct gendisk *disk = bdev->bd_disk; - ctlr_info_t *host = get_host(disk); + ctlr_info_t *h = get_host(disk); drive_info_struct *drv = get_drv(disk); - int ctlr = host->ctlr; void __user *argp = (void __user *)arg; -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg); -#endif /* CCISS_DEBUG */ - + dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n", + cmd, arg); switch (cmd) { case CCISS_GETPCIINFO: { @@ -1192,10 +1250,10 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, if (!arg) return -EINVAL; - pciinfo.domain = pci_domain_nr(host->pdev->bus); - pciinfo.bus = host->pdev->bus->number; - pciinfo.dev_fn = host->pdev->devfn; - pciinfo.board_id = host->board_id; + pciinfo.domain = pci_domain_nr(h->pdev->bus); + pciinfo.bus = h->pdev->bus->number; + pciinfo.dev_fn = h->pdev->devfn; + pciinfo.board_id = h->board_id; if (copy_to_user (argp, &pciinfo, sizeof(cciss_pci_info_struct))) return -EFAULT; @@ -1207,9 +1265,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, if (!arg) return -EINVAL; intinfo.delay = - readl(&host->cfgtable->HostWrite.CoalIntDelay); + readl(&h->cfgtable->HostWrite.CoalIntDelay); intinfo.count = - readl(&host->cfgtable->HostWrite.CoalIntCount); + readl(&h->cfgtable->HostWrite.CoalIntCount); if (copy_to_user (argp, &intinfo, sizeof(cciss_coalint_struct))) return -EFAULT; @@ -1229,26 +1287,23 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, (&intinfo, argp, sizeof(cciss_coalint_struct))) return -EFAULT; if ((intinfo.delay == 0) && (intinfo.count == 0)) - { -// printk("cciss_ioctl: delay and count cannot be 0\n"); return -EINVAL; - } - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + spin_lock_irqsave(&h->lock, flags); /* Update the field, and then ring the doorbell */ writel(intinfo.delay, - &(host->cfgtable->HostWrite.CoalIntDelay)); + &(h->cfgtable->HostWrite.CoalIntDelay)); writel(intinfo.count, - &(host->cfgtable->HostWrite.CoalIntCount)); - writel(CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); + &(h->cfgtable->HostWrite.CoalIntCount)); + writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) { - if (!(readl(host->vaddr + SA5_DOORBELL) + if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) break; /* delay and try again */ udelay(1000); } - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); if (i >= MAX_IOCTL_CONFIG_WAIT) return -EAGAIN; return 0; @@ -1262,7 +1317,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, return -EINVAL; for (i = 0; i < 16; i++) NodeName[i] = - readb(&host->cfgtable->ServerName[i]); + readb(&h->cfgtable->ServerName[i]); if (copy_to_user(argp, NodeName, sizeof(NodeName_type))) return -EFAULT; return 0; @@ -1282,23 +1337,23 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, (NodeName, argp, sizeof(NodeName_type))) return -EFAULT; - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + spin_lock_irqsave(&h->lock, flags); /* Update the field, and then ring the doorbell */ for (i = 0; i < 16; i++) writeb(NodeName[i], - &host->cfgtable->ServerName[i]); + &h->cfgtable->ServerName[i]); - writel(CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); + writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) { - if (!(readl(host->vaddr + SA5_DOORBELL) + if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) break; /* delay and try again */ udelay(1000); } - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + spin_unlock_irqrestore(&h->lock, flags); if (i >= MAX_IOCTL_CONFIG_WAIT) return -EAGAIN; return 0; @@ -1310,7 +1365,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, if (!arg) return -EINVAL; - heartbeat = readl(&host->cfgtable->HeartBeat); + heartbeat = readl(&h->cfgtable->HeartBeat); if (copy_to_user (argp, &heartbeat, sizeof(Heartbeat_type))) return -EFAULT; @@ -1322,7 +1377,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, if (!arg) return -EINVAL; - BusTypes = readl(&host->cfgtable->BusTypes); + BusTypes = readl(&h->cfgtable->BusTypes); if (copy_to_user (argp, &BusTypes, sizeof(BusTypes_type))) return -EFAULT; @@ -1334,7 +1389,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, if (!arg) return -EINVAL; - memcpy(firmware, host->firm_ver, 4); + memcpy(firmware, h->firm_ver, 4); if (copy_to_user (argp, firmware, sizeof(FirmwareVer_type))) @@ -1357,7 +1412,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, case CCISS_DEREGDISK: case CCISS_REGNEWD: case CCISS_REVALIDVOLS: - return rebuild_lun_table(host, 0, 1); + return rebuild_lun_table(h, 0, 1); case CCISS_GETLUNINFO:{ LogvolInfo_struct luninfo; @@ -1377,7 +1432,6 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, CommandList_struct *c; char *buff = NULL; u64bit temp64; - unsigned long flags; DECLARE_COMPLETION_ONSTACK(wait); if (!arg) @@ -1413,7 +1467,8 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, } else { memset(buff, 0, iocommand.buf_size); } - if ((c = cmd_alloc(host, 0)) == NULL) { + c = cmd_special_alloc(h); + if (!c) { kfree(buff); return -ENOMEM; } @@ -1439,7 +1494,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, /* Fill in the scatter gather information */ if (iocommand.buf_size > 0) { - temp64.val = pci_map_single(host->pdev, buff, + temp64.val = pci_map_single(h->pdev, buff, iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); c->SG[0].Addr.lower = temp64.val32.lower; @@ -1449,30 +1504,24 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, } c->waiting = &wait; - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&host->reqQ, c); - host->Qdepth++; - start_io(host); - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - + enqueue_cmd_and_start_io(h, c); wait_for_completion(&wait); /* unlock the buffers from DMA */ temp64.val32.lower = c->SG[0].Addr.lower; temp64.val32.upper = c->SG[0].Addr.upper; - pci_unmap_single(host->pdev, (dma_addr_t) temp64.val, + pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); - check_ioctl_unit_attention(host, c); + check_ioctl_unit_attention(h, c); /* Copy the error information out */ iocommand.error_info = *(c->err_info); if (copy_to_user (argp, &iocommand, sizeof(IOCTL_Command_struct))) { kfree(buff); - cmd_free(host, c, 0); + cmd_special_free(h, c); return -EFAULT; } @@ -1481,12 +1530,12 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, if (copy_to_user (iocommand.buf, buff, iocommand.buf_size)) { kfree(buff); - cmd_free(host, c, 0); + cmd_special_free(h, c); return -EFAULT; } } kfree(buff); - cmd_free(host, c, 0); + cmd_special_free(h, c); return 0; } case CCISS_BIG_PASSTHRU:{ @@ -1495,7 +1544,6 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, unsigned char **buff = NULL; int *buff_size = NULL; u64bit temp64; - unsigned long flags; BYTE sg_used = 0; int status = 0; int i; @@ -1569,7 +1617,8 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, data_ptr += sz; sg_used++; } - if ((c = cmd_alloc(host, 0)) == NULL) { + c = cmd_special_alloc(h); + if (!c) { status = -ENOMEM; goto cleanup1; } @@ -1590,7 +1639,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, if (ioc->buf_size > 0) { for (i = 0; i < sg_used; i++) { temp64.val = - pci_map_single(host->pdev, buff[i], + pci_map_single(h->pdev, buff[i], buff_size[i], PCI_DMA_BIDIRECTIONAL); c->SG[i].Addr.lower = @@ -1602,26 +1651,21 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, } } c->waiting = &wait; - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&host->reqQ, c); - host->Qdepth++; - start_io(host); - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + enqueue_cmd_and_start_io(h, c); wait_for_completion(&wait); /* unlock the buffers from DMA */ for (i = 0; i < sg_used; i++) { temp64.val32.lower = c->SG[i].Addr.lower; temp64.val32.upper = c->SG[i].Addr.upper; - pci_unmap_single(host->pdev, + pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, buff_size[i], PCI_DMA_BIDIRECTIONAL); } - check_ioctl_unit_attention(host, c); + check_ioctl_unit_attention(h, c); /* Copy the error information out */ ioc->error_info = *(c->err_info); if (copy_to_user(argp, ioc, sizeof(*ioc))) { - cmd_free(host, c, 0); + cmd_special_free(h, c); status = -EFAULT; goto cleanup1; } @@ -1631,14 +1675,14 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, for (i = 0; i < sg_used; i++) { if (copy_to_user (ptr, buff[i], buff_size[i])) { - cmd_free(host, c, 0); + cmd_special_free(h, c); status = -EFAULT; goto cleanup1; } ptr += buff_size[i]; } } - cmd_free(host, c, 0); + cmd_special_free(h, c); status = 0; cleanup1: if (buff) { @@ -1726,26 +1770,26 @@ static void cciss_check_queues(ctlr_info_t *h) static void cciss_softirq_done(struct request *rq) { - CommandList_struct *cmd = rq->completion_data; - ctlr_info_t *h = hba[cmd->ctlr]; - SGDescriptor_struct *curr_sg = cmd->SG; - unsigned long flags; + CommandList_struct *c = rq->completion_data; + ctlr_info_t *h = hba[c->ctlr]; + SGDescriptor_struct *curr_sg = c->SG; u64bit temp64; + unsigned long flags; int i, ddir; int sg_index = 0; - if (cmd->Request.Type.Direction == XFER_READ) + if (c->Request.Type.Direction == XFER_READ) ddir = PCI_DMA_FROMDEVICE; else ddir = PCI_DMA_TODEVICE; /* command did not need to be retried */ /* unmap the DMA mapping for all the scatter gather elements */ - for (i = 0; i < cmd->Header.SGList; i++) { + for (i = 0; i < c->Header.SGList; i++) { if (curr_sg[sg_index].Ext == CCISS_SG_CHAIN) { - cciss_unmap_sg_chain_block(h, cmd); + cciss_unmap_sg_chain_block(h, c); /* Point to the next block */ - curr_sg = h->cmd_sg_list[cmd->cmdindex]; + curr_sg = h->cmd_sg_list[c->cmdindex]; sg_index = 0; } temp64.val32.lower = curr_sg[sg_index].Addr.lower; @@ -1755,18 +1799,16 @@ static void cciss_softirq_done(struct request *rq) ++sg_index; } -#ifdef CCISS_DEBUG - printk("Done with %p\n", rq); -#endif /* CCISS_DEBUG */ + dev_dbg(&h->pdev->dev, "Done with %p\n", rq); /* set the residual count for pc requests */ - if (blk_pc_request(rq)) - rq->resid_len = cmd->err_info->ResidualCnt; + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) + rq->resid_len = c->err_info->ResidualCnt; blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO); spin_lock_irqsave(&h->lock, flags); - cmd_free(h, cmd, 1); + cmd_free(h, c); cciss_check_queues(h); spin_unlock_irqrestore(&h->lock, flags); } @@ -1782,7 +1824,7 @@ static inline void log_unit_to_scsi3addr(ctlr_info_t *h, * via the inquiry page 0. Model, vendor, and rev are set to empty strings if * they cannot be read. */ -static void cciss_get_device_descr(int ctlr, int logvol, +static void cciss_get_device_descr(ctlr_info_t *h, int logvol, char *vendor, char *model, char *rev) { int rc; @@ -1797,8 +1839,8 @@ static void cciss_get_device_descr(int ctlr, int logvol, if (!inq_buf) return; - log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol); - rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf, sizeof(*inq_buf), 0, + log_unit_to_scsi3addr(h, scsi3addr, logvol); + rc = sendcmd_withirq(h, CISS_INQUIRY, inq_buf, sizeof(*inq_buf), 0, scsi3addr, TYPE_CMD); if (rc == IO_OK) { memcpy(vendor, &inq_buf->data_byte[8], VENDOR_LEN); @@ -1818,7 +1860,7 @@ static void cciss_get_device_descr(int ctlr, int logvol, * number cannot be had, for whatever reason, 16 bytes of 0xff * are returned instead. */ -static void cciss_get_serial_no(int ctlr, int logvol, +static void cciss_get_serial_no(ctlr_info_t *h, int logvol, unsigned char *serial_no, int buflen) { #define PAGE_83_INQ_BYTES 64 @@ -1833,8 +1875,8 @@ static void cciss_get_serial_no(int ctlr, int logvol, if (!buf) return; memset(serial_no, 0, buflen); - log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol); - rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf, + log_unit_to_scsi3addr(h, scsi3addr, logvol); + rc = sendcmd_withirq(h, CISS_INQUIRY, buf, PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD); if (rc == IO_OK) memcpy(serial_no, &buf[8], buflen); @@ -1900,10 +1942,9 @@ init_queue_failure: * is also the contr |