All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] hpsa: updates, January 2011
@ 2011-01-06 20:47 Stephen M. Cameron
  2011-01-06 20:47 ` [PATCH 01/11] hpsa: defend against zero sized buffers in passthru ioctls Stephen M. Cameron
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:47 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

The following series contains a few miscellaneous fixes for hpsa.
The biggest change is to the reset_devices code to fix the
saving/restoring of PCI registers so that the "doorbell"
reset method now works on those controllers which support it.

---

Stephen M. Cameron (11):
      hpsa: defend against zero sized buffers in passthru ioctls
      hpsa: fixup DMA address before freeing.
      hpsa: Remove duplicate defines of DIRECT_LOOKUP_ constants
      hpsa: fix board status waiting code
      hpsa: Use kernel provided PCI state save and restore functions
      hpsa: limit commands allocated on reset_devices
      hpsa: do not reset unknown boards on reset_devices
      hpsa: take the adapter lock in hpsa_wait_for_mode_change_ack
      hpsa: allow driver to put controller in either simple or performant mode
      hpsa: use usleep_range not msleep for small sleeps
      hpsa: Add a per controller commands_outstanding entry in /sys


 Documentation/scsi/hpsa.txt |    6 +
 drivers/scsi/hpsa.c         |  210 ++++++++++++++++++++++---------------------
 drivers/scsi/hpsa.h         |    4 +
 drivers/scsi/hpsa_cmd.h     |    1 
 4 files changed, 119 insertions(+), 102 deletions(-)

-- 
-- steve

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

* [PATCH 01/11] hpsa: defend against zero sized buffers in passthru ioctls
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
@ 2011-01-06 20:47 ` Stephen M. Cameron
  2011-01-06 20:47 ` [PATCH 02/11] hpsa: fixup DMA address before freeing Stephen M. Cameron
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:47 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/scsi/hpsa.c |   36 ++++++++++++++++--------------------
 1 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 12deffc..e4b5f3c 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2433,15 +2433,17 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		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;
+		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);
 		}
-	} else
-		memset(buff, 0, iocommand.buf_size);
+	}
 	c = cmd_special_alloc(h);
 	if (c == NULL) {
 		kfree(buff);
@@ -2487,8 +2489,8 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		cmd_special_free(h, c);
 		return -EFAULT;
 	}
-
-	if (iocommand.Request.Type.Direction == XFER_READ) {
+	if (iocommand.Request.Type.Direction == XFER_READ &&
+		iocommand.buf_size > 0) {
 		/* Copy the data out of the buffer we created */
 		if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
 			kfree(buff);
@@ -2581,14 +2583,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *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 = c->Header.SGTotal = sg_used;
 	memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
 	c->Header.Tag.lower = c->busaddr;
 	memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
@@ -2605,7 +2600,8 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		}
 	}
 	hpsa_scsi_do_simple_cmd_core(h, c);
-	hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
+	if (sg_used)
+		hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
 	check_ioctl_unit_attention(h, c);
 	/* Copy the error information out */
 	memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info));
@@ -2614,7 +2610,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		status = -EFAULT;
 		goto cleanup1;
 	}
-	if (ioc->Request.Type.Direction == XFER_READ) {
+	if (ioc->Request.Type.Direction == XFER_READ && ioc->buf_size > 0) {
 		/* Copy the data out of the buffer we created */
 		BYTE __user *ptr = ioc->buf;
 		for (i = 0; i < sg_used; i++) {


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

* [PATCH 02/11] hpsa: fixup DMA address before freeing.
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
  2011-01-06 20:47 ` [PATCH 01/11] hpsa: defend against zero sized buffers in passthru ioctls Stephen M. Cameron
@ 2011-01-06 20:47 ` Stephen M. Cameron
  2011-01-06 20:47 ` [PATCH 03/11] hpsa: Remove duplicate defines of DIRECT_LOOKUP_ constants Stephen M. Cameron
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:47 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

From: Stephen M. Cameron <StephenM.Cameron>

