All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] cciss: driver updates
@ 2009-11-12 18:49 Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 01/11] cciss: Make device attributes static Stephen M. Cameron
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

Updates for cciss, main items are: retry driver initiated commands
on unit attention condition, do not automatically rescan for devices
on unit attention, support for more scatter gather elements and larger
transfers.
---

Alex Chiang (1):
      cciss: Make device attributes static

Don Brace (1):
      cciss: Add enhanced scatter-gather support.

Stephen M. Cameron (9):
      cciss: Fix problem with remove_from_scan_list on driver unload
      cciss:  Retry driver initiated cmds with unit attention condition
      cciss:  Remove the "withirq" parameter from various functions where possible
      cciss: clean up code in cciss_shutdown
      cciss: remove sendcmd() as it is no longer used.
      cciss: fix typo that causes scsi status to be lost.
      cciss: Remove unnecessary check in scan_thread
      cciss: Do not automatically rescan on UNIT ATTENTION/LUN DATA CHANGED
      cciss: Fix weird usage of ENXIO in cciss_scsi.c


 drivers/block/cciss.c      |  549 +++++++++++++++++++++-----------------------
 drivers/block/cciss.h      |   18 +
 drivers/block/cciss_cmd.h  |    7 -
 drivers/block/cciss_scsi.c |    4 
 4 files changed, 283 insertions(+), 295 deletions(-)

-- 
-- steve

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 01/11] cciss: Make device attributes static
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 02/11] cciss: Fix problem with remove_from_scan_list on driver unload Stephen M. Cameron
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Alex Chiang <achiang@hp.com>

cciss: Make device attributes static

Cc: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: Alex Chiang <achiang@hp.com>
Acked-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 6399e50..92b1263 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -482,7 +482,7 @@ static ssize_t host_store_rescan(struct device *dev,
 
 	return count;
 }
-DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
+static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
 
 static ssize_t dev_show_unique_id(struct device *dev,
 				 struct device_attribute *attr,
@@ -512,7 +512,7 @@ static ssize_t dev_show_unique_id(struct device *dev,
 				sn[8], sn[9], sn[10], sn[11],
 				sn[12], sn[13], sn[14], sn[15]);
 }
-DEVICE_ATTR(unique_id, S_IRUGO, dev_show_unique_id, NULL);
+static DEVICE_ATTR(unique_id, S_IRUGO, dev_show_unique_id, NULL);
 
 static ssize_t dev_show_vendor(struct device *dev,
 			       struct device_attribute *attr,
@@ -536,7 +536,7 @@ static ssize_t dev_show_vendor(struct device *dev,
 	else
 		return snprintf(buf, sizeof(vendor) + 1, "%s\n", drv->vendor);
 }
-DEVICE_ATTR(vendor, S_IRUGO, dev_show_vendor, NULL);
+static DEVICE_ATTR(vendor, S_IRUGO, dev_show_vendor, NULL);
 
 static ssize_t dev_show_model(struct device *dev,
 			      struct device_attribute *attr,
@@ -560,7 +560,7 @@ static ssize_t dev_show_model(struct device *dev,
 	else
 		return snprintf(buf, sizeof(model) + 1, "%s\n", drv->model);
 }
-DEVICE_ATTR(model, S_IRUGO, dev_show_model, NULL);
+static DEVICE_ATTR(model, S_IRUGO, dev_show_model, NULL);
 
 static ssize_t dev_show_rev(struct device *dev,
 			    struct device_attribute *attr,
@@ -584,7 +584,7 @@ static ssize_t dev_show_rev(struct device *dev,
 	else
 		return snprintf(buf, sizeof(rev) + 1, "%s\n", drv->rev);
 }
-DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL);
+static DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL);
 
 static ssize_t cciss_show_lunid(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -609,7 +609,7 @@ static ssize_t cciss_show_lunid(struct device *dev,
 		lunid[0], lunid[1], lunid[2], lunid[3],
 		lunid[4], lunid[5], lunid[6], lunid[7]);
 }
-DEVICE_ATTR(lunid, S_IRUGO, cciss_show_lunid, NULL);
+static DEVICE_ATTR(lunid, S_IRUGO, cciss_show_lunid, NULL);
 
 static ssize_t cciss_show_raid_level(struct device *dev,
 				     struct device_attribute *attr, char *buf)
@@ -632,7 +632,7 @@ static ssize_t cciss_show_raid_level(struct device *dev,
 	return snprintf(buf, strlen(raid_label[raid]) + 7, "RAID %s\n",
 			raid_label[raid]);
 }
-DEVICE_ATTR(raid_level, S_IRUGO, cciss_show_raid_level, NULL);
+static DEVICE_ATTR(raid_level, S_IRUGO, cciss_show_raid_level, NULL);
 
 static ssize_t cciss_show_usage_count(struct device *dev,
 				      struct device_attribute *attr, char *buf)
@@ -651,7 +651,7 @@ static ssize_t cciss_show_usage_count(struct device *dev,
 	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 	return snprintf(buf, 20, "%d\n", count);
 }
-DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL);
+static DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL);
 
 static struct attribute *cciss_host_attrs[] = {
 	&dev_attr_rescan.attr,


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 02/11] cciss: Fix problem with remove_from_scan_list on driver unload
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 01/11] cciss: Make device attributes static Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 03/11] cciss: Retry driver initiated cmds with unit attention condition Stephen M. Cameron
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss: Fix problem with remove_from_scan_list that on driver unload
it doesn't remove the controller from the scan list correctly if
the controller is currently being scanned for new devices.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c |   21 +++++++++++++--------
 1 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 92b1263..81c2187 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3513,28 +3513,33 @@ static int add_to_scan_list(struct ctlr_info *h)
  * @h:			   Pointer to the controller.
  *
  * Removes the controller from the rescan queue if present. Blocks if
