2010-08-26 18:49:23

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 00/13] cciss: clean up cciss_ioctl()

This series of patches factors out all of cases of the giant
switch statement in cciss_ioctl into separate functions. And
there's one patch at the end that gets rid of some superfluous
if statements in the big passthru path.

I've run test programs that exercise all these ioctls and they
appear to still work.
---

Stephen M. Cameron (13):
cciss: factor out cciss_getpciinfo
cciss: factor out cciss_getintinfo
cciss: factor out cciss_setintinfo
cciss: factor out cciss_getnodename
cciss: factor out cciss_setnodename
cciss: factor out cciss_getheartbeat
cciss: factor out cciss_getbustypes
cciss: factor out cciss_getfirmver
cciss: factor out cciss_getdrivver
cciss: factor out cciss_getluninfo
cciss: factor out cciss_passthru
cciss: factor out cciss_big_passthru
cciss: remove some superfluous tests from cciss_bigpassthru()


drivers/block/cciss.c | 842 ++++++++++++++++++++++++-------------------------
1 files changed, 412 insertions(+), 430 deletions(-)

--
-- steve


2010-08-26 18:49:32

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 01/13] cciss: factor out cciss_getpciinfo

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 34 +++++++++++++++++-----------------
1 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index eef94fa..c1eca37 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1232,9 +1232,22 @@ static void check_ioctl_unit_attention(ctlr_info_t *h, CommandList_struct *c)
c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
(void)check_for_unit_attention(h, c);
}
-/*
- * ioctl
- */
+
+static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp)
+{
+ cciss_pci_info_struct pciinfo;
+
+ if (!argp)
+ return -EINVAL;
+ 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;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1247,20 +1260,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
cmd, arg);
switch (cmd) {
case CCISS_GETPCIINFO:
- {
- cciss_pci_info_struct pciinfo;
-
- if (!arg)
- return -EINVAL;
- 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;
- return 0;
- }
+ return cciss_getpciinfo(h, argp);
case CCISS_GETINTINFO:
{
cciss_coalint_struct intinfo;

2010-08-26 18:49:37

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 02/13] cciss: factor out cciss_getintinfo

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 28 +++++++++++++++-------------
1 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index c1eca37..14380c4 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1248,6 +1248,20 @@ static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
+{
+ cciss_coalint_struct intinfo;
+
+ if (!argp)
+ return -EINVAL;
+ intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay);
+ intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount);
+ if (copy_to_user
+ (argp, &intinfo, sizeof(cciss_coalint_struct)))
+ return -EFAULT;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1262,19 +1276,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_GETPCIINFO:
return cciss_getpciinfo(h, argp);
case CCISS_GETINTINFO:
- {
- cciss_coalint_struct intinfo;
- if (!arg)
- return -EINVAL;
- intinfo.delay =
- readl(&h->cfgtable->HostWrite.CoalIntDelay);
- intinfo.count =
- readl(&h->cfgtable->HostWrite.CoalIntCount);
- if (copy_to_user
- (argp, &intinfo, sizeof(cciss_coalint_struct)))
- return -EFAULT;
- return 0;
- }
+ return cciss_getintinfo(h, argp);
case CCISS_SETINTINFO:
{
cciss_coalint_struct intinfo;

2010-08-26 18:49:44

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 04/13] cciss: factor out cciss_getnodename

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 28 +++++++++++++++-------------
1 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5ff5a1d..77db6ea 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1293,6 +1293,20 @@ static int cciss_setintinfo(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
+{
+ NodeName_type NodeName;
+ int i;
+
+ if (!argp)
+ return -EINVAL;
+ for (i = 0; i < 16; i++)
+ NodeName[i] = readb(&h->cfgtable->ServerName[i]);
+ if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
+ return -EFAULT;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1311,19 +1325,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_SETINTINFO:
return cciss_setintinfo(h, argp);
case CCISS_GETNODENAME:
- {
- NodeName_type NodeName;
- int i;
-
- if (!arg)
- return -EINVAL;
- for (i = 0; i < 16; i++)
- NodeName[i] =
- readb(&h->cfgtable->ServerName[i]);
- if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
- return -EFAULT;
- return 0;
- }
+ return cciss_getnodename(h, argp);
case CCISS_SETNODENAME:
{
NodeName_type NodeName;

2010-08-26 18:49:52

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 05/13] cciss: factor out cciss_setnodename

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 65 ++++++++++++++++++++++---------------------------
1 files changed, 29 insertions(+), 36 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 77db6ea..90c1906 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1307,6 +1307,34 @@ static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_setnodename(ctlr_info_t *h, void __user *argp)
+{
+ NodeName_type NodeName;
+ unsigned long flags;
+ int i;
+
+ if (!argp)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user(NodeName, argp, sizeof(NodeName_type)))
+ return -EFAULT;
+ spin_lock_irqsave(&h->lock, flags);
+ /* Update the field, and then ring the doorbell */
+ for (i = 0; i < 16; i++)
+ writeb(NodeName[i], &h->cfgtable->ServerName[i]);
+ writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+ for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+ if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+ break;
+ udelay(1000); /* delay and try again */
+ }
+ spin_unlock_irqrestore(&h->lock, flags);
+ if (i >= MAX_IOCTL_CONFIG_WAIT)
+ return -EAGAIN;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1327,42 +1355,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_GETNODENAME:
return cciss_getnodename(h, argp);
case CCISS_SETNODENAME:
- {
- NodeName_type NodeName;
- unsigned long flags;
- int i;
-
- if (!arg)
- return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (copy_from_user
- (NodeName, argp, sizeof(NodeName_type)))
- return -EFAULT;
-
- spin_lock_irqsave(&h->lock, flags);
-
- /* Update the field, and then ring the doorbell */
- for (i = 0; i < 16; i++)
- writeb(NodeName[i],
- &h->cfgtable->ServerName[i]);
-
- writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-
- for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
- if (!(readl(h->vaddr + SA5_DOORBELL)
- & CFGTBL_ChangeReq))
- break;
- /* delay and try again */
- udelay(1000);
- }
- spin_unlock_irqrestore(&h->lock, flags);
- if (i >= MAX_IOCTL_CONFIG_WAIT)
- return -EAGAIN;
- return 0;
- }
-
+ return cciss_setnodename(h, argp);
case CCISS_GETHEARTBEAT:
{
Heartbeat_type heartbeat;

2010-08-26 18:49:55

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 06/13] cciss: factor out cciss_getheartbeat

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 24 +++++++++++++-----------
1 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 90c1906..d9d2e5a 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1335,6 +1335,18 @@ static int cciss_setnodename(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
+{
+ Heartbeat_type heartbeat;
+
+ if (!argp)
+ return -EINVAL;
+ heartbeat = readl(&h->cfgtable->HeartBeat);
+ if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type)))
+ return -EFAULT;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1357,17 +1369,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_SETNODENAME:
return cciss_setnodename(h, argp);
case CCISS_GETHEARTBEAT:
- {
- Heartbeat_type heartbeat;
-
- if (!arg)
- return -EINVAL;
- heartbeat = readl(&h->cfgtable->HeartBeat);
- if (copy_to_user
- (argp, &heartbeat, sizeof(Heartbeat_type)))
- return -EFAULT;
- return 0;
- }
+ return cciss_getheartbeat(h, argp);
case CCISS_GETBUSTYPES:
{
BusTypes_type BusTypes;

2010-08-26 18:50:00

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 07/13] cciss: factor out cciss_getbustypes

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 24 +++++++++++++-----------
1 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index d9d2e5a..013d023 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1347,6 +1347,18 @@ static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
+{
+ BusTypes_type BusTypes;
+
+ if (!argp)
+ return -EINVAL;
+ BusTypes = readl(&h->cfgtable->BusTypes);
+ if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type)))
+ return -EFAULT;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1371,17 +1383,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_GETHEARTBEAT:
return cciss_getheartbeat(h, argp);
case CCISS_GETBUSTYPES:
- {
- BusTypes_type BusTypes;
-
- if (!arg)
- return -EINVAL;
- BusTypes = readl(&h->cfgtable->BusTypes);
- if (copy_to_user
- (argp, &BusTypes, sizeof(BusTypes_type)))
- return -EFAULT;
- return 0;
- }
+ return cciss_getbustypes(h, argp);
case CCISS_GETFIRMVER:
{
FirmwareVer_type firmware;

2010-08-26 18:50:12

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 09/13] cciss: factor out cciss_getdrivver

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 26 +++++++++++++-------------
1 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index c4790ba..6e915de 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1373,8 +1373,19 @@ static int cciss_getfirmver(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_getdrivver(ctlr_info_t *h, void __user *argp)
+{
+ DriverVer_type DriverVer = DRIVER_VERSION;
+
+ if (!argp)
+ return -EINVAL;
+ if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type)))
+ return -EFAULT;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct gendisk *disk = bdev->bd_disk;
ctlr_info_t *h = get_host(disk);
@@ -1401,18 +1412,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_GETFIRMVER:
return cciss_getfirmver(h, argp);
case CCISS_GETDRIVVER:
- {
- DriverVer_type DriverVer = DRIVER_VERSION;
-
- if (!arg)
- return -EINVAL;
-
- if (copy_to_user
- (argp, &DriverVer, sizeof(DriverVer_type)))
- return -EFAULT;
- return 0;
- }
-
+ return cciss_getdrivver(h, argp);
case CCISS_DEREGDISK:
case CCISS_REGNEWD:
case CCISS_REVALIDVOLS:

2010-08-26 18:50:15

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 10/13] cciss: factor out cciss_getluninfo

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 32 ++++++++++++++++++--------------
1 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 6e915de..3f24450 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1384,12 +1384,27 @@ static int cciss_getdrivver(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_getluninfo(ctlr_info_t *h,
+ struct gendisk *disk, void __user *argp)
+{
+ LogvolInfo_struct luninfo;
+ drive_info_struct *drv = get_drv(disk);
+
+ if (!argp)
+ return -EINVAL;
+ memcpy(&luninfo.LunID, drv->LunID, sizeof(luninfo.LunID));
+ luninfo.num_opens = drv->usage_count;
+ luninfo.num_parts = 0;
+ if (copy_to_user(argp, &luninfo, sizeof(LogvolInfo_struct)))
+ return -EFAULT;
+ return 0;
+}
+
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 *h = get_host(disk);
- drive_info_struct *drv = get_drv(disk);
void __user *argp = (void __user *)arg;

dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n",
@@ -1417,19 +1432,8 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_REGNEWD:
case CCISS_REVALIDVOLS:
return rebuild_lun_table(h, 0, 1);
-
- case CCISS_GETLUNINFO:{
- LogvolInfo_struct luninfo;
-
- memcpy(&luninfo.LunID, drv->LunID,
- sizeof(luninfo.LunID));
- luninfo.num_opens = drv->usage_count;
- luninfo.num_parts = 0;
- if (copy_to_user(argp, &luninfo,
- sizeof(LogvolInfo_struct)))
- return -EFAULT;
- return 0;
- }
+ case CCISS_GETLUNINFO:
+ return cciss_getluninfo(h, disk, argp);
case CCISS_PASSTHRU:
{
IOCTL_Command_struct iocommand;

2010-08-26 18:50:21

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 11/13] cciss: factor out cciss_passthru

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 212 +++++++++++++++++++++++--------------------------
1 files changed, 101 insertions(+), 111 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 3f24450..5a84080 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1400,6 +1400,106 @@ static int cciss_getluninfo(ctlr_info_t *h,
return 0;
}

+static int cciss_passthru(ctlr_info_t *h, void __user *argp)
+{
+ IOCTL_Command_struct iocommand;
+ CommandList_struct *c;
+ char *buff = NULL;
+ u64bit temp64;
+ DECLARE_COMPLETION_ONSTACK(wait);
+
+ if (!argp)
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ if (copy_from_user
+ (&iocommand, argp, sizeof(IOCTL_Command_struct)))
+ return -EFAULT;
+ if ((iocommand.buf_size < 1) &&
+ (iocommand.Request.Type.Direction != XFER_NONE)) {
+ return -EINVAL;
+ }
+ if (iocommand.buf_size > 0) {
+ buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+ if (buff == NULL)
+ return -EFAULT;
+ }
+ if (iocommand.Request.Type.Direction == XFER_WRITE) {
+ /* Copy the data into the buffer we created */
+ if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
+ kfree(buff);
+ return -EFAULT;
+ }
+ } else {
+ memset(buff, 0, iocommand.buf_size);
+ }
+ c = cmd_special_alloc(h);
+ if (!c) {
+ kfree(buff);
+ return -ENOMEM;
+ }
+ /* Fill in the command type */
+ c->cmd_type = CMD_IOCTL_PEND;
+ /* Fill in Command Header */
+ c->Header.ReplyQueue = 0; /* unused in simple mode */
+ if (iocommand.buf_size > 0) { /* buffer to fill */
+ c->Header.SGList = 1;
+ c->Header.SGTotal = 1;
+ } else { /* no buffers to fill */
+ c->Header.SGList = 0;
+ c->Header.SGTotal = 0;
+ }
+ c->Header.LUN = iocommand.LUN_info;
+ /* use the kernel address the cmd block for tag */
+ c->Header.Tag.lower = c->busaddr;
+
+ /* Fill in Request block */
+ c->Request = iocommand.Request;
+
+ /* Fill in the scatter gather information */
+ if (iocommand.buf_size > 0) {
+ temp64.val = pci_map_single(h->pdev, buff,
+ iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Addr.lower = temp64.val32.lower;
+ c->SG[0].Addr.upper = temp64.val32.upper;
+ c->SG[0].Len = iocommand.buf_size;
+ c->SG[0].Ext = 0; /* we are not chaining */
+ }
+ c->waiting = &wait;
+
+ 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(h->pdev, (dma_addr_t) temp64.val, iocommand.buf_size,
+ PCI_DMA_BIDIRECTIONAL);
+ 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_special_free(h, c);
+ return -EFAULT;
+ }
+
+ if (iocommand.Request.Type.Direction == XFER_READ) {
+ /* Copy the data out of the buffer we created */
+ if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
+ kfree(buff);
+ cmd_special_free(h, c);
+ return -EFAULT;
+ }
+ }
+ kfree(buff);
+ cmd_special_free(h, c);
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1435,117 +1535,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_GETLUNINFO:
return cciss_getluninfo(h, disk, argp);
case CCISS_PASSTHRU:
- {
- IOCTL_Command_struct iocommand;
- CommandList_struct *c;
- char *buff = NULL;
- u64bit temp64;
- DECLARE_COMPLETION_ONSTACK(wait);
-
- if (!arg)
- return -EINVAL;
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
-
- if (copy_from_user
- (&iocommand, argp, sizeof(IOCTL_Command_struct)))
- return -EFAULT;
- if ((iocommand.buf_size < 1) &&
- (iocommand.Request.Type.Direction != XFER_NONE)) {
- return -EINVAL;
- }
-#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
- /* Check kmalloc limits */
- if (iocommand.buf_size > 128000)
- return -EINVAL;
-#endif
- if (iocommand.buf_size > 0) {
- buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
- if (buff == NULL)
- return -EFAULT;
- }
- if (iocommand.Request.Type.Direction == XFER_WRITE) {
- /* Copy the data into the buffer we created */
- if (copy_from_user
- (buff, iocommand.buf, iocommand.buf_size)) {
- kfree(buff);
- return -EFAULT;
- }
- } else {
- memset(buff, 0, iocommand.buf_size);
- }
- c = cmd_special_alloc(h);
- if (!c) {
- kfree(buff);
- return -ENOMEM;
- }
- /* Fill in the command type */
- c->cmd_type = CMD_IOCTL_PEND;
- /* Fill in Command Header */
- c->Header.ReplyQueue = 0; /* unused in simple mode */
- if (iocommand.buf_size > 0) /* buffer to fill */
- {
- c->Header.SGList = 1;
- c->Header.SGTotal = 1;
- } else /* no buffers to fill */
- {
- c->Header.SGList = 0;
- c->Header.SGTotal = 0;
- }
- c->Header.LUN = iocommand.LUN_info;
- /* use the kernel address the cmd block for tag */
- c->Header.Tag.lower = c->busaddr;
-
- /* Fill in Request block */
- c->Request = iocommand.Request;
-
- /* Fill in the scatter gather information */
- if (iocommand.buf_size > 0) {
- temp64.val = pci_map_single(h->pdev, buff,
- iocommand.buf_size,
- PCI_DMA_BIDIRECTIONAL);
- c->SG[0].Addr.lower = temp64.val32.lower;
- c->SG[0].Addr.upper = temp64.val32.upper;
- c->SG[0].Len = iocommand.buf_size;
- c->SG[0].Ext = 0; /* we are not chaining */
- }
- c->waiting = &wait;
-
- 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(h->pdev, (dma_addr_t) temp64.val,
- iocommand.buf_size,
- PCI_DMA_BIDIRECTIONAL);
-
- 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_special_free(h, c);
- return -EFAULT;
- }
-
- if (iocommand.Request.Type.Direction == XFER_READ) {
- /* Copy the data out of the buffer we created */
- if (copy_to_user
- (iocommand.buf, buff, iocommand.buf_size)) {
- kfree(buff);
- cmd_special_free(h, c);
- return -EFAULT;
- }
- }
- kfree(buff);
- cmd_special_free(h, c);
- return 0;
- }
+ return cciss_passthru(h, argp);
case CCISS_BIG_PASSTHRU:{
BIG_IOCTL_Command_struct *ioc;
CommandList_struct *c;

2010-08-26 18:50:27

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 12/13] cciss: factor out cciss_big_passthru

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 307 ++++++++++++++++++++++++-------------------------
1 files changed, 151 insertions(+), 156 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5a84080..a7ec339 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1500,6 +1500,155 @@ static int cciss_passthru(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp)
+{
+ BIG_IOCTL_Command_struct *ioc;
+ CommandList_struct *c;
+ unsigned char **buff = NULL;
+ int *buff_size = NULL;
+ u64bit temp64;
+ BYTE sg_used = 0;
+ int status = 0;
+ int i;
+ DECLARE_COMPLETION_ONSTACK(wait);
+ __u32 left;
+ __u32 sz;
+ BYTE __user *data_ptr;
+
+ if (!argp)
+ return -EINVAL;
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ ioc = (BIG_IOCTL_Command_struct *)
+ kmalloc(sizeof(*ioc), GFP_KERNEL);
+ if (!ioc) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ if ((ioc->buf_size < 1) &&
+ (ioc->Request.Type.Direction != XFER_NONE)) {
+ status = -EINVAL;
+ goto cleanup1;
+ }
+ /* Check kmalloc limits using all SGs */
+ if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
+ status = -EINVAL;
+ goto cleanup1;
+ }
+ if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
+ status = -EINVAL;
+ goto cleanup1;
+ }
+ buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
+ if (!buff) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL);
+ if (!buff_size) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ left = ioc->buf_size;
+ data_ptr = ioc->buf;
+ while (left) {
+ sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
+ buff_size[sg_used] = sz;
+ buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+ if (buff[sg_used] == NULL) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ if (ioc->Request.Type.Direction == XFER_WRITE) {
+ if (copy_from_user(buff[sg_used], data_ptr, sz)) {
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ } else {
+ memset(buff[sg_used], 0, sz);
+ }
+ left -= sz;
+ data_ptr += sz;
+ sg_used++;
+ }
+ c = cmd_special_alloc(h);
+ if (!c) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ c->cmd_type = CMD_IOCTL_PEND;
+ c->Header.ReplyQueue = 0;
+
+ if (ioc->buf_size > 0) {
+ c->Header.SGList = sg_used;
+ c->Header.SGTotal = sg_used;
+ } else {
+ c->Header.SGList = 0;
+ c->Header.SGTotal = 0;
+ }
+ c->Header.LUN = ioc->LUN_info;
+ c->Header.Tag.lower = c->busaddr;
+
+ c->Request = ioc->Request;
+ if (ioc->buf_size > 0) {
+ for (i = 0; i < sg_used; i++) {
+ temp64.val =
+ pci_map_single(h->pdev, buff[i], buff_size[i],
+ PCI_DMA_BIDIRECTIONAL);
+ c->SG[i].Addr.lower = temp64.val32.lower;
+ c->SG[i].Addr.upper = temp64.val32.upper;
+ c->SG[i].Len = buff_size[i];
+ c->SG[i].Ext = 0; /* we are not chaining */
+ }
+ }
+ c->waiting = &wait;
+ 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(h->pdev,
+ (dma_addr_t) temp64.val, buff_size[i],
+ PCI_DMA_BIDIRECTIONAL);
+ }
+ 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_special_free(h, c);
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ if (ioc->Request.Type.Direction == XFER_READ) {
+ /* Copy the data out of the buffer we created */
+ BYTE __user *ptr = ioc->buf;
+ for (i = 0; i < sg_used; i++) {
+ if (copy_to_user(ptr, buff[i], buff_size[i])) {
+ cmd_special_free(h, c);
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ ptr += buff_size[i];
+ }
+ }
+ cmd_special_free(h, c);
+ status = 0;
+cleanup1:
+ if (buff) {
+ for (i = 0; i < sg_used; i++)
+ kfree(buff[i]);
+ kfree(buff);
+ }
+ kfree(buff_size);
+ kfree(ioc);
+ return status;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1536,162 +1685,8 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
return cciss_getluninfo(h, disk, argp);
case CCISS_PASSTHRU:
return cciss_passthru(h, argp);
- case CCISS_BIG_PASSTHRU:{
- BIG_IOCTL_Command_struct *ioc;
- CommandList_struct *c;
- unsigned char **buff = NULL;
- int *buff_size = NULL;
- u64bit temp64;
- BYTE sg_used = 0;
- int status = 0;
- int i;
- DECLARE_COMPLETION_ONSTACK(wait);
- __u32 left;
- __u32 sz;
- BYTE __user *data_ptr;
-
- if (!arg)
- return -EINVAL;
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- ioc = (BIG_IOCTL_Command_struct *)
- kmalloc(sizeof(*ioc), GFP_KERNEL);
- if (!ioc) {
- status = -ENOMEM;
- goto cleanup1;
- }
- if (copy_from_user(ioc, argp, sizeof(*ioc))) {
- status = -EFAULT;
- goto cleanup1;
- }
- if ((ioc->buf_size < 1) &&
- (ioc->Request.Type.Direction != XFER_NONE)) {
- status = -EINVAL;
- goto cleanup1;
- }
- /* Check kmalloc limits using all SGs */
- if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
- status = -EINVAL;
- goto cleanup1;
- }
- if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
- status = -EINVAL;
- goto cleanup1;
- }
- buff =
- kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
- if (!buff) {
- status = -ENOMEM;
- goto cleanup1;
- }
- buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
- GFP_KERNEL);
- if (!buff_size) {
- status = -ENOMEM;
- goto cleanup1;
- }
- left = ioc->buf_size;
- data_ptr = ioc->buf;
- while (left) {
- sz = (left >
- ioc->malloc_size) ? ioc->
- malloc_size : left;
- buff_size[sg_used] = sz;
- buff[sg_used] = kmalloc(sz, GFP_KERNEL);
- if (buff[sg_used] == NULL) {
- status = -ENOMEM;
- goto cleanup1;
- }
- if (ioc->Request.Type.Direction == XFER_WRITE) {
- if (copy_from_user
- (buff[sg_used], data_ptr, sz)) {
- status = -EFAULT;
- goto cleanup1;
- }
- } else {
- memset(buff[sg_used], 0, sz);
- }
- left -= sz;
- data_ptr += sz;
- sg_used++;
- }
- c = cmd_special_alloc(h);
- if (!c) {
- status = -ENOMEM;
- goto cleanup1;
- }
- c->cmd_type = CMD_IOCTL_PEND;
- c->Header.ReplyQueue = 0;
-
- if (ioc->buf_size > 0) {
- c->Header.SGList = sg_used;
- c->Header.SGTotal = sg_used;
- } else {
- c->Header.SGList = 0;
- c->Header.SGTotal = 0;
- }
- c->Header.LUN = ioc->LUN_info;
- c->Header.Tag.lower = c->busaddr;
-
- c->Request = ioc->Request;
- if (ioc->buf_size > 0) {
- for (i = 0; i < sg_used; i++) {
- temp64.val =
- pci_map_single(h->pdev, buff[i],
- buff_size[i],
- PCI_DMA_BIDIRECTIONAL);
- c->SG[i].Addr.lower =
- temp64.val32.lower;
- c->SG[i].Addr.upper =
- temp64.val32.upper;
- c->SG[i].Len = buff_size[i];
- c->SG[i].Ext = 0; /* we are not chaining */
- }
- }
- c->waiting = &wait;
- 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(h->pdev,
- (dma_addr_t) temp64.val, buff_size[i],
- PCI_DMA_BIDIRECTIONAL);
- }
- 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_special_free(h, c);
- status = -EFAULT;
- goto cleanup1;
- }
- if (ioc->Request.Type.Direction == XFER_READ) {
- /* Copy the data out of the buffer we created */
- BYTE __user *ptr = ioc->buf;
- for (i = 0; i < sg_used; i++) {
- if (copy_to_user
- (ptr, buff[i], buff_size[i])) {
- cmd_special_free(h, c);
- status = -EFAULT;
- goto cleanup1;
- }
- ptr += buff_size[i];
- }
- }
- cmd_special_free(h, c);
- status = 0;
- cleanup1:
- if (buff) {
- for (i = 0; i < sg_used; i++)
- kfree(buff[i]);
- kfree(buff);
- }
- kfree(buff_size);
- kfree(ioc);
- return status;
- }
+ case CCISS_BIG_PASSTHRU:
+ return cciss_bigpassthru(h, argp);