Some low bits might have been set by the driver, causing
a message like this to come out:

 [   13.288062] ------------[ cut here ]------------
 [   13.293211] WARNING: at lib/dma-debug.c:803 check_unmap+0x1a1/0x654()
 [   13.300387] Hardware name: ProLiant DL180 G6
 [   13.305335] hpsa 0000:06:00.0: DMA-API: device driver tries to free
 DMA memory it has not allocated [device address=0x000000007f81e001]
 [size=640 bytes]

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index e4b5f3c..e2089a3 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2267,7 +2267,7 @@ static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
 	pci_free_consistent(h->pdev, sizeof(*c->err_info),
 			    c->err_info, (dma_addr_t) temp64.val);
 	pci_free_consistent(h->pdev, sizeof(*c),
-			    c, (dma_addr_t) c->busaddr);
+			    c, (dma_addr_t) (c->busaddr & DIRECT_LOOKUP_MASK));
 }
 
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index f5c4c3c..7910c14 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -265,6 +265,7 @@ struct ErrorInfo {
 
 #define DIRECT_LOOKUP_SHIFT 5
 #define DIRECT_LOOKUP_BIT 0x10
+#define DIRECT_LOOKUP_MASK (~((1 << DIRECT_LOOKUP_SHIFT) - 1))
 
 #define HPSA_ERROR_BIT          0x02
 struct ctlr_info; /* defined in hpsa.h */


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

* [PATCH 03/11] hpsa: Remove duplicate defines of DIRECT_LOOKUP_ constants
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
  2011-01-06 20:47 ` [PATCH 01/11] hpsa: defend against zero sized buffers in passthru ioctls Stephen M. Cameron
  2011-01-06 20:47 ` [PATCH 02/11] hpsa: fixup DMA address before freeing Stephen M. Cameron
@ 2011-01-06 20:47 ` Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 04/11] hpsa: fix board status waiting code Stephen M. Cameron
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:47 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

From: Stephen M. Cameron <StephenM.Cameron>

They are defined in hpsa_cmd.h

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index e2089a3..b345cc4 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2863,13 +2863,11 @@ static inline void finish_cmd(struct CommandList *c, u32 raw_tag)
 
 static inline u32 hpsa_tag_contains_index(u32 tag)
 {
-#define DIRECT_LOOKUP_BIT 0x10
 	return tag & DIRECT_LOOKUP_BIT;
 }
 
 static inline u32 hpsa_tag_to_index(u32 tag)
 {
-#define DIRECT_LOOKUP_SHIFT 5
 	return tag >> DIRECT_LOOKUP_SHIFT;
 }
 


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

* [PATCH 04/11] hpsa: fix board status waiting code
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
                   ` (2 preceding siblings ...)
  2011-01-06 20:47 ` [PATCH 03/11] hpsa: Remove duplicate defines of DIRECT_LOOKUP_ constants Stephen M. Cameron
@ 2011-01-06 20:48 ` Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 05/11] hpsa: Use kernel provided PCI state save and restore functions Stephen M. Cameron
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:48 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

After a reset, we should first wait for the board to become "not ready",
and then wait for it to become "ready", instead of immediately
waiting for it to become "ready", and do this waiting *after*
restoring PCI config space registers.  Also, only wait 10 secs
for board to become "not ready" after a reset (it should quickly
become not ready.)

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/scsi/hpsa.c |   44 ++++++++++++++++++++++++++++++++++++--------
 drivers/scsi/hpsa.h |    4 ++++
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index b345cc4..cfd30ad 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -173,6 +173,10 @@ static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
 static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
 	unsigned long *memory_bar);
 static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
+static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
+	void __iomem *vaddr, int wait_for_ready);
+#define BOARD_NOT_READY 0
+#define BOARD_READY 1
 
 static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
 static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
@@ -3237,6 +3241,20 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	   need a little pause here */
 	msleep(HPSA_POST_RESET_PAUSE_MSECS);
 