- * the controller is currently conducting a rescan.
+ * the controller is currently conducting a rescan.  The controller
+ * can be in one of three states:
+ * 1. Doesn't need a scan
+ * 2. On the scan list, but not scanning yet (we remove it)
+ * 3. Busy scanning (and not on the list). In this case we want to wait for
+ *    the scan to complete to make sure the scanning thread for this
+ *    controller is completely idle.
  **/
 static void remove_from_scan_list(struct ctlr_info *h)
 {
 	struct ctlr_info *test_h, *tmp_h;
-	int scanning = 0;
 
 	mutex_lock(&scan_mutex);
 	list_for_each_entry_safe(test_h, tmp_h, &scan_q, scan_list) {
-		if (test_h == h) {
+		if (test_h == h) { /* state 2. */
 			list_del(&h->scan_list);
 			complete_all(&h->scan_wait);
 			mutex_unlock(&scan_mutex);
 			return;
 		}
 	}
-	if (&h->busy_scanning)
-		scanning = 0;
-	mutex_unlock(&scan_mutex);
-
-	if (scanning)
+	if (h->busy_scanning) { /* state 3. */
+		mutex_unlock(&scan_mutex);
 		wait_for_completion(&h->scan_wait);
+	} else { /* state 1, nothing to do. */
+		mutex_unlock(&scan_mutex);
+	}
 }
 
 /**


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 03/11] cciss: Retry driver initiated cmds with unit attention condition
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 01/11] cciss: Make device attributes static Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 02/11] cciss: Fix problem with remove_from_scan_list on driver unload Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 04/11] cciss: Remove the "withirq" parameter from various functions where possible Stephen M. Cameron
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss:  Retry driver initiated cmds with unit attention condition

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 81c2187..429b9b6 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2531,6 +2531,8 @@ static int check_target_status(ctlr_info_t *h, CommandList_struct *c)
 		case 0: return IO_OK; /* no sense */
 		case 1: return IO_OK; /* recovered error */
 		default:
+			if (check_for_unit_attention(h, c))
+				return IO_NEEDS_RETRY;
 			printk(KERN_WARNING "cciss%d: cmd 0x%02x "
 				"check condition, sense key = 0x%02x\n",
 				h->ctlr, c->Request.CDB[0],


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 04/11] cciss: Remove the "withirq" parameter from various functions where possible
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (2 preceding siblings ...)
  2009-11-12 18:49 ` [PATCH 03/11] cciss: Retry driver initiated cmds with unit attention condition Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 05/11] cciss: clean up code in cciss_shutdown Stephen M. Cameron
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss:  Remove the "withirq" parameter from various functions where possible

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c |   89 ++++++++++++++++---------------------------------
 1 files changed, 29 insertions(+), 60 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 429b9b6..4321c94 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -179,12 +179,12 @@ 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, int withirq,
+static void cciss_read_capacity(int ctlr, int logvol,
 			sector_t *total_size, unsigned int *block_size);
-static void cciss_read_capacity_16(int ctlr, int logvol, int withirq,
+static void cciss_read_capacity_16(int ctlr, int logvol,
 			sector_t *total_size, unsigned int *block_size);
 static void cciss_geometry_inquiry(int ctlr, int logvol,
-			int withirq, sector_t total_size,
+			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 *,
@@ -1701,7 +1701,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, int withirq,
+static void cciss_get_device_descr(int ctlr, int logvol,
 				   char *vendor, char *model, char *rev)
 {
 	int rc;
@@ -1717,14 +1717,8 @@ static void cciss_get_device_descr(int ctlr, int logvol, int withirq,
 		return;
 
 	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
-	if (withirq)
-		rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf,
-			     sizeof(InquiryData_struct), 0,
-				scsi3addr, TYPE_CMD);
-	else
-		rc = sendcmd(CISS_INQUIRY, ctlr, inq_buf,
-			     sizeof(InquiryData_struct), 0,
-				scsi3addr, TYPE_CMD);
+	rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf, sizeof(*inq_buf), 0,
+			scsi3addr, TYPE_CMD);
 	if (rc == IO_OK) {
 		memcpy(vendor, &inq_buf->data_byte[8], VENDOR_LEN);
 		vendor[VENDOR_LEN] = '\0';
@@ -1743,7 +1737,7 @@ static void cciss_get_device_descr(int ctlr, int logvol, int withirq,
  * number cannot be had, for whatever reason, 16 bytes of 0xff
  * are returned instead.
  */
-static void cciss_get_serial_no(int ctlr, int logvol, int withirq,
+static void cciss_get_serial_no(int ctlr, int logvol,
 				unsigned char *serial_no, int buflen)
 {
 #define PAGE_83_INQ_BYTES 64
@@ -1759,12 +1753,8 @@ static void cciss_get_serial_no(int ctlr, int logvol, int withirq,
 		return;
 	memset(serial_no, 0, buflen);
 	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
-	if (withirq)
-		rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf,
-			PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD);
-	else
-		rc = sendcmd(CISS_INQUIRY, ctlr, buf,
-			PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD);
+	rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf,
+		PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD);
 	if (rc == IO_OK)
 		memcpy(serial_no, &buf[8], buflen);
 	kfree(buf);
@@ -1852,18 +1842,16 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time,
 
 	/* testing to see if 16-byte CDBs are already being used */
 	if (h->cciss_read == CCISS_READ_16) {
-		cciss_read_capacity_16(h->ctlr, drv_index, 1,
+		cciss_read_capacity_16(h->ctlr, drv_index,
 			&total_size, &block_size);
 
 	} else {
-		cciss_read_capacity(ctlr, drv_index, 1,
-				    &total_size, &block_size);
-
+		cciss_read_capacity(ctlr, drv_index, &total_size, &block_size);
 		/* if read_capacity returns all F's this volume is >2TB */
 		/* in size so we switch to 16-byte CDB's for all */
 		/* read/write ops */
 		if (total_size == 0xFFFFFFFFULL) {
-			cciss_read_capacity_16(ctlr, drv_index, 1,
+			cciss_read_capacity_16(ctlr, drv_index,
 			&total_size, &block_size);
 			h->cciss_read = CCISS_READ_16;
 			h->cciss_write = CCISS_WRITE_16;
@@ -1873,14 +1861,14 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time,
 		}
 	}
 
-	cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
+	cciss_geometry_inquiry(ctlr, drv_index, total_size, block_size,
 			       inq_buff, drvinfo);
 	drvinfo->block_size = block_size;
 	drvinfo->nr_blocks = total_size + 1;
 
-	cciss_get_device_descr(ctlr, drv_index, 1, drvinfo->vendor,
+	cciss_get_device_descr(ctlr, drv_index, drvinfo->vendor,
 				drvinfo->model, drvinfo->rev);
-	cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no,
+	cciss_get_serial_no(ctlr, drv_index, drvinfo->serial_no,
 			sizeof(drvinfo->serial_no));
 	/* Save the lunid in case we deregister the disk, below. */
 	memcpy(drvinfo->LunID, h->drv[drv_index]->LunID,
@@ -2674,7 +2662,7 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
 }
 
 static void cciss_geometry_inquiry(int ctlr, int logvol,
-				   int withirq, sector_t total_size,
+				   sector_t total_size,
 				   unsigned int block_size,
 				   InquiryData_struct *inq_buff,
 				   drive_info_struct *drv)
@@ -2685,14 +2673,8 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
 
 	memset(inq_buff, 0, sizeof(InquiryData_struct));
 	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
-	if (withirq)
-		return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
-					      inq_buff, sizeof(*inq_buff),
-					      0xC1, scsi3addr, TYPE_CMD);
-	else
-		return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,
-				      sizeof(*inq_buff), 0xC1, scsi3addr,
-				      TYPE_CMD);
+	return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff,
+			sizeof(*inq_buff), 0xC1, scsi3addr, TYPE_CMD);
 	if (return_code == IO_OK) {
 		if (inq_buff->data_byte[8] == 0xFF) {
 			printk(KERN_WARNING
@@ -2725,7 +2707,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
 }
 
 static void
-cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
+cciss_read_capacity(int ctlr, int logvol, sector_t *total_size,
 		    unsigned int *block_size)
 {
 	ReadCapdata_struct *buf;
@@ -2739,14 +2721,8 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
 	}
 
 	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
-	if (withirq)
-		return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
-				ctlr, buf, sizeof(ReadCapdata_struct),
-					0, scsi3addr, TYPE_CMD);
-	else
-		return_code = sendcmd(CCISS_READ_CAPACITY,
-				ctlr, buf, sizeof(ReadCapdata_struct),
-					0, scsi3addr, TYPE_CMD);
+	return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, buf,
+		sizeof(ReadCapdata_struct), 0, scsi3addr, TYPE_CMD);
 	if (return_code == IO_OK) {
 		*total_size = be32_to_cpu(*(__be32 *) buf->total_size);
 		*block_size = be32_to_cpu(*(__be32 *) buf->block_size);
@@ -2758,8 +2734,8 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
 	kfree(buf);
 }
 
-static void
-cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, 				unsigned int *block_size)
+static void cciss_read_capacity_16(int ctlr, int logvol,
+	sector_t *total_size, unsigned int *block_size)
 {
 	ReadCapdata_struct_16 *buf;
 	int return_code;
@@ -2772,16 +2748,9 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
 	}
 
 	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
-	if (withirq) {
-		return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
-			ctlr, buf, sizeof(ReadCapdata_struct_16),
-				0, scsi3addr, TYPE_CMD);
-	}
-	else {
-		return_code = sendcmd(CCISS_READ_CAPACITY_16,
-			ctlr, buf, sizeof(ReadCapdata_struct_16),
-				0, scsi3addr, TYPE_CMD);
-	}
+	return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
+		ctlr, buf, sizeof(ReadCapdata_struct_16),
+			0, scsi3addr, TYPE_CMD);
 	if (return_code == IO_OK) {
 		*total_size = be64_to_cpu(*(__be64 *) buf->total_size);
 		*block_size = be32_to_cpu(*(__be32 *) buf->block_size);
@@ -2822,13 +2791,13 @@ static int cciss_revalidate(struct gendisk *disk)
 		return 1;
 	}
 	if (h->cciss_read == CCISS_READ_10) {
-		cciss_read_capacity(h->ctlr, logvol, 1,
+		cciss_read_capacity(h->ctlr, logvol,
 					&total_size, &block_size);
 	} else {
-		cciss_read_capacity_16(h->ctlr, logvol, 1,
+		cciss_read_capacity_16(h->ctlr, logvol,
 					&total_size, &block_size);
 	}
-	cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
+	cciss_geometry_inquiry(h->ctlr, logvol, total_size, block_size,
 			       inq_buff, drv);
 
 	blk_queue_logical_block_size(drv->queue, drv->block_size);


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 05/11] cciss: clean up code in cciss_shutdown
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (3 preceding siblings ...)
  2009-11-12 18:49 ` [PATCH 04/11] cciss: Remove the "withirq" parameter from various functions where possible Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 06/11] cciss: remove sendcmd() as it is no longer used Stephen M. Cameron
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss: clean up code in cciss_shutdown.  Send the flush cache
command down with interrupts still enabled, and do not do DMA
from the stack.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c |   38 ++++++++++++++++++--------------------
 1 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 4321c94..f804542 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -4376,30 +4376,28 @@ clean_no_release_regions:
 
 static void cciss_shutdown(struct pci_dev *pdev)
 {
-	ctlr_info_t *tmp_ptr;
-	int i;
-	char flush_buf[4];
+	ctlr_info_t *h;
+	char *flush_buf;
 	int return_code;
 
-	tmp_ptr = pci_get_drvdata(pdev);
-	if (tmp_ptr == NULL)
-		return;
-	i = tmp_ptr->ctlr;
-	if (hba[i] == NULL)
+	h = pci_get_drvdata(pdev);
+	flush_buf = kzalloc(4, GFP_KERNEL);
+	if (!flush_buf) {
+		printk(KERN_WARNING
+			"cciss:%d cache not flushed, out of memory.\n",
+			h->ctlr);
 		return;
-
-	/* Turn board interrupts off  and send the flush cache command */
-	/* sendcmd will turn off interrupt, and send the flush...
-	 * To write all data in the battery backed cache to disks */
-	memset(flush_buf, 0, 4);
-	return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0,
-		CTLR_LUNID, TYPE_CMD);
-	if (return_code == IO_OK) {
-		printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
-	} else {
-		printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
 	}
-	free_irq(hba[i]->intr[2], hba[i]);
+	/* write all data in the battery backed cache to disk */
+	memset(flush_buf, 0, 4);
+	return_code = sendcmd_withirq(CCISS_CACHE_FLUSH, h->ctlr, flush_buf,
+		4, 0, CTLR_LUNID, TYPE_CMD);
+	kfree(flush_buf);
+	if (return_code != IO_OK)
+		printk(KERN_WARNING "cciss%d: Error flushing cache\n",
+			h->ctlr);
+	h->access.set_intr_mask(h, CCISS_INTR_OFF);
+	free_irq(h->intr[2], h);
 }
 
 static void __devexit cciss_remove_one(struct pci_dev *pdev)


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 06/11] cciss: remove sendcmd() as it is no longer used.
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (4 preceding siblings ...)
  2009-11-12 18:49 ` [PATCH 05/11] cciss: clean up code in cciss_shutdown Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 07/11] cciss: fix typo that causes scsi status to be lost Stephen M. Cameron
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss: remove sendcmd() as it is no longer used.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c |  163 -------------------------------------------------
 1 files changed, 0 insertions(+), 163 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index f804542..23c2910 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -190,8 +190,6 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
 static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
 					   __u32);
 static void start_io(ctlr_info_t *h);
-static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size,
-		   __u8 page_code, unsigned char *scsi3addr, int cmd_type);
 static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
 			__u8 page_code, unsigned char scsi3addr[],
 			int cmd_type);
@@ -2808,167 +2806,6 @@ static int cciss_revalidate(struct gendisk *disk)
 }
 
 /*
- *   Wait polling for a command to complete.
- *   The memory mapped FIFO is polled for the completion.
- *   Used only at init time, interrupts from the HBA are disabled.
- */
-static unsigned long pollcomplete(int ctlr)
-{
-	unsigned long done;
-	int i;
-
-	/* Wait (up to 20 seconds) for a command to complete */
-
-	for (i = 20 * HZ; i > 0; i--) {
-		done = hba[ctlr]->access.command_completed(hba[ctlr]);
-		if (done == FIFO_EMPTY)
-			schedule_timeout_uninterruptible(1);
-		else
-			return done;
-	}
-	/* Invalid address to tell caller we ran out of time */
-	return 1;
-}
-
-/* Send command c to controller h and poll for it to complete.
- * Turns interrupts off on the board.  Used at driver init time
- * and during SCSI error recovery.
- */
-static int sendcmd_core(ctlr_info_t *h, CommandList_struct *c)
-{
-	int i;
-	unsigned long complete;
-	int status = IO_ERROR;
-	u64bit buff_dma_handle;
-
-resend_cmd1:
-
-	/* Disable interrupt on the board. */
-	h->access.set_intr_mask(h, CCISS_INTR_OFF);
-
-	/* Make sure there is room in the command FIFO */
-	/* Actually it should be completely empty at this time */
-	/* unless we are in here doing error handling for the scsi */
-	/* tape side of the driver. */
-	for (i = 200000; i > 0; i--) {
-		/* if fifo isn't full go */
-		if (!(h->access.fifo_full(h)))
-			break;
-		udelay(10);
-		printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"
-		       " waiting!\n", h->ctlr);
-	}
-	h->access.submit_command(h, c); /* Send the cmd */
-	do {
-		complete = pollcomplete(h->ctlr);
-
-#ifdef CCISS_DEBUG
-		printk(KERN_DEBUG "cciss: command completed\n");
-#endif				/* CCISS_DEBUG */
-
-		if (complete == 1) {
-			printk(KERN_WARNING
-			       "cciss cciss%d: SendCmd Timeout out, "
-			       "No command list address returned!\n", h->ctlr);
-			status = IO_ERROR;
-			break;
-		}
-
-		/* Make sure it's the command we're expecting. */
-		if ((complete & ~CISS_ERROR_BIT) != c->busaddr) {
-			printk(KERN_WARNING "cciss%d: Unexpected command "
-				"completion.\n", h->ctlr);
-			continue;
-		}
-
-		/* It is our command.  If no error, we're done. */
-		if (!(complete & CISS_ERROR_BIT)) {
-			status = IO_OK;
-			break;
-		}
-
-		/* There is an error... */
-
-		/* if data overrun or underun on Report command ignore it */
-		if (((c->Request.CDB[0] == CISS_REPORT_LOG) ||
-		     (c->Request.CDB[0] == CISS_REPORT_PHYS) ||
-		     (c->Request.CDB[0] == CISS_INQUIRY)) &&
-			((c->err_info->CommandStatus == CMD_DATA_OVERRUN) ||
-			 (c->err_info->CommandStatus == CMD_DATA_UNDERRUN))) {
-			complete = c->busaddr;
-			status = IO_OK;
-			break;
-		}
-
-		if (c->err_info->CommandStatus == CMD_UNSOLICITED_ABORT) {
-			printk(KERN_WARNING "cciss%d: unsolicited abort %p\n",
-				h->ctlr, c);
-			if (c->retry_count < MAX_CMD_RETRIES) {
-				printk(KERN_WARNING "cciss%d: retrying %p\n",
-				   h->ctlr, c);
-				c->retry_count++;
-				/* erase the old error information */
-				memset(c->err_info, 0, sizeof(c->err_info));
-				goto resend_cmd1;
-			}
-			printk(KERN_WARNING "cciss%d: retried %p too many "
-				"times\n", h->ctlr, c);
-			status = IO_ERROR;
-			break;
-		}
-
-		if (c->err_info->CommandStatus == CMD_UNABORTABLE) {
-			printk(KERN_WARNING "cciss%d: command could not be "
-				"aborted.\n", h->ctlr);
-			status = IO_ERROR;
-			break;
-		}
-
-		if (c->err_info->CommandStatus == CMD_TARGET_STATUS) {
-			status = check_target_status(h, c);
-			break;
-		}
-
-		printk(KERN_WARNING "cciss%d: sendcmd error\n", h->ctlr);
-		printk(KERN_WARNING "cmd = 0x%02x, CommandStatus = 0x%02x\n",
-			c->Request.CDB[0], c->err_info->CommandStatus);
-		status = IO_ERROR;
-		break;
-
-	} while (1);
-
-	/* unlock the data buffer from DMA */
-	buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
-	buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
-	pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val,
-			 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
-	return status;
-}
-
-/*
- * Send a command to the controller, and wait for it to complete.
- * Used at init time, and during SCSI error recovery.
- */
-static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size,
-	__u8 page_code, unsigned char *scsi3addr, int cmd_type)
-{
-	CommandList_struct *c;
-	int status;
-
-	c = cmd_alloc(hba[ctlr], 1);
-	if (!c) {
-		printk(KERN_WARNING "cciss: unable to get memory");
-		return IO_ERROR;
-	}
-	status = fill_cmd(c, cmd, ctlr, buff, size, page_code,
-		scsi3addr, cmd_type);
-	if (status == IO_OK)
-		status = sendcmd_core(hba[ctlr], c);
-	cmd_free(hba[ctlr], c, 1);
-	return status;
-}
-
-/*
  * Map (physical) PCI mem into (virtual) kernel space
  */
 static void __iomem *remap_pci_mem(ulong base, ulong size)


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 07/11] cciss: fix typo that causes scsi status to be lost.
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (5 preceding siblings ...)
  2009-11-12 18:49 ` [PATCH 06/11] cciss: remove sendcmd() as it is no longer used Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 08/11] cciss: Remove unnecessary check in scan_thread Stephen M. Cameron
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss: fix typo that causes scsi status to be lost.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss_scsi.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 3315268..237d2b3 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -755,7 +755,7 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag)
                         			cp,  
 						ei->ScsiStatus); 
 #endif