/* scsi_cmd_ioctl handles these, below, though some are not */
/* very meaningful for cciss. SG_IO is the main one people want. */

2010-08-26 18:50:33

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 13/13] cciss: remove some superfluous tests from cciss_bigpassthru()

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 25 ++++++++-----------------
1 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index a7ec339..d3ce357 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1582,28 +1582,19 @@ static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp)
}
c->cmd_type = CMD_IOCTL_PEND;
c->Header.ReplyQueue = 0;
-
- if (ioc->buf_size > 0) {
- c->Header.SGList = sg_used;
- c->Header.SGTotal = sg_used;
- } else {
- c->Header.SGList = 0;
- c->Header.SGTotal = 0;
- }
+ c->Header.SGList = sg_used;
+ c->Header.SGTotal = sg_used;
c->Header.LUN = ioc->LUN_info;
c->Header.Tag.lower = c->busaddr;

c->Request = ioc->Request;
- if (ioc->buf_size > 0) {
- for (i = 0; i < sg_used; i++) {
- temp64.val =
- pci_map_single(h->pdev, buff[i], buff_size[i],
+ for (i = 0; i < sg_used; i++) {
+ temp64.val = pci_map_single(h->pdev, buff[i], buff_size[i],
PCI_DMA_BIDIRECTIONAL);
- c->SG[i].Addr.lower = temp64.val32.lower;
- c->SG[i].Addr.upper = temp64.val32.upper;
- c->SG[i].Len = buff_size[i];
- c->SG[i].Ext = 0; /* we are not chaining */
- }
+ c->SG[i].Addr.lower = temp64.val32.lower;
+ c->SG[i].Addr.upper = temp64.val32.upper;
+ c->SG[i].Len = buff_size[i];
+ c->SG[i].Ext = 0; /* we are not chaining */
}
c->waiting = &wait;
enqueue_cmd_and_start_io(h, c);

2010-08-26 18:50:09

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 08/13] cciss: factor out cciss_getfirmver

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 27 +++++++++++++++------------
1 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 013d023..c4790ba 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1359,6 +1359,20 @@ static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_getfirmver(ctlr_info_t *h, void __user *argp)
+{
+ FirmwareVer_type firmware;
+
+ if (!argp)
+ return -EINVAL;
+ memcpy(firmware, h->firm_ver, 4);
+
+ if (copy_to_user
+ (argp, firmware, sizeof(FirmwareVer_type)))
+ return -EFAULT;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1385,18 +1399,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_GETBUSTYPES:
return cciss_getbustypes(h, argp);
case CCISS_GETFIRMVER:
- {
- FirmwareVer_type firmware;
-
- if (!arg)
- return -EINVAL;
- memcpy(firmware, h->firm_ver, 4);
-
- if (copy_to_user
- (argp, firmware, sizeof(FirmwareVer_type)))
- return -EFAULT;
- return 0;
- }
+ return cciss_getfirmver(h, argp);
case CCISS_GETDRIVVER:
{
DriverVer_type DriverVer = DRIVER_VERSION;

2010-08-26 18:51:54

by Stephen M. Cameron

[permalink] [raw]
Subject: [PATCH 03/13] cciss: factor out cciss_setintinfo

From: Stephen M. Cameron <[email protected]>

Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/block/cciss.c | 66 ++++++++++++++++++++++++-------------------------
1 files changed, 32 insertions(+), 34 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 14380c4..5ff5a1d 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1262,6 +1262,37 @@ static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
return 0;
}

+static int cciss_setintinfo(ctlr_info_t *h, void __user *argp)
+{
+ cciss_coalint_struct intinfo;
+ unsigned long flags;
+ int i;
+
+ if (!argp)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&intinfo, argp, sizeof(intinfo)))
+ return -EFAULT;
+ if ((intinfo.delay == 0) && (intinfo.count == 0))
+ return -EINVAL;
+ spin_lock_irqsave(&h->lock, flags);
+ /* Update the field, and then ring the doorbell */
+ writel(intinfo.delay, &(h->cfgtable->HostWrite.CoalIntDelay));
+ writel(intinfo.count, &(h->cfgtable->HostWrite.CoalIntCount));
+ writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+
+ for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+ if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+ break;
+ udelay(1000); /* delay and try again */
+ }
+ spin_unlock_irqrestore(&h->lock, flags);
+ if (i >= MAX_IOCTL_CONFIG_WAIT)
+ return -EAGAIN;
+ return 0;
+}
+
static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1278,40 +1309,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_GETINTINFO:
return cciss_getintinfo(h, argp);
case CCISS_SETINTINFO:
- {
- cciss_coalint_struct intinfo;
- unsigned long flags;
- int i;
-
- if (!arg)
- return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (copy_from_user
- (&intinfo, argp, sizeof(cciss_coalint_struct)))
- return -EFAULT;
- if ((intinfo.delay == 0) && (intinfo.count == 0))
- return -EINVAL;
- spin_lock_irqsave(&h->lock, flags);
- /* Update the field, and then ring the doorbell */
- writel(intinfo.delay,
- &(h->cfgtable->HostWrite.CoalIntDelay));
- writel(intinfo.count,
- &(h->cfgtable->HostWrite.CoalIntCount));
- writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-
- for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
- if (!(readl(h->vaddr + SA5_DOORBELL)
- & CFGTBL_ChangeReq))
- break;
- /* delay and try again */
- udelay(1000);
- }
- spin_unlock_irqrestore(&h->lock, flags);
- if (i >= MAX_IOCTL_CONFIG_WAIT)
- return -EAGAIN;
- return 0;
- }
+ return cciss_setintinfo(h, argp);
case CCISS_GETNODENAME:
{
NodeName_type NodeName;