+	/* Wait for board to become not ready, then ready. */
+	dev_info(&pdev->dev, "Waiting for board to become ready.\n");
+	rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
+	if (rc)
+		dev_warn(&pdev->dev,
+			"failed waiting for board to become not ready\n");
+	rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY);
+	if (rc) {
+		dev_warn(&pdev->dev,
+			"failed waiting for board to become ready\n");
+		goto unmap_cfgtable;
+	}
+	dev_info(&pdev->dev, "board ready.\n");
+
 	/* Controller should be in simple mode at this point.  If it's not,
 	 * It means we're on one of those controllers which doesn't support
 	 * the doorbell reset method and on which the PCI power management reset
@@ -3432,18 +3450,28 @@ static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
 	return -ENODEV;
 }
 
-static int __devinit hpsa_wait_for_board_ready(struct ctlr_info *h)
+static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
+	void __iomem *vaddr, int wait_for_ready)
 {
-	int i;
+	int i, iterations;
 	u32 scratchpad;
+	if (wait_for_ready)
+		iterations = HPSA_BOARD_READY_ITERATIONS;
+	else
+		iterations = HPSA_BOARD_NOT_READY_ITERATIONS;
 
-	for (i = 0; i < HPSA_BOARD_READY_ITERATIONS; i++) {
-		scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
-		if (scratchpad == HPSA_FIRMWARE_READY)
-			return 0;
+	for (i = 0; i < iterations; i++) {
+		scratchpad = readl(vaddr + SA5_SCRATCHPAD_OFFSET);
+		if (wait_for_ready) {
+			if (scratchpad == HPSA_FIRMWARE_READY)
+				return 0;
+		} else {
+			if (scratchpad != HPSA_FIRMWARE_READY)
+				return 0;
+		}
 		msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS);
 	}
-	dev_warn(&h->pdev->dev, "board not ready, timed out.\n");
+	dev_warn(&pdev->dev, "board not ready, timed out.\n");
 	return -ENODEV;
 }
 
@@ -3635,7 +3663,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)
 		err = -ENOMEM;
 		goto err_out_free_res;
 	}
-	err = hpsa_wait_for_board_ready(h);
+	err = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY);
 	if (err)
 		goto err_out_free_res;
 	err = hpsa_find_cfgtables(h);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 19586e1..074d237 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -154,12 +154,16 @@ struct ctlr_info {
  * HPSA_BOARD_READY_ITERATIONS are derived from those.
  */
 #define HPSA_BOARD_READY_WAIT_SECS (120)