-					cmd->result |= (ei->ScsiStatus < 1);
+					cmd->result |= (ei->ScsiStatus << 1);
                 		}
 				else {  /* scsi status is zero??? How??? */
 					


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 08/11] cciss: Remove unnecessary check in scan_thread
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (6 preceding siblings ...)
  2009-11-12 18:49 ` [PATCH 07/11] cciss: fix typo that causes scsi status to be lost Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:49 ` [PATCH 09/11] cciss: Do not automatically rescan on UNIT ATTENTION/LUN DATA CHANGED Stephen M. Cameron
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss: Remove unnecessary check in scan_thread

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 23c2910..42eaddb 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3386,13 +3386,11 @@ static int scan_thread(void *data)
 			h->busy_scanning = 1;
 			mutex_unlock(&scan_mutex);
 
-			if (h) {
-				rebuild_lun_table(h, 0, 0);
-				complete_all(&h->scan_wait);
-				mutex_lock(&scan_mutex);
-				h->busy_scanning = 0;
-				mutex_unlock(&scan_mutex);
-			}
+			rebuild_lun_table(h, 0, 0);
+			complete_all(&h->scan_wait);
+			mutex_lock(&scan_mutex);
+			h->busy_scanning = 0;
+			mutex_unlock(&scan_mutex);
 		}
 	}
 


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 09/11] cciss: Do not automatically rescan on UNIT ATTENTION/LUN DATA CHANGED
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (7 preceding siblings ...)
  2009-11-12 18:49 ` [PATCH 08/11] cciss: Remove unnecessary check in scan_thread Stephen M. Cameron
@ 2009-11-12 18:49 ` Stephen M. Cameron
  2009-11-12 18:50 ` [PATCH 10/11] cciss: Add enhanced scatter-gather support Stephen M. Cameron
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:49 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss: Do not automatically rescan on UNIT ATTENTION/LUN DATA CHANGED
There are problems with doing this.  If, say, several logical drives
are deleted at once, several such UNIT ATTENTIONS will be encountered,
often during the rescan triggered by the first such UNIT ATTENTION.
The block layer may be in the midst of trying to add logical drives
which were just deleted (resulting in the subsequent UNIT ATTENTION(s).)
Making the rescan code robust enough to tolerate this kind of thing
is too complicated for the moment.  So, for now, we just don't do it.
Note: This UNIT ATTENTION/LUN DATA CHANGED situation only occurs on
the MSA2012.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c |   18 ++++++++++++++++--
 1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 42eaddb..bf2d1c8 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3416,8 +3416,22 @@ static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c)
 	case REPORT_LUNS_CHANGED:
 		printk(KERN_WARNING "cciss%d: report LUN data "
 			"changed\n", h->ctlr);
-		add_to_scan_list(h);
-		wake_up_process(cciss_scan_thread);
+	/*
+	 * Here, we could call add_to_scan_list and wake up the scan thread,
+	 * except that it's quite likely that we will get more than one
+	 * REPORT_LUNS_CHANGED condition in quick succession, which means
+	 * that those which occur after the first one will likely happen
+	 * *during* the scan_thread's rescan.  And the rescan code is not
+	 * robust enough to restart in the middle, undoing what it has already
+	 * done, and it's not clear that it's even possible to do this, since
+	 * part of what it does is notify the block layer, which starts
+	 * doing it's own i/o to read partition tables and so on, and the
+	 * driver doesn't have visibility to know what might need undoing.
+	 * In any event, if possible, it is horribly complicated to get right
+	 * so we just don't do it for now.
+	 *
+	 * Note: this REPORT_LUNS_CHANGED condition only occurs on the MSA2012.
+	 */
 		return 1;
 	break;
 	case POWER_OR_RESET:


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 10/11] cciss: Add enhanced scatter-gather support.
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (8 preceding siblings ...)
  2009-11-12 18:49 ` [PATCH 09/11] cciss: Do not automatically rescan on UNIT ATTENTION/LUN DATA CHANGED Stephen M. Cameron
