aboutsummaryrefslogtreecommitdiff
path: root/drivers/block/cpqarray.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cpqarray.c')
-rw-r--r--drivers/block/cpqarray.c356
1 files changed, 162 insertions, 194 deletions
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 862b9abac0a..2b944038453 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -19,7 +19,6 @@
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
*
*/
-#include <linux/config.h> /* CONFIG_PROC_FS */
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -33,12 +32,14 @@
#include <linux/blkpg.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/seq_file.h>
#include <linux/init.h>
#include <linux/hdreg.h>
+#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
+#include <linux/scatterlist.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -67,6 +68,7 @@ MODULE_LICENSE("GPL");
#define CPQARRAY_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
+static DEFINE_MUTEX(cpqarray_mutex);
static int nr_ctlr;
static ctlr_info_t *hba[MAX_CTLR];
@@ -157,21 +159,20 @@ static int sendcmd(
unsigned int blkcnt,
unsigned int log_unit );
-static int ida_open(struct inode *inode, struct file *filep);
-static int ida_release(struct inode *inode, struct file *filep);
-static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
+static int ida_unlocked_open(struct block_device *bdev, fmode_t mode);
+static void ida_release(struct gendisk *disk, fmode_t mode);
+static int ida_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg);
static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
-static void do_ida_request(request_queue_t *q);
+static void do_ida_request(struct request_queue *q);
static void start_io(ctlr_info_t *h);
static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c);
-static inline void complete_buffers(struct bio *bio, int ok);
static inline void complete_command(cmdlist_t *cmd, int timeout);
-static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t do_ida_intr(int irq, void *dev_id);
static void ida_timer(unsigned long tdata);
static int ida_revalidate(struct gendisk *disk);
static int revalidate_allvol(ctlr_info_t *host);
@@ -179,7 +180,6 @@ static int cpqarray_register_ctlr(int ctlr, struct pci_dev *pdev);
#ifdef CONFIG_PROC_FS
static void ida_procinit(int i);
-static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
#else
static void ida_procinit(int i) {}
#endif
@@ -195,9 +195,9 @@ static inline ctlr_info_t *get_host(struct gendisk *disk)
}
-static struct block_device_operations ida_fops = {
+static const struct block_device_operations ida_fops = {
.owner = THIS_MODULE,
- .open = ida_open,
+ .open = ida_unlocked_open,
.release = ida_release,
.ioctl = ida_ioctl,
.getgeo = ida_getgeo,
@@ -208,6 +208,7 @@ static struct block_device_operations ida_fops = {
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_array;
+static const struct file_operations ida_proc_fops;
/*
* Get us a file in /proc/array that says something about each controller.
@@ -216,23 +217,20 @@ static struct proc_dir_entry *proc_array;
static void __init ida_procinit(int i)
{
if (proc_array == NULL) {
- proc_array = proc_mkdir("cpqarray", proc_root_driver);
+ proc_array = proc_mkdir("driver/cpqarray", NULL);
if (!proc_array) return;
}
- create_proc_read_entry(hba[i]->devname, 0, proc_array,
- ida_proc_get_info, hba[i]);
+ proc_create_data(hba[i]->devname, 0, proc_array, &ida_proc_fops, hba[i]);
}
/*
* Report information about this controller.
*/
-static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+static int ida_proc_show(struct seq_file *m, void *v)
{
- off_t pos = 0;
- off_t len = 0;
- int size, i, ctlr;
- ctlr_info_t *h = (ctlr_info_t*)data;
+ int i, ctlr;
+ ctlr_info_t *h = (ctlr_info_t*)m->private;
drv_info_t *drv;
#ifdef CPQ_PROC_PRINT_QUEUES
cmdlist_t *c;
@@ -240,7 +238,7 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset, int lengt
#endif
ctlr = h->ctlr;
- size = sprintf(buffer, "%s: Compaq %s Controller\n"
+ seq_printf(m, "%s: Compaq %s Controller\n"
" Board ID: 0x%08lx\n"
" Firmware Revision: %c%c%c%c\n"
" Controller Sig: 0x%08lx\n"
@@ -260,55 +258,54 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset, int lengt
h->log_drives, h->phys_drives,
h->Qdepth, h->maxQsinceinit);
- pos += size; len += size;
-
- size = sprintf(buffer+len, "Logical Drive Info:\n");
- pos += size; len += size;
+ seq_puts(m, "Logical Drive Info:\n");
for(i=0; i<h->log_drives; i++) {
drv = &h->drv[i];
- size = sprintf(buffer+len, "ida/c%dd%d: blksz=%d nr_blks=%d\n",
+ seq_printf(m, "ida/c%dd%d: blksz=%d nr_blks=%d\n",
ctlr, i, drv->blk_size, drv->nr_blks);
- pos += size; len += size;
}
#ifdef CPQ_PROC_PRINT_QUEUES
spin_lock_irqsave(IDA_LOCK(h->ctlr), flags);
- size = sprintf(buffer+len, "\nCurrent Queues:\n");
- pos += size; len += size;
+ seq_puts(m, "\nCurrent Queues:\n");
c = h->reqQ;
- size = sprintf(buffer+len, "reqQ = %p", c); pos += size; len += size;
+ seq_printf(m, "reqQ = %p", c);
if (c) c=c->next;
while(c && c != h->reqQ) {
- size = sprintf(buffer+len, "->%p", c);
- pos += size; len += size;
+ seq_printf(m, "->%p", c);
c=c->next;
}
c = h->cmpQ;
- size = sprintf(buffer+len, "\ncmpQ = %p", c); pos += size; len += size;
+ seq_printf(m, "\ncmpQ = %p", c);
if (c) c=c->next;
while(c && c != h->cmpQ) {
- size = sprintf(buffer+len, "->%p", c);
- pos += size; len += size;
+ seq_printf(m, "->%p", c);
c=c->next;
}
- size = sprintf(buffer+len, "\n"); pos += size; len += size;
+ seq_putc(m, '\n');
spin_unlock_irqrestore(IDA_LOCK(h->ctlr), flags);
#endif
- size = sprintf(buffer+len, "nr_allocs = %d\nnr_frees = %d\n",
+ seq_printf(m, "nr_allocs = %d\nnr_frees = %d\n",
h->nr_allocs, h->nr_frees);
- pos += size; len += size;
-
- *eof = 1;
- *start = buffer+offset;
- len -= offset;
- if (len>length)
- len = length;
- return len;
+ return 0;
+}
+
+static int ida_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ida_proc_show, PDE_DATA(inode));
}
+
+static const struct file_operations ida_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = ida_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif /* CONFIG_PROC_FS */
module_param_array(eisa, int, NULL, 0);
@@ -323,7 +320,7 @@ static void release_io_mem(ctlr_info_t *c)
c->io_mem_length = 0;
}
-static void __devexit cpqarray_remove_one(int i)
+static void cpqarray_remove_one(int i)
{
int j;
char buff[4];
@@ -348,7 +345,6 @@ static void __devexit cpqarray_remove_one(int i)
for(j = 0; j < NWD; j++) {
if (ida_gendisk[i][j]->flags & GENHD_FL_UP)
del_gendisk(ida_gendisk[i][j]);
- devfs_remove("ida/c%dd%d",i,j);
put_disk(ida_gendisk[i][j]);
}
blk_cleanup_queue(hba[i]->queue);
@@ -356,7 +352,7 @@ static void __devexit cpqarray_remove_one(int i)
free_hba(i);
}
-static void __devexit cpqarray_remove_one_pci (struct pci_dev *pdev)
+static void cpqarray_remove_one_pci(struct pci_dev *pdev)
{
int i;
ctlr_info_t *tmp_ptr;
@@ -381,7 +377,7 @@ static void __devexit cpqarray_remove_one_pci (struct pci_dev *pdev)
/* removing an instance that was not removed automatically..
* must be an eisa card.
*/
-static void __devexit cpqarray_remove_one_eisa (int i)
+static void cpqarray_remove_one_eisa(int i)
{
if (hba[i] == NULL) {
printk(KERN_ERR "cpqarray: controller %d appears to have"
@@ -392,9 +388,9 @@ static void __devexit cpqarray_remove_one_eisa (int i)
}
/* pdev is NULL for eisa */
-static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int cpqarray_register_ctlr(int i, struct pci_dev *pdev)
{
- request_queue_t *q;
+ struct request_queue *q;
int j;
/*
@@ -410,8 +406,7 @@ static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
}
hba[i]->access.set_intr_mask(hba[i], 0);
if (request_irq(hba[i]->intr, do_ida_intr,
- SA_INTERRUPT|SA_SHIRQ|SA_SAMPLE_RANDOM,
- hba[i]->devname, hba[i]))
+ IRQF_DISABLED|IRQF_SHARED, hba[i]->devname, hba[i]))
{
printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n",
hba[i]->intr, hba[i]->devname);
@@ -424,18 +419,17 @@ static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
goto Enomem2;
}
- hba[i]->cmd_pool = (cmdlist_t *)pci_alloc_consistent(
+ hba[i]->cmd_pool = pci_alloc_consistent(
hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t),
&(hba[i]->cmd_pool_dhandle));
- hba[i]->cmd_pool_bits = kmalloc(
- ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long),
+ hba[i]->cmd_pool_bits = kcalloc(
+ DIV_ROUND_UP(NR_CMDS, BITS_PER_LONG), sizeof(unsigned long),
GFP_KERNEL);
if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool)
goto Enomem1;
memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));
- memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long));
printk(KERN_INFO "cpqarray: Finding drives on %s",
hba[i]->devname);
@@ -456,11 +450,8 @@ static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
blk_queue_bounce_limit(q, hba[i]->pci_dev->dma_mask);
/* This is a hardware imposed limit. */
- blk_queue_max_hw_segments(q, SG_MAX);
+ blk_queue_max_segments(q, SG_MAX);
- /* This is a driver limit and could be eliminated. */
- blk_queue_max_phys_segments(q, SG_MAX);
-
init_timer(&hba[i]->timer);
hba[i]->timer.expires = jiffies + IDA_TIMER;
hba[i]->timer.data = (unsigned long)hba[i];
@@ -479,7 +470,7 @@ static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
disk->fops = &ida_fops;
if (j && !drv->nr_blks)
continue;
- blk_queue_hardsect_size(hba[i]->queue, drv->blk_size);
+ blk_queue_logical_block_size(hba[i]->queue, drv->blk_size);
set_capacity(disk, drv->nr_blks);
disk->queue = hba[i]->queue;
disk->private_data = drv;
@@ -514,8 +505,8 @@ Enomem4:
return -1;
}
-static int __init cpqarray_init_one( struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int cpqarray_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
int i;
@@ -545,7 +536,7 @@ static int __init cpqarray_init_one( struct pci_dev *pdev,
static struct pci_driver cpqarray_pci_driver = {
.name = "cpqarray",
.probe = cpqarray_init_one,
- .remove = __devexit_p(cpqarray_remove_one_pci),
+ .remove = cpqarray_remove_one_pci,
.id_table = cpqarray_pci_device_id,
};
@@ -572,7 +563,12 @@ static int __init cpqarray_init(void)
num_cntlrs_reg++;
}
- return(num_cntlrs_reg);
+ if (num_cntlrs_reg)
+ return 0;
+ else {
+ pci_unregister_driver(&cpqarray_pci_driver);
+ return -ENODEV;
+ }
}
/* Function to find the first free pointer into our hba[] array */
@@ -617,12 +613,14 @@ static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
int i;
c->pci_dev = pdev;
+ pci_set_master(pdev);
if (pci_enable_device(pdev)) {
printk(KERN_ERR "cpqarray: Unable to Enable PCI device\n");
return -1;
}
vendor_id = pdev->vendor;
device_id = pdev->device;
+ revision = pdev->revision;
irq = pdev->irq;
for(i=0; i<6; i++)
@@ -635,7 +633,6 @@ static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
}
pci_read_config_word(pdev, PCI_COMMAND, &command);
- pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
@@ -823,12 +820,12 @@ DBGINFO(
/*
* Open. Make sure the device is really there.
*/
-static int ida_open(struct inode *inode, struct file *filep)
+static int ida_open(struct block_device *bdev, fmode_t mode)
{
- drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+ drv_info_t *drv = get_drv(bdev->bd_disk);
+ ctlr_info_t *host = get_host(bdev->bd_disk);
- DBGINFO(printk("ida_open %s\n", inode->i_bdev->bd_disk->disk_name));
+ DBGINFO(printk("ida_open %s\n", bdev->bd_disk->disk_name));
/*
* Root is allowed to open raw volume zero even if it's not configured
* so array config can still work. I don't think I really like this,
@@ -845,14 +842,28 @@ static int ida_open(struct inode *inode, struct file *filep)
return 0;
}
+static int ida_unlocked_open(struct block_device *bdev, fmode_t mode)
+{
+ int ret;
+
+ mutex_lock(&cpqarray_mutex);
+ ret = ida_open(bdev, mode);
+ mutex_unlock(&cpqarray_mutex);
+
+ return ret;
+}
+
/*
* Close. Sync first.
*/
-static int ida_release(struct inode *inode, struct file *filep)
+static void ida_release(struct gendisk *disk, fmode_t mode)
{
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+ ctlr_info_t *host;
+
+ mutex_lock(&cpqarray_mutex);
+ host = get_host(disk);
host->usage_count--;
- return 0;
+ mutex_unlock(&cpqarray_mutex);
}
/*
@@ -890,7 +901,7 @@ static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c)
* are in here (either via the dummy do_ida_request functions or by being
* called from the interrupt handler
*/
-static void do_ida_request(request_queue_t *q)
+static void do_ida_request(struct request_queue *q)
{
ctlr_info_t *h = q->queuedata;
cmdlist_t *c;
@@ -898,32 +909,30 @@ static void do_ida_request(request_queue_t *q)
struct scatterlist tmp_sg[SG_MAX];
int i, dir, seg;
- if (blk_queue_plugged(q))
- goto startio;
-
queue_next:
- creq = elv_next_request(q);
+ creq = blk_peek_request(q);
if (!creq)
goto startio;
- if (creq->nr_phys_segments > SG_MAX)
- BUG();
+ BUG_ON(creq->nr_phys_segments > SG_MAX);
if ((c = cmd_alloc(h,1)) == NULL)
goto startio;
- blkdev_dequeue_request(creq);
+ blk_start_request(creq);
c->ctlr = h->ctlr;
c->hdr.unit = (drv_info_t *)(creq->rq_disk->private_data) - h->drv;
c->hdr.size = sizeof(rblk_t) >> 2;
c->size += sizeof(rblk_t);
- c->req.hdr.blk = creq->sector;
+ c->req.hdr.blk = blk_rq_pos(creq);
c->rq = creq;
DBGPX(
- printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors);
+ printk("sector=%d, nr_sectors=%u\n",
+ blk_rq_pos(creq), blk_rq_sectors(creq));
);
+ sg_init_table(tmp_sg, SG_MAX);
seg = blk_rq_map_sg(q, creq, tmp_sg);
/* Now do all the DMA Mappings */
@@ -935,13 +944,13 @@ DBGPX(
{
c->req.sg[i].size = tmp_sg[i].length;
c->req.sg[i].addr = (__u32) pci_map_page(h->pci_dev,
- tmp_sg[i].page,
+ sg_page(&tmp_sg[i]),
tmp_sg[i].offset,
tmp_sg[i].length, dir);
}
-DBGPX( printk("Submitting %d sectors in %d segments\n", creq->nr_sectors, seg); );
+DBGPX( printk("Submitting %u sectors in %d segments\n", blk_rq_sectors(creq), seg); );
c->req.hdr.sg_cnt = seg;
- c->req.hdr.blk_cnt = creq->nr_sectors;
+ c->req.hdr.blk_cnt = blk_rq_sectors(creq);
c->req.hdr.cmd = (rq_data_dir(creq) == READ) ? IDA_READ : IDA_WRITE;
c->type = CMD_RWREQ;
@@ -984,27 +993,13 @@ static void start_io(ctlr_info_t *h)
}
}
-static inline void complete_buffers(struct bio *bio, int ok)
-{
- struct bio *xbh;
- while(bio) {
- int nr_sectors = bio_sectors(bio);
-
- xbh = bio->bi_next;
- bio->bi_next = NULL;
-
- blk_finished_io(nr_sectors);
- bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO);
-
- bio = xbh;
- }
-}
/*
* Mark all buffers that cmd was responsible for
*/
static inline void complete_command(cmdlist_t *cmd, int timeout)
{
- int ok=1;
+ struct request *rq = cmd->rq;
+ int error = 0;
int i, ddir;
if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
@@ -1016,16 +1011,17 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
if (cmd->req.hdr.rcode & RCODE_FATAL) {
printk(KERN_WARNING "Fatal error on ida/c%dd%d\n",
cmd->ctlr, cmd->hdr.unit);
- ok = 0;
+ error = -EIO;
}
if (cmd->req.hdr.rcode & RCODE_INVREQ) {
printk(KERN_WARNING "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n",
cmd->ctlr, cmd->hdr.unit, cmd->req.hdr.cmd,
cmd->req.hdr.blk, cmd->req.hdr.blk_cnt,
cmd->req.hdr.sg_cnt, cmd->req.hdr.rcode);
- ok = 0;
+ error = -EIO;
}
- if (timeout) ok = 0;
+ if (timeout)
+ error = -EIO;
/* unmap the DMA mapping for all the scatter gather elements */
if (cmd->req.hdr.cmd == IDA_READ)
ddir = PCI_DMA_FROMDEVICE;
@@ -1035,10 +1031,8 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
pci_unmap_page(hba[cmd->ctlr]->pci_dev, cmd->req.sg[i].addr,
cmd->req.sg[i].size, ddir);
- complete_buffers(cmd->rq->bio, ok);
-
- DBGPX(printk("Done with %p\n", cmd->rq););
- end_that_request_last(cmd->rq, ok ? 1 : -EIO);
+ DBGPX(printk("Done with %p\n", rq););
+ __blk_end_request_all(rq, error);
}
/*
@@ -1046,7 +1040,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
* Find the command on the completion queue, remove it, tell the OS and
* try to queue up more IO
*/
-static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t do_ida_intr(int irq, void *dev_id)
{
ctlr_info_t *h = dev_id;
cmdlist_t *c;
@@ -1147,10 +1141,10 @@ static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo)
* ida_ioctl does some miscellaneous stuff like reporting drive geometry,
* setting readahead and submitting commands from userspace to the controller.
*/
-static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
+static int ida_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
- drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+ drv_info_t *drv = get_drv(bdev->bd_disk);
+ ctlr_info_t *host = get_host(bdev->bd_disk);
int error;
ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg;
ida_ioctl_t *my_io;
@@ -1181,15 +1175,17 @@ out_passthru:
return error;
case IDAGETCTLRSIG:
if (!arg) return -EINVAL;
- put_user(host->ctlr_sig, (int __user *)arg);
+ if (put_user(host->ctlr_sig, (int __user *)arg))
+ return -EFAULT;
return 0;
case IDAREVALIDATEVOLS:
- if (iminor(inode) != 0)
+ if (MINOR(bdev->bd_dev) != 0)
return -ENXIO;
return revalidate_allvol(host);
case IDADRIVERVERSION:
if (!arg) return -EINVAL;
- put_user(DRIVER_VERSION, (unsigned long __user *)arg);
+ if (put_user(DRIVER_VERSION, (unsigned long __user *)arg))
+ return -EFAULT;
return 0;
case IDAGETPCIINFO:
{
@@ -1197,6 +1193,7 @@ out_passthru:
ida_pci_info_struct pciinfo;
if (!arg) return -EINVAL;
+ memset(&pciinfo, 0, sizeof(pciinfo));
pciinfo.bus = host->pci_dev->bus->number;
pciinfo.dev_fn = host->pci_dev->devfn;
pciinfo.board_id = host->board_id;
@@ -1211,6 +1208,19 @@ out_passthru:
}
}
+
+static int ida_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long param)
+{
+ int ret;
+
+ mutex_lock(&cpqarray_mutex);
+ ret = ida_locked_ioctl(bdev, mode, cmd, param);
+ mutex_unlock(&cpqarray_mutex);
+
+ return ret;
+}
+
/*
* ida_ctlr_ioctl is for passing commands to the controller from userspace.
* The command block (io) has already been copied to kernel space for us,
@@ -1244,17 +1254,11 @@ static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io)
/* Pre submit processing */
switch(io->cmd) {
case PASSTHRU_A:
- p = kmalloc(io->sg[0].size, GFP_KERNEL);
- if (!p)
- {
- error = -ENOMEM;
- cmd_free(h, c, 0);
- return(error);
- }
- if (copy_from_user(p, io->sg[0].addr, io->sg[0].size)) {
- kfree(p);
- cmd_free(h, c, 0);
- return -EFAULT;
+ p = memdup_user(io->sg[0].addr, io->sg[0].size);
+ if (IS_ERR(p)) {
+ error = PTR_ERR(p);
+ cmd_free(h, c, 0);
+ return error;
}
c->req.hdr.blk = pci_map_single(h->pci_dev, &(io->c),
sizeof(ida_ioctl_t),
@@ -1285,18 +1289,12 @@ static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io)
case DIAG_PASS_THRU:
case COLLECT_BUFFER:
case WRITE_FLASH_ROM:
- p = kmalloc(io->sg[0].size, GFP_KERNEL);
- if (!p)
- {
- error = -ENOMEM;
- cmd_free(h, c, 0);
- return(error);
+ p = memdup_user(io->sg[0].addr, io->sg[0].size);
+ if (IS_ERR(p)) {
+ error = PTR_ERR(p);
+ cmd_free(h, c, 0);
+ return error;
}
- if (copy_from_user(p, io->sg[0].addr, io->sg[0].size)) {
- kfree(p);
- cmd_free(h, c, 0);
- return -EFAULT;
- }
c->req.sg[0].size = io->sg[0].size;
c->req.sg[0].addr = pci_map_single(h->pci_dev, p,
c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
@@ -1559,7 +1557,7 @@ static int revalidate_allvol(ctlr_info_t *host)
drv_info_t *drv = &host->drv[i];
if (i && !drv->nr_blks)
continue;
- blk_queue_hardsect_size(host->queue, drv->blk_size);
+ blk_queue_logical_block_size(host->queue, drv->blk_size);
set_capacity(disk, drv->nr_blks);
disk->queue = host->queue;
disk->private_data = drv;
@@ -1622,7 +1620,7 @@ static void start_fwbk(int ctlr)
" processing\n");
/* Command does not return anything, but idasend command needs a
buffer */
- id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+ id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
if(id_ctlr_buf==NULL)
{
printk(KERN_WARNING "cpqarray: Out of memory. "
@@ -1657,45 +1655,30 @@ static void getgeometry(int ctlr)
info_p->log_drv_map = 0;
- id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
- if(id_ldrive == NULL)
- {
+ id_ldrive = kzalloc(sizeof(id_log_drv_t), GFP_KERNEL);
+ if (!id_ldrive) {
printk( KERN_ERR "cpqarray: out of memory.\n");
- return;
+ goto err_0;
}
- id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
- if(id_ctlr_buf == NULL)
- {
- kfree(id_ldrive);
+ id_ctlr_buf = kzalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+ if (!id_ctlr_buf) {
printk( KERN_ERR "cpqarray: out of memory.\n");
- return;
+ goto err_1;
}
- id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
- if(id_lstatus_buf == NULL)
- {
- kfree(id_ctlr_buf);
- kfree(id_ldrive);
+ id_lstatus_buf = kzalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
+ if (!id_lstatus_buf) {
printk( KERN_ERR "cpqarray: out of memory.\n");
- return;
+ goto err_2;
}
- sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL);
- if(sense_config_buf == NULL)
- {
- kfree(id_lstatus_buf);
- kfree(id_ctlr_buf);
- kfree(id_ldrive);
+ sense_config_buf = kzalloc(sizeof(config_t), GFP_KERNEL);
+ if (!sense_config_buf) {
printk( KERN_ERR "cpqarray: out of memory.\n");
- return;
+ goto err_3;
}
- memset(id_ldrive, 0, sizeof(id_log_drv_t));
- memset(id_ctlr_buf, 0, sizeof(id_ctlr_t));
- memset(id_lstatus_buf, 0, sizeof(sense_log_drv_stat_t));
- memset(sense_config_buf, 0, sizeof(config_t));
-
info_p->phys_drives = 0;
info_p->log_drv_map = 0;
info_p->drv_assign_map = 0;
@@ -1709,13 +1692,8 @@ static void getgeometry(int ctlr)
* so the idastubopen will fail on all logical drives
* on the controller.
*/
- /* Free all the buffers and return */
printk(KERN_ERR "cpqarray: error sending ID controller\n");
- kfree(sense_config_buf);
- kfree(id_lstatus_buf);
- kfree(id_ctlr_buf);
- kfree(id_ldrive);
- return;
+ goto err_4;
}
info_p->log_drives = id_ctlr_buf->nr_drvs;
@@ -1741,8 +1719,6 @@ static void getgeometry(int ctlr)
(log_index < id_ctlr_buf->nr_drvs)
&& (log_unit < NWD);
log_unit++) {
- struct gendisk *disk = ida_gendisk[ctlr][log_unit];
-
size = sizeof(sense_log_drv_stat_t);
/*
@@ -1763,12 +1739,7 @@ static void getgeometry(int ctlr)
" failed to report status of logical drive %d\n"
"Access to this controller has been disabled\n",
ctlr, log_unit);
- /* Free all the buffers and return */
- kfree(sense_config_buf);
- kfree(id_lstatus_buf);
- kfree(id_ctlr_buf);
- kfree(id_ldrive);
- return;
+ goto err_4;
}
/*
Make sure the logical drive is configured
@@ -1797,18 +1768,10 @@ static void getgeometry(int ctlr)
sizeof(config_t), 0, 0, log_unit);
if (ret_code == IO_ERROR) {
info_p->log_drv_map = 0;
- /* Free all the buffers and return */
printk(KERN_ERR "cpqarray: error sending sense config\n");
- kfree(sense_config_buf);
- kfree(id_lstatus_buf);
- kfree(id_ctlr_buf);
- kfree(id_ldrive);
- return;
-
+ goto err_4;
}
- sprintf(disk->devfs_name, "ida/c%dd%d", ctlr, log_unit);
-
info_p->phys_drives =
sense_config_buf->ctlr_phys_drv;
info_p->drv_assign_map
@@ -1821,12 +1784,18 @@ static void getgeometry(int ctlr)
log_index = log_index + 1;
} /* end of if logical drive configured */
} /* end of for log_unit */
+
+ /* Free all the buffers and return */
+err_4:
kfree(sense_config_buf);
- kfree(id_ldrive);
+err_3:
kfree(id_lstatus_buf);
+err_2:
kfree(id_ctlr_buf);
+err_1:
+ kfree(id_ldrive);
+err_0:
return;
-
}
static void __exit cpqarray_exit(void)
@@ -1844,8 +1813,7 @@ static void __exit cpqarray_exit(void)
}
}
- devfs_remove("ida");
- remove_proc_entry("cpqarray", proc_root_driver);
+ remove_proc_entry("driver/cpqarray", NULL);
}
module_init(cpqarray_init)