+#define HPSA_BOARD_NOT_READY_WAIT_SECS (10)
 #define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100)
 #define HPSA_BOARD_READY_POLL_INTERVAL \
 	((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000)
 #define HPSA_BOARD_READY_ITERATIONS \
 	((HPSA_BOARD_READY_WAIT_SECS * 1000) / \
 		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
+#define HPSA_BOARD_NOT_READY_ITERATIONS \
+	((HPSA_BOARD_NOT_READY_WAIT_SECS * 1000) / \
+		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
 #define HPSA_POST_RESET_PAUSE_MSECS (3000)
 #define HPSA_POST_RESET_NOOP_RETRIES (12)
 


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

* [PATCH 05/11] hpsa: Use kernel provided PCI state save and restore functions
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
                   ` (3 preceding siblings ...)
  2011-01-06 20:48 ` [PATCH 04/11] hpsa: fix board status waiting code Stephen M. Cameron
@ 2011-01-06 20:48 ` Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 06/11] hpsa: limit commands allocated on reset_devices Stephen M. Cameron
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:48 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

and use the doorbell reset method if available (which doesn't
lock up the controller if you properly save and restore all
the PCI registers that you're supposed to.)

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/scsi/hpsa.c |   81 +++++++++------------------------------------------
 1 files changed, 15 insertions(+), 66 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index cfd30ad..82b94e2 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3053,38 +3053,6 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 #define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
 #define hpsa_noop(p) hpsa_message(p, 3, 0)
 
-static __devinit int hpsa_reset_msi(struct pci_dev *pdev)
-{
-/* the #defines are stolen from drivers/pci/msi.h. */
-#define msi_control_reg(base)		(base + PCI_MSI_FLAGS)
-#define PCI_MSIX_FLAGS_ENABLE		(1 << 15)
-
-	int pos;
-	u16 control = 0;
-
-	pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
-	if (pos) {
-		pci_read_config_word(pdev, msi_control_reg(pos), &control);
-		if (control & PCI_MSI_FLAGS_ENABLE) {
-			dev_info(&pdev->dev, "resetting MSI\n");
-			pci_write_config_word(pdev, msi_control_reg(pos),
-					control & ~PCI_MSI_FLAGS_ENABLE);
-		}
-	}
-
-	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
-	if (pos) {
-		pci_read_config_word(pdev, msi_control_reg(pos), &control);
-		if (control & PCI_MSIX_FLAGS_ENABLE) {
-			dev_info(&pdev->dev, "resetting MSI-X\n");
-			pci_write_config_word(pdev, msi_control_reg(pos),
-					control & ~PCI_MSIX_FLAGS_ENABLE);
-		}
-	}
-
-	return 0;
-}
-
 static int hpsa_controller_hard_reset(struct pci_dev *pdev,
 	void * __iomem vaddr, bool use_doorbell)
 {
@@ -3140,17 +3108,17 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
  */
 static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 {
-	u16 saved_config_space[32];
 	u64 cfg_offset;
 	u32 cfg_base_addr;
 	u64 cfg_base_addr_index;
 	void __iomem *vaddr;
 	unsigned long paddr;
 	u32 misc_fw_support, active_transport;
-	int rc, i;
+	int rc;
 	struct CfgTable __iomem *cfgtable;
 	bool use_doorbell;
 	u32 board_id;
+	u16 command_register;
 
 	/* For controllers as old as the P600, this is very nearly
 	 * the same thing as
@@ -3160,14 +3128,6 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	 * pci_set_power_state(pci_dev, PCI_D0);
 	 * pci_restore_state(pci_dev);
 	 *
-	 * but we can't use these nice canned kernel routines on
-	 * kexec, because they also check the MSI/MSI-X state in PCI
-	 * configuration space and do the wrong thing when it is
-	 * set/cleared.  Also, the pci_save/restore_state functions
-	 * violate the ordering requirements for restoring the
-	 * configuration space from the CCISS document (see the
-	 * comment below).  So we roll our own ....
-	 *
 	 * For controllers newer than the P600, the pci power state
 	 * method of resetting doesn't work so we have another way
 	 * using the doorbell register.
@@ -3184,9 +3144,13 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	if (board_id == 0x409C0E11 || board_id == 0x409D0E11)
 		return -ENOTSUPP;
 
-	for (i = 0; i < 32; i++)
-		pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
-
+	/* Save the PCI command register */
+	pci_read_config_word(pdev, 4, &command_register);
+	/* Turn the board off.  This is so that later pci_restore_state()
+	 * won't turn the board on before the rest of config space is ready.
+	 */
+	pci_disable_device(pdev);
+	pci_save_state(pdev);
 
 	/* find the first memory BAR, so we can find the cfg table */
 	rc = hpsa_pci_find_memory_BAR(pdev, &paddr);
@@ -3212,30 +3176,17 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	misc_fw_support = readl(&cfgtable->misc_fw_support);
 	use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
 
-	/* The doorbell reset seems to cause lockups on some Smart
-	 * Arrays (e.g. P410, P410i, maybe others).  Until this is
-	 * fixed or at least isolated, avoid the doorbell reset.
-	 */
-	use_doorbell = 0;
-
 	rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell);
 	if (rc)
 		goto unmap_cfgtable;
 
-	/* Restore the PCI configuration space.  The Open CISS
-	 * Specification says, "Restore the PCI Configuration
-	 * Registers, offsets 00h through 60h. It is important to
-	 * restore the command register, 16-bits at offset 04h,
-	 * last. Do not restore the configuration status register,
-	 * 16-bits at offset 06h."  Note that the offset is 2*i.
-	 */
-	for (i = 0; i < 32; i++) {
-		if (i == 2 || i == 3)
-			continue;
-		pci_write_config_word(pdev, 2*i, saved_config_space[i]);
+	pci_restore_state(pdev);
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		dev_warn(&pdev->dev, "failed to enable device.\n");
+		goto unmap_cfgtable;
 	}
-	wmb();
-	pci_write_config_word(pdev, 4, saved_config_space[2]);
+	pci_write_config_word(pdev, 4, command_register);
 
 	/* Some devices (notably the HP Smart Array 5i Controller)
 	   need a little pause here */
@@ -3732,8 +3683,6 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
 		return 0; /* just try to do the kdump anyhow. */
 	if (rc)
 		return -ENODEV;
-	if (hpsa_reset_msi(pdev))
-		return -ENODEV;
 
 	/* Now try to get the controller to respond to a no-op */
 	for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {


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

* [PATCH 06/11] hpsa: limit commands allocated on reset_devices
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
                   ` (4 preceding siblings ...)
  2011-01-06 20:48 ` [PATCH 05/11] hpsa: Use kernel provided PCI state save and restore functions Stephen M. Cameron
@ 2011-01-06 20:48 ` Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 07/11] hpsa: do not reset unknown boards " Stephen M. Cameron
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:48 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

This is to conserve memory in a memory-limited kdump scenario

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 82b94e2..688b243 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3470,6 +3470,11 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
 static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
 {
 	h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
+
+	/* Limit commands in memory limited kdump scenario. */
+	if (reset_devices && h->max_commands > 32)
+		h->max_commands = 32;
+
 	if (h->max_commands < 16) {
 		dev_warn(&h->pdev->dev, "Controller reports "
 			"max supported commands of %d, an obvious lie. "


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

* [PATCH 07/11] hpsa: do not reset unknown boards on reset_devices
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
                   ` (5 preceding siblings ...)
  2011-01-06 20:48 ` [PATCH 06/11] hpsa: limit commands allocated on reset_devices Stephen M. Cameron
@ 2011-01-06 20:48 ` Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 08/11] hpsa: take the adapter lock in hpsa_wait_for_mode_change_ack Stephen M. Cameron
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:48 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

This is to prevent hpsa from resetting older boards
which the cciss driver may be controlling.

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 688b243..5b9cd41 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3140,7 +3140,11 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	 * likely not be happy.  Just forbid resetting this conjoined mess.
 	 * The 640x isn't really supported by hpsa anyway.
 	 */
-	hpsa_lookup_board_id(pdev, &board_id);
+	rc = hpsa_lookup_board_id(pdev, &board_id);
+	if (rc < 0) {
+		dev_warn(&pdev->dev, "Not resetting device.\n");
+		return -ENODEV;
+	}
 	if (board_id == 0x409C0E11 || board_id == 0x409D0E11)
 		return -ENOTSUPP;
 


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

* [PATCH 08/11] hpsa: take the adapter lock in hpsa_wait_for_mode_change_ack
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
                   ` (6 preceding siblings ...)
  2011-01-06 20:48 ` [PATCH 07/11] hpsa: do not reset unknown boards " Stephen M. Cameron
@ 2011-01-06 20:48 ` Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 09/11] hpsa: allow driver to put controller in either simple or performant mode Stephen M. Cameron
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:48 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

Need to take the lock while accessing the register to check to
see if config table changes have taken effect.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 drivers/scsi/hpsa.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 5b9cd41..4fb62c2 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3553,13 +3553,18 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)
 static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
 {
 	int i;
+	u32 doorbell_value;
+	unsigned long flags;
 
 	/* under certain very rare conditions, this can take awhile.
 	 * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
 	 * as we enter this code.)
 	 */
 	for (i = 0; i < MAX_CONFIG_WAIT; i++) {
-		if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+		spin_lock_irqsave(&h->lock, flags);
+		doorbell_value = readl(h->vaddr + SA5_DOORBELL);
+		spin_unlock_irqrestore(&h->lock, flags);
+		if (!doorbell_value & CFGTBL_ChangeReq)
 			break;
 		/* delay and try again */
 		msleep(10);
@@ -3731,6 +3736,8 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
 	h->busy_initializing = 1;
 	INIT_HLIST_HEAD(&h->cmpQ);
 	INIT_HLIST_HEAD(&h->reqQ);
+	spin_lock_init(&h->lock);
+	spin_lock_init(&h->scan_lock);
 	rc = hpsa_pci_init(h);
 	if (rc != 0)
 		goto clean1;
@@ -3790,8 +3797,6 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
 	}
 	if (hpsa_allocate_sg_chain_blocks(h))
 		goto clean4;
-	spin_lock_init(&h->lock);
-	spin_lock_init(&h->scan_lock);
 	init_waitqueue_head(&h->scan_wait_queue);
 	h->scan_finished = 1; /* no scan currently in progress */
 


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

* [PATCH 09/11] hpsa: allow driver to put controller in either simple or performant mode
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
                   ` (7 preceding siblings ...)
  2011-01-06 20:48 ` [PATCH 08/11] hpsa: take the adapter lock in hpsa_wait_for_mode_change_ack Stephen M. Cameron
@ 2011-01-06 20:48 ` Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 10/11] hpsa: use usleep_range not msleep for small sleeps Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 11/11] hpsa: Add a per controller commands_outstanding entry in /sys Stephen M. Cameron
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:48 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
---
 Documentation/scsi/hpsa.txt |    6 ++++++
 drivers/scsi/hpsa.c         |    7 +++++++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/Documentation/scsi/hpsa.txt b/Documentation/scsi/hpsa.txt
index dca6583..b14e6ee 100644
--- a/Documentation/scsi/hpsa.txt
+++ b/Documentation/scsi/hpsa.txt
@@ -28,6 +28,12 @@ boot parameter "hpsa_allow_any=1" is specified, however these are not tested
 nor supported by HP with this driver.  For older Smart Arrays, the cciss
 driver should still be used.
 
+The "hpsa_simple_mode=1" boot parameter may be used to prevent the driver from
+putting the controller into "performant" mode.  The difference is that with simple
+mode, each command completion requires an interrupt, while with "performant mode"
+(the default, and ordinarily better performing) it is possible to have multiple
+command completions indicated by a single interrupt.
+
 HPSA specific entries in /sys
 -----------------------------
 
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 4fb62c2..10076f1 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -74,6 +74,10 @@ static int hpsa_allow_any;
 module_param(hpsa_allow_any, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(hpsa_allow_any,
 		"Allow hpsa driver to access unknown HP Smart Array hardware");
+static int hpsa_simple_mode;
+module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hpsa_simple_mode,
+	"Use 'simple mode' rather than 'performant mode'");
 
 /* define the PCI info for the cards we can control */
 static const struct pci_device_id hpsa_pci_device_id[] = {
@@ -4038,6 +4042,9 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
 {
 	u32 trans_support;
 
+	if (hpsa_simple_mode)
+		return;
+
 	trans_support = readl(&(h->cfgtable->TransportSupport));
 	if (!(trans_support & PERFORMANT_MODE))
 		return;


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

* [PATCH 10/11] hpsa: use usleep_range not msleep for small sleeps
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
                   ` (8 preceding siblings ...)
  2011-01-06 20:48 ` [PATCH 09/11] hpsa: allow driver to put controller in either simple or performant mode Stephen M. Cameron
@ 2011-01-06 20:48 ` Stephen M. Cameron
  2011-01-06 20:48 ` [PATCH 11/11] hpsa: Add a per controller commands_outstanding entry in /sys Stephen M. Cameron
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:48 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 10076f1..ddd729e 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3571,7 +3571,7 @@ static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
 		if (!doorbell_value & CFGTBL_ChangeReq)
 			break;
 		/* delay and try again */
-		msleep(10);
+		usleep_range(10000, 20000);
 	}
 }
 


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

* [PATCH 11/11] hpsa: Add a per controller commands_outstanding entry in /sys
  2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
                   ` (9 preceding siblings ...)
  2011-01-06 20:48 ` [PATCH 10/11] hpsa: use usleep_range not msleep for small sleeps Stephen M. Cameron
@ 2011-01-06 20:48 ` Stephen M. Cameron
  10 siblings, 0 replies; 12+ messages in thread
From: Stephen M. Cameron @ 2011-01-06 20:48 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, mike.miller, linux-kernel, thenzl, akpm, smcameron

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

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index ddd729e..c255f46 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -159,6 +159,8 @@ static ssize_t unique_id_show(struct device *dev,
 	struct device_attribute *attr, char *buf);
 static ssize_t host_show_firmware_revision(struct device *dev,
 	     struct device_attribute *attr, char *buf);
+static ssize_t host_show_commands_outstanding(struct device *dev,
+	     struct device_attribute *attr, char *buf);
 static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno);
 static ssize_t host_store_rescan(struct device *dev,
 	 struct device_attribute *attr, const char *buf, size_t count);
@@ -188,6 +190,8 @@ static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
 static DEVICE_ATTR(firmware_revision, S_IRUGO,
 	host_show_firmware_revision, NULL);
+static DEVICE_ATTR(commands_outstanding, S_IRUGO,
+	host_show_commands_outstanding, NULL);
 
 static struct device_attribute *hpsa_sdev_attrs[] = {
 	&dev_attr_raid_level,
@@ -199,6 +203,7 @@ static struct device_attribute *hpsa_sdev_attrs[] = {
 static struct device_attribute *hpsa_shost_attrs[] = {
 	&dev_attr_rescan,
 	&dev_attr_firmware_revision,
+	&dev_attr_commands_outstanding,
 	NULL,
 };
 
@@ -299,6 +304,15 @@ static ssize_t host_show_firmware_revision(struct device *dev,
 		fwrev[0], fwrev[1], fwrev[2], fwrev[3]);
 }
 
+static ssize_t host_show_commands_outstanding(struct device *dev,
+	     struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct ctlr_info *h = shost_to_hba(shost);
+
+	return snprintf(buf, 20, "%d\n", h->commands_outstanding);
+}
+
 /* Enqueuing and dequeuing functions for cmdlists. */
 static inline void addQ(struct hlist_head *list, struct CommandList *c)
 {


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

end of thread, other threads:[~2011-01-06 20:48 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-06 20:47 [PATCH 00/11] hpsa: updates, January 2011 Stephen M. Cameron
2011-01-06 20:47 ` [PATCH 01/11] hpsa: defend against zero sized buffers in passthru ioctls Stephen M. Cameron
2011-01-06 20:47 ` [PATCH 02/11] hpsa: fixup DMA address before freeing Stephen M. Cameron
2011-01-06 20:47 ` [PATCH 03/11] hpsa: Remove duplicate defines of DIRECT_LOOKUP_ constants Stephen M. Cameron
2011-01-06 20:48 ` [PATCH 04/11] hpsa: fix board status waiting code Stephen M. Cameron
2011-01-06 20:48 ` [PATCH 05/11] hpsa: Use kernel provided PCI state save and restore functions Stephen M. Cameron
2011-01-06 20:48 ` [PATCH 06/11] hpsa: limit commands allocated on reset_devices Stephen M. Cameron
2011-01-06 20:48 ` [PATCH 07/11] hpsa: do not reset unknown boards " Stephen M. Cameron
2011-01-06 20:48 ` [PATCH 08/11] hpsa: take the adapter lock in hpsa_wait_for_mode_change_ack Stephen M. Cameron
2011-01-06 20:48 ` [PATCH 09/11] hpsa: allow driver to put controller in either simple or performant mode Stephen M. Cameron
2011-01-06 20:48 ` [PATCH 10/11] hpsa: use usleep_range not msleep for small sleeps Stephen M. Cameron
2011-01-06 20:48 ` [PATCH 11/11] hpsa: Add a per controller commands_outstanding entry in /sys Stephen M. Cameron

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.