@ 2009-11-12 18:50 ` Stephen M. Cameron
  2009-11-12 18:50 ` [PATCH 11/11] cciss: Fix weird usage of ENXIO in cciss_scsi.c Stephen M. Cameron
  2009-11-13  7:46 ` [PATCH 00/11] cciss: driver updates Jens Axboe
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:50 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Don Brace <brace@beardog.cce.hp.com>

cciss: Add enhanced scatter-gather support.  For controllers which
supported, more than 512 scatter-gather elements per command may
be used, and the max transfer size can be increased to 8192 blocks.

Signed-off-by: Don Brace <brace@beardog.cce.hp.com>
Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c     |  183 +++++++++++++++++++++++++++++++++++++++++----
 drivers/block/cciss.h     |   18 ++++
 drivers/block/cciss_cmd.h |    7 +-
 3 files changed, 188 insertions(+), 20 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index bf2d1c8..1bd313d 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1655,9 +1655,11 @@ 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;
 	u64bit temp64;
 	int i, ddir;
+	int sg_index = 0;
 
 	if (cmd->Request.Type.Direction == XFER_READ)
 		ddir = PCI_DMA_FROMDEVICE;
@@ -1667,9 +1669,22 @@ static void cciss_softirq_done(struct request *rq)
 	/* 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++) {
-		temp64.val32.lower = cmd->SG[i].Addr.lower;
-		temp64.val32.upper = cmd->SG[i].Addr.upper;
-		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+		if (curr_sg[sg_index].Ext == CCISS_SG_CHAIN) {
+			temp64.val32.lower = cmd->SG[i].Addr.lower;
+			temp64.val32.upper = cmd->SG[i].Addr.upper;
+			pci_dma_sync_single_for_cpu(h->pdev, temp64.val,
+						cmd->SG[i].Len, ddir);
+			pci_unmap_single(h->pdev, temp64.val,
+						cmd->SG[i].Len, ddir);
+			/* Point to the next block */
+			curr_sg = h->cmd_sg_list[cmd->cmdindex]->sgchain;
+			sg_index = 0;
+		}
+		temp64.val32.lower = curr_sg[sg_index].Addr.lower;
+		temp64.val32.upper = curr_sg[sg_index].Addr.upper;
+		pci_unmap_page(h->pdev, temp64.val, curr_sg[sg_index].Len,
+				ddir);
+		++sg_index;
 	}
 
 #ifdef CCISS_DEBUG
@@ -1781,10 +1796,10 @@ static int cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
 	blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
 
 	/* This is a hardware imposed limit. */
-	blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
+	blk_queue_max_hw_segments(disk->queue, h->maxsgentries);
 
 	/* This is a limit in the driver and could be eliminated. */
-	blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
+	blk_queue_max_phys_segments(disk->queue, h->maxsgentries);
 
 	blk_queue_max_sectors(disk->queue, h->cciss_max_sectors);
 
@@ -3063,9 +3078,13 @@ static void do_cciss_request(struct request_queue *q)
 	int seg;
 	struct request *creq;
 	u64bit temp64;
-	struct scatterlist tmp_sg[MAXSGENTRIES];
+	struct scatterlist *tmp_sg;
+	SGDescriptor_struct *curr_sg;
 	drive_info_struct *drv;
 	int i, dir;
+	int nseg = 0;
+	int sg_index = 0;
+	int chained = 0;
 
 	/* We call start_io here in case there is a command waiting on the
 	 * queue that has not been sent.
@@ -3078,13 +3097,14 @@ static void do_cciss_request(struct request_queue *q)
 	if (!creq)
 		goto startio;
 
-	BUG_ON(creq->nr_phys_segments > MAXSGENTRIES);
+	BUG_ON(creq->nr_phys_segments > h->maxsgentries);
 
 	if ((c = cmd_alloc(h, 1)) == NULL)
 		goto full;
 
 	blk_start_request(creq);
 
+	tmp_sg = h->scatter_list[c->cmdindex];
 	spin_unlock_irq(q->queue_lock);
 
 	c->cmd_type = CMD_RWREQ;
@@ -3113,7 +3133,7 @@ static void do_cciss_request(struct request_queue *q)
 	       (int)blk_rq_pos(creq), (int)blk_rq_sectors(creq));
 #endif				/* CCISS_DEBUG */
 
-	sg_init_table(tmp_sg, MAXSGENTRIES);
+	sg_init_table(tmp_sg, h->maxsgentries);
 	seg = blk_rq_map_sg(q, creq, tmp_sg);
 
 	/* get the DMA records for the setup */
@@ -3122,25 +3142,70 @@ static void do_cciss_request(struct request_queue *q)
 	else
 		dir = PCI_DMA_TODEVICE;
 
+	curr_sg = c->SG;
+	sg_index = 0;
+	chained = 0;
+
 	for (i = 0; i < seg; i++) {
-		c->SG[i].Len = tmp_sg[i].length;
+		if (((sg_index+1) == (h->max_cmd_sgentries)) &&
+			!chained && ((seg - i) > 1)) {
+			nseg = seg - i;
+			curr_sg[sg_index].Len = (nseg) *
+					sizeof(SGDescriptor_struct);
+			curr_sg[sg_index].Ext = CCISS_SG_CHAIN;
+
+			/* Point to next chain block. */
+			curr_sg = h->cmd_sg_list[c->cmdindex]->sgchain;
+			sg_index = 0;
+			chained = 1;
+		}
+		curr_sg[sg_index].Len = tmp_sg[i].length;
 		temp64.val = (__u64) pci_map_page(h->pdev, sg_page(&tmp_sg[i]),
-						  tmp_sg[i].offset,
-						  tmp_sg[i].length, dir);
-		c->SG[i].Addr.lower = temp64.val32.lower;
-		c->SG[i].Addr.upper = temp64.val32.upper;
-		c->SG[i].Ext = 0;	// we are not chaining
+						tmp_sg[i].offset,
+						tmp_sg[i].length, dir);
+		curr_sg[sg_index].Addr.lower = temp64.val32.lower;
+		curr_sg[sg_index].Addr.upper = temp64.val32.upper;
+		curr_sg[sg_index].Ext = 0;  /* we are not chaining */
+
+		++sg_index;
 	}
+
+	if (chained) {
+		int len;
+		curr_sg = c->SG;
+		sg_index = h->max_cmd_sgentries - 1;
+		len = curr_sg[sg_index].Len;
+		/* Setup pointer to next chain block.
+		 * Fill out last element in current chain
+		 * block with address of next chain block.
+		 */
+		temp64.val = pci_map_single(h->pdev,
+					h->cmd_sg_list[c->cmdindex]->sgchain,
+					len, dir);
+
+		h->cmd_sg_list[c->cmdindex]->sg_chain_dma = temp64.val;
+		curr_sg[sg_index].Addr.lower = temp64.val32.lower;
+		curr_sg[sg_index].Addr.upper = temp64.val32.upper;
+
+		pci_dma_sync_single_for_device(h->pdev,
+				h->cmd_sg_list[c->cmdindex]->sg_chain_dma,
+				len, dir);
+	}
+
 	/* track how many SG entries we are using */
 	if (seg > h->maxSG)
 		h->maxSG = seg;
 
 #ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "cciss: Submitting %u sectors in %d segments\n",
-	       blk_rq_sectors(creq), seg);
+	printk(KERN_DEBUG "cciss: Submitting %ld sectors in %d segments "
+			"chained[%d]\n",
+			blk_rq_sectors(creq), seg, chained);
 #endif				/* CCISS_DEBUG */
 
-	c->Header.SGList = c->Header.SGTotal = seg;
+	c->Header.SGList = c->Header.SGTotal = seg + chained;
+	if (seg > h->max_cmd_sgentries)
+		c->Header.SGList = h->max_cmd_sgentries;
+
 	if (likely(blk_fs_request(creq))) {
 		if(h->cciss_read == CCISS_READ_10) {
 			c->Request.CDB[1] = 0;
@@ -3713,6 +3778,23 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 	 * leave a little room for ioctl calls.
 	 */
 	c->max_commands = readl(&(c->cfgtable->CmdsOutMax));
+	c->maxsgentries = readl(&(c->cfgtable->MaxSGElements));
+
+	/*
+	 * Limit native command to 32 s/g elements to save dma'able memory.
+	 * Howvever spec says if 0, use 31
+	 */
+
+	c->max_cmd_sgentries = 31;
+	if (c->maxsgentries > 512) {
+		c->max_cmd_sgentries = 32;
+		c->chainsize = c->maxsgentries - c->max_cmd_sgentries + 1;
+		c->maxsgentries -= 1;   /* account for chain pointer */
+	} else {
+		c->maxsgentries = 31;   /* Default to traditional value */
+		c->chainsize = 0;       /* traditional */
+	}
+
 	c->product_name = products[prod_index].product_name;
 	c->access = *(products[prod_index].access);
 	c->nr_cmds = c->max_commands - 4;
@@ -4039,6 +4121,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 {
 	int i;
 	int j = 0;
+	int k = 0;
 	int rc;
 	int dac, return_code;
 	InquiryData_struct *inq_buff;
@@ -4142,6 +4225,53 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 		printk(KERN_ERR "cciss: out of memory");
 		goto clean4;
 	}
+
+	/* Need space for temp scatter list */
+	hba[i]->scatter_list = kmalloc(hba[i]->max_commands *
+						sizeof(struct scatterlist *),
+						GFP_KERNEL);
+	for (k = 0; k < hba[i]->nr_cmds; k++) {
+		hba[i]->scatter_list[k] = kmalloc(sizeof(struct scatterlist) *
+							hba[i]->maxsgentries,
+							GFP_KERNEL);
+		if (hba[i]->scatter_list[k] == NULL) {
+			printk(KERN_ERR "cciss%d: could not allocate "
+				"s/g lists\n", i);
+			goto clean4;
+		}
+	}
+	hba[i]->cmd_sg_list = kmalloc(sizeof(struct Cmd_sg_list *) *
+						hba[i]->nr_cmds,
+						GFP_KERNEL);
+	if (!hba[i]->cmd_sg_list) {
+		printk(KERN_ERR "cciss%d: Cannot get memory for "
+			"s/g chaining.\n", i);
+		goto clean4;
+	}
+	/* Build up chain blocks for each command */
+	if (hba[i]->chainsize > 0) {
+		for (j = 0; j < hba[i]->nr_cmds; j++) {
+			hba[i]->cmd_sg_list[j] =
+					kmalloc(sizeof(struct Cmd_sg_list),
+							GFP_KERNEL);
+			if (!hba[i]->cmd_sg_list[j]) {
+				printk(KERN_ERR "cciss%d: Cannot get memory "
+					"for chain block.\n", i);
+				goto clean4;
+			}
+			/* Need a block of chainsized s/g elements. */
+			hba[i]->cmd_sg_list[j]->sgchain =
+					kmalloc((hba[i]->chainsize *
+						sizeof(SGDescriptor_struct)),
+						GFP_KERNEL);
+			if (!hba[i]->cmd_sg_list[j]->sgchain) {
+				printk(KERN_ERR "cciss%d: Cannot get memory "
+					"for s/g chains\n", i);
+				goto clean4;
+			}
+		}
+	}
+
 	spin_lock_init(&hba[i]->lock);
 
 	/* Initialize the pdev driver private data.
@@ -4187,7 +4317,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 
 	cciss_procinit(i);
 
-	hba[i]->cciss_max_sectors = 2048;
+	hba[i]->cciss_max_sectors = 8192;
 
 	rebuild_lun_table(hba[i], 1, 0);
 	hba[i]->busy_initializing = 0;
@@ -4195,6 +4325,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 
 clean4:
 	kfree(hba[i]->cmd_pool_bits);
+	/* Free up sg elements */
+	for (k = 0; k < hba[i]->nr_cmds; k++)
+		kfree(hba[i]->scatter_list[k]);
+	kfree(hba[i]->scatter_list);
+	for (j = 0; j < hba[i]->nr_cmds; j++) {
+		if (hba[i]->cmd_sg_list[j])
+			kfree(hba[i]->cmd_sg_list[j]->sgchain);
+		kfree(hba[i]->cmd_sg_list[j]);
+	}
 	if (hba[i]->cmd_pool)
 		pci_free_consistent(hba[i]->pdev,
 				    hba[i]->nr_cmds * sizeof(CommandList_struct),
@@ -4308,6 +4447,14 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
 	pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
 			    hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
 	kfree(hba[i]->cmd_pool_bits);
+	/* Free up sg elements */
+	for (j = 0; j < hba[i]->nr_cmds; j++)
+		kfree(hba[i]->scatter_list[j]);
+	kfree(hba[i]->scatter_list);
+	for (j = 0; j < hba[i]->nr_cmds; j++) {
+		kfree(hba[i]->cmd_sg_list[j]->sgchain);
+		kfree(hba[i]->cmd_sg_list[j]);
+	}
 	/*
 	 * Deliberately omit pci_disable_device(): it does something nasty to
 	 * Smart Array controllers that pci_enable_device does not undo
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 31524cf..e5c63e5 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -55,7 +55,13 @@ typedef struct _drive_info_struct
 	char device_initialized;     /* indicates whether dev is initialized */
 } drive_info_struct;
 
-struct ctlr_info 
+struct Cmd_sg_list {
+	SGDescriptor_struct	*sgchain;
+	dma64_addr_t		sg_chain_dma;
+	int			chain_block_size;
+};
+
+struct ctlr_info
 {
 	int	ctlr;
 	char	devname[8];
@@ -75,6 +81,16 @@ struct ctlr_info
 	int	num_luns;
 	int 	highest_lun;
 	int	usage_count;  /* number of opens all all minor devices */
+	/* Need space for temp sg list
+	 * number of scatter/gathers supported
+	 * number of scatter/gathers in chained block
+	 */
+	struct	scatterlist **scatter_list;
+	int	maxsgentries;
+	int	chainsize;
+	int	max_cmd_sgentries;
+	struct Cmd_sg_list **cmd_sg_list;
+
 #	define DOORBELL_INT	0
 #	define PERF_MODE_INT	1
 #	define SIMPLE_MODE_INT	2
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index dbaed1e..b50a9b2 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -7,7 +7,8 @@
 
 //general boundary defintions
 #define SENSEINFOBYTES          32//note that this value may vary between host implementations
-#define MAXSGENTRIES            31
+#define MAXSGENTRIES            32
+#define CCISS_SG_CHAIN          0x80000000
 #define MAXREPLYQS              256
 
 //Command Status value
@@ -319,6 +320,10 @@ typedef struct _CfgTable_struct {
   BYTE             ServerName[16];
   DWORD            HeartBeat;
   DWORD            SCSI_Prefetch;
+  DWORD            MaxSGElements;
+  DWORD            MaxLogicalUnits;
+  DWORD            MaxPhysicalDrives;
+  DWORD            MaxPhysicalDrivesPerLogicalUnit;
 } CfgTable_struct;
 #pragma pack()	 
 #endif // CCISS_CMD_H


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 11/11] cciss: Fix weird usage of ENXIO in cciss_scsi.c
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (9 preceding siblings ...)
  2009-11-12 18:50 ` [PATCH 10/11] cciss: Add enhanced scatter-gather support Stephen M. Cameron
@ 2009-11-12 18:50 ` Stephen M. Cameron
  2009-11-13  7:46 ` [PATCH 00/11] cciss: driver updates Jens Axboe
  11 siblings, 0 replies; 13+ messages in thread
From: Stephen M. Cameron @ 2009-11-12 18:50 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel, mikem, achiang, brace

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

cciss: Fix weird usage of ENXIO in cciss_scsi.c

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/block/cciss.c      |    7 ++-----
 drivers/block/cciss_scsi.c |    2 +-
 2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1bd313d..eab81c6 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -422,12 +422,9 @@ cciss_proc_write(struct file *file, const char __user *buf,
 	if (strncmp(ENGAGE_SCSI, buffer, sizeof ENGAGE_SCSI - 1) == 0) {
 		struct seq_file *seq = file->private_data;
 		ctlr_info_t *h = seq->private;
-		int rc;
 
-		rc = cciss_engage_scsi(h->ctlr);
-		if (rc != 0)
-			err = -rc;
-		else
+		err = cciss_engage_scsi(h->ctlr);
+		if (err == 0)
 			err = length;
 	} else
 #endif /* CONFIG_CISS_SCSI_TAPE */
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 237d2b3..5d0e46d 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1547,7 +1547,7 @@ cciss_engage_scsi(int ctlr)
 	if (sa->registered) {
 		printk("cciss%d: SCSI subsystem already engaged.\n", ctlr);
 		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-		return ENXIO;
+		return -ENXIO;
 	}
 	sa->registered = 1;
 	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 00/11] cciss: driver updates
  2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
                   ` (10 preceding siblings ...)
  2009-11-12 18:50 ` [PATCH 11/11] cciss: Fix weird usage of ENXIO in cciss_scsi.c Stephen M. Cameron
@ 2009-11-13  7:46 ` Jens Axboe
  11 siblings, 0 replies; 13+ messages in thread
From: Jens Axboe @ 2009-11-13  7:46 UTC (permalink / raw)
  To: Stephen M. Cameron; +Cc: akpm, linux-kernel, mikem, achiang, brace

On Thu, Nov 12 2009, Stephen M. Cameron wrote:
> Updates for cciss, main items are: retry driver initiated commands
> on unit attention condition, do not automatically rescan for devices
> on unit attention, support for more scatter gather elements and larger
> transfers.

Thanks Stephen, applied for 2.6.33.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-11-13  7:46 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-12 18:49 [PATCH 00/11] cciss: driver updates Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 01/11] cciss: Make device attributes static Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 02/11] cciss: Fix problem with remove_from_scan_list on driver unload Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 03/11] cciss: Retry driver initiated cmds with unit attention condition Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 04/11] cciss: Remove the "withirq" parameter from various functions where possible Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 05/11] cciss: clean up code in cciss_shutdown Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 06/11] cciss: remove sendcmd() as it is no longer used Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 07/11] cciss: fix typo that causes scsi status to be lost Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 08/11] cciss: Remove unnecessary check in scan_thread Stephen M. Cameron
2009-11-12 18:49 ` [PATCH 09/11] cciss: Do not automatically rescan on UNIT ATTENTION/LUN DATA CHANGED Stephen M. Cameron
2009-11-12 18:50 ` [PATCH 10/11] cciss: Add enhanced scatter-gather support Stephen M. Cameron
2009-11-12 18:50 ` [PATCH 11/11] cciss: Fix weird usage of ENXIO in cciss_scsi.c Stephen M. Cameron
2009-11-13  7:46 ` [PATCH 00/11] cciss: driver updates Jens Axboe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.