linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] hpsa: resend of November 2013 patches
@ 2013-12-04 23:09 Stephen M. Cameron
  2013-12-04 23:09 ` [PATCH 1/9] hpsa: revert bring logical drives online when format completes Stephen M. Cameron
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:09 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

This updated series applies on top of the "misc" branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git

Note: the first two patches in this series revert previously
applied patches which I had not previously realized were present
in James's tree.

There's one extra patch in this set that wasn't present in the series
I sent in November to allow the SCSI mid layer to handle unit attn's.

Patches from the November series that are already present in James's
tree are not in this patch series.

And, finally if this is all too confusing and you want me to send
something else, let me know.

---

Matt Gates (1):
      hpsa: allow SCSI mid layer to handle unit attention

Stephen M. Cameron (8):
      hpsa: revert bring logical drives online when format completes
      hpsa: revert hide logical drives with format in progress from linux
      hpsa: return 0 from driver probe function on success, not 1
      hpsa: use workqueue instead of kernel thread for lockup detection
      hpsa: rename scsi prefetch field
      hpsa: enable unit attention reporting
      hpsa: do not discard scsi status on aborted commands
      hpsa: do not require board "not ready" status after hard reset


 drivers/scsi/hpsa.c     |  321 ++++++-----------------------------------------
 drivers/scsi/hpsa.h     |   17 --
 drivers/scsi/hpsa_cmd.h |    4 -
 3 files changed, 45 insertions(+), 297 deletions(-)

-- 

-- steve


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

* [PATCH 1/9] hpsa: revert bring logical drives online when format completes
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
@ 2013-12-04 23:09 ` Stephen M. Cameron
  2013-12-04 23:09 ` [PATCH 2/9] hpsa: revert hide logical drives with format in progress from linux Stephen M. Cameron
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:09 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

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

This relies on a kernel thread which I wish to remove and
replace with a work queue based solution.

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 89f50c3..961332b 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -220,8 +220,6 @@ static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
 static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr,
 				     int wait_for_ready);
 static inline void finish_cmd(struct CommandList *c);
-static unsigned char hpsa_format_in_progress(struct ctlr_info *h,
-		unsigned char scsi3addr[]);
 #define BOARD_NOT_READY 0
 #define BOARD_READY 1
 
@@ -945,112 +943,6 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
 	return DEVICE_NOT_FOUND;
 }
 
-#define OFFLINE_DEVICE_POLL_INTERVAL (120 * HZ)
-static int hpsa_offline_device_thread(void *v)
-{
-	struct ctlr_info *h = v;
-	unsigned long flags;
-	struct offline_device_entry *d;
-	unsigned char need_rescan = 0;
-	struct list_head *this, *tmp;
-
-	while (1) {
-		schedule_timeout_interruptible(OFFLINE_DEVICE_POLL_INTERVAL);
-		if (kthread_should_stop())
-			break;
-
-		/* Check if any of the offline devices have become ready */
-		spin_lock_irqsave(&h->offline_device_lock, flags);
-		list_for_each_safe(this, tmp, &h->offline_device_list) {
-			d = list_entry(this, struct offline_device_entry,
-					offline_list);
-			spin_unlock_irqrestore(&h->offline_device_lock, flags);
-			if (!hpsa_format_in_progress(h, d->scsi3addr)) {
-				need_rescan = 1;
-				goto do_rescan;
-			}
-			spin_lock_irqsave(&h->offline_device_lock, flags);
-		}
-		spin_unlock_irqrestore(&h->offline_device_lock, flags);
-	}
-
-do_rescan:
-
-	/* Remove all entries from the list and rescan and exit this thread.
-	 * If there are still offline devices, the rescan will make a new list
-	 * and create a new offline device monitor thread.
-	 */
-	spin_lock_irqsave(&h->offline_device_lock, flags);
-	list_for_each_safe(this, tmp, &h->offline_device_list) {
-		d = list_entry(this, struct offline_device_entry, offline_list);
-		list_del_init(this);
-		kfree(d);
-	}
-	h->offline_device_monitor = NULL;
-	h->offline_device_thread_state = OFFLINE_DEVICE_THREAD_STOPPED;
-	spin_unlock_irqrestore(&h->offline_device_lock, flags);
-	if (need_rescan)
-		hpsa_scan_start(h->scsi_host);
-	return 0;
-}
-
-static void hpsa_monitor_offline_device(struct ctlr_info *h,
-					unsigned char scsi3addr[])
-{
-	struct offline_device_entry *device;
-	unsigned long flags;
-
-	/* Check to see if device is already on the list */
-	spin_lock_irqsave(&h->offline_device_lock, flags);
-	list_for_each_entry(device, &h->offline_device_list, offline_list) {
-		if (memcmp(device->scsi3addr, scsi3addr,
-				sizeof(device->scsi3addr)) == 0) {
-			spin_unlock_irqrestore(&h->offline_device_lock, flags);
-			return;
-		}
-	}
-	spin_unlock_irqrestore(&h->offline_device_lock, flags);
-
-	/* Device is not on the list, add it. */
-	device = kmalloc(sizeof(*device), GFP_KERNEL);
-	if (!device) {
-		dev_warn(&h->pdev->dev, "out of memory in %s\n", __func__);
-		return;
-	}
-	memcpy(device->scsi3addr, scsi3addr, sizeof(device->scsi3addr));
-	spin_lock_irqsave(&h->offline_device_lock, flags);
-	list_add_tail(&device->offline_list, &h->offline_device_list);
-	if (h->offline_device_thread_state == OFFLINE_DEVICE_THREAD_STOPPED) {
-		h->offline_device_thread_state = OFFLINE_DEVICE_THREAD_RUNNING;
-		spin_unlock_irqrestore(&h->offline_device_lock, flags);
-		h->offline_device_monitor =
-			kthread_run(hpsa_offline_device_thread, h, HPSA "-odm");
-		spin_lock_irqsave(&h->offline_device_lock, flags);
-	}
-	if (!h->offline_device_monitor) {
-		dev_warn(&h->pdev->dev, "failed to start offline device monitor thread.\n");
-		h->offline_device_thread_state = OFFLINE_DEVICE_THREAD_STOPPED;
-	}
-	spin_unlock_irqrestore(&h->offline_device_lock, flags);
-}
-
-static void stop_offline_device_monitor(struct ctlr_info *h)
-{
-	unsigned long flags;
-	int stop_thread;
-
-	spin_lock_irqsave(&h->offline_device_lock, flags);
-	stop_thread = (h->offline_device_thread_state ==
-				OFFLINE_DEVICE_THREAD_RUNNING);
-	if (stop_thread)
-		/* STOPPING state prevents new thread from starting. */
-		h->offline_device_thread_state =
-				OFFLINE_DEVICE_THREAD_STOPPING;
-	spin_unlock_irqrestore(&h->offline_device_lock, flags);
-	if (stop_thread)
-		kthread_stop(h->offline_device_monitor);
-}
-
 static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
 	struct hpsa_scsi_dev_t *sd[], int nsds)
 {
@@ -1123,10 +1015,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
 		 */
 		if (sd[i]->format_in_progress) {
 			dev_info(&h->pdev->dev,
-				"c%db%dt%dl%d: Logical drive parity initialization, erase or format in progress\n",
-				h->scsi_host->host_no,
-				sd[i]->bus, sd[i]->target, sd[i]->lun);
-			dev_info(&h->pdev->dev, "c%db%dt%dl%d: temporarily offline\n",
+				"Logical drive format in progress, device c%db%dt%dl%d offline.\n",
 				h->scsi_host->host_no,
 				sd[i]->bus, sd[i]->target, sd[i]->lun);
 			continue;
@@ -1150,17 +1039,6 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
 	}
 	spin_unlock_irqrestore(&h->devlock, flags);
 
-	/* Monitor devices which are NOT READY, FORMAT IN PROGRESS to be
-	 * brought online later. This must be done without holding h->devlock,
-	 * so don't touch h->dev[]
-	 */
-	for (i = 0; i < nsds; i++) {
-		if (!sd[i]) /* if already added above. */
-			continue;
-		if (sd[i]->format_in_progress)
-			hpsa_monitor_offline_device(h, sd[i]->scsi3addr);
-	}
-
 	/* Don't notify scsi mid layer of any changes the first time through
 	 * (or if there are no changes) scsi_scan_host will do it later the
 	 * first time through.
@@ -5065,10 +4943,8 @@ reinit_after_soft_reset:
 	h->intr_mode = hpsa_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
 	INIT_LIST_HEAD(&h->cmpQ);
 	INIT_LIST_HEAD(&h->reqQ);
-	INIT_LIST_HEAD(&h->offline_device_list);
 	spin_lock_init(&h->lock);
 	spin_lock_init(&h->scan_lock);
-	spin_lock_init(&h->offline_device_lock);
 	spin_lock_init(&h->passthru_count_lock);
 	rc = hpsa_pci_init(h);
 	if (rc != 0)
@@ -5077,7 +4953,6 @@ reinit_after_soft_reset:
 	sprintf(h->devname, HPSA "%d", number_of_controllers);
 	h->ctlr = number_of_controllers;
 	number_of_controllers++;
-	h->offline_device_thread_state = OFFLINE_DEVICE_THREAD_STOPPED;
 
 	/* configure PCI DMA stuff */
 	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
@@ -5256,7 +5131,6 @@ static void hpsa_remove_one(struct pci_dev *pdev)
 	}
 	h = pci_get_drvdata(pdev);
 	stop_controller_lockup_detector(h);
-	stop_offline_device_monitor(h);
 	hpsa_unregister_scsi(h);	/* unhook from SCSI subsystem */
 	hpsa_shutdown(pdev);
 	iounmap(h->vaddr);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index bea2365..04074f5 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -161,20 +161,7 @@ struct ctlr_info {
 #define HPSATMF_LOG_QRY_TASK    (1 << 23)
 #define HPSATMF_LOG_QRY_TSET    (1 << 24)
 #define HPSATMF_LOG_QRY_ASYNC   (1 << 25)
-	spinlock_t offline_device_lock;
-	struct list_head offline_device_list;
-	struct task_struct *offline_device_monitor;
-	unsigned char offline_device_thread_state;
-#define OFFLINE_DEVICE_THREAD_STOPPED 0
-#define OFFLINE_DEVICE_THREAD_STOPPING 1
-#define OFFLINE_DEVICE_THREAD_RUNNING 2
 };
-
-struct offline_device_entry {
-	unsigned char scsi3addr[8];
-	struct list_head offline_list;
-};
-
 #define HPSA_ABORT_MSG 0
 #define HPSA_DEVICE_RESET_MSG 1
 #define HPSA_RESET_TYPE_CONTROLLER 0x00


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

* [PATCH 2/9] hpsa: revert hide logical drives with format in progress from linux
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
  2013-12-04 23:09 ` [PATCH 1/9] hpsa: revert bring logical drives online when format completes Stephen M. Cameron
@ 2013-12-04 23:09 ` Stephen M. Cameron
  2013-12-04 23:10 ` [PATCH 3/9] hpsa: return 0 from driver probe function on success, not 1 Stephen M. Cameron
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:09 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

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

This relies on a kernel thread which I wish to replace with a
work queue based solution.

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 961332b..75800f7 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1007,20 +1007,6 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
 	for (i = 0; i < nsds; i++) {
 		if (!sd[i]) /* if already added above. */
 			continue;
-
-		/* Don't add devices which are NOT READY, FORMAT IN PROGRESS
-		 * as the SCSI mid-layer does not handle such devices well.
-		 * It relentlessly loops sending TUR at 3Hz, then READ(10)
-		 * at 160Hz, and prevents the system from coming up.
-		 */
-		if (sd[i]->format_in_progress) {
-			dev_info(&h->pdev->dev,
-				"Logical drive format in progress, device c%db%dt%dl%d offline.\n",
-				h->scsi_host->host_no,
-				sd[i]->bus, sd[i]->target, sd[i]->lun);
-			continue;
-		}
-
 		device_change = hpsa_scsi_find_entry(sd[i], h->dev,
 					h->ndevices, &entry);
 		if (device_change == DEVICE_NOT_FOUND) {
@@ -1726,34 +1712,6 @@ static inline void hpsa_set_bus_target_lun(struct hpsa_scsi_dev_t *device,
 	device->lun = lun;
 }
 
-static unsigned char hpsa_format_in_progress(struct ctlr_info *h,
-		unsigned char scsi3addr[])
-{
-	struct CommandList *c;
-	unsigned char *sense, sense_key, asc, ascq;
-#define ASC_LUN_NOT_READY 0x04
-#define ASCQ_LUN_NOT_READY_FORMAT_IN_PROGRESS 0x04
-
-
-	c = cmd_special_alloc(h);
-	if (!c)
-		return 0;
-	fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, scsi3addr, TYPE_CMD);
-	hpsa_scsi_do_simple_cmd_core(h, c);
-	sense = c->err_info->SenseInfo;
-	sense_key = sense[2];
-	asc = sense[12];
-	ascq = sense[13];
-	if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
-		c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION &&
-		sense_key == NOT_READY &&
-		asc == ASC_LUN_NOT_READY &&
-		ascq == ASCQ_LUN_NOT_READY_FORMAT_IN_PROGRESS)
-		return 1;
-	cmd_special_free(h, c);
-	return 0;
-}
-
 static int hpsa_update_device_info(struct ctlr_info *h,
 	unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device,
 	unsigned char *is_OBDR_device)
@@ -1792,14 +1750,10 @@ static int hpsa_update_device_info(struct ctlr_info *h,
 		sizeof(this_device->device_id));
 
 	if (this_device->devtype == TYPE_DISK &&
-		is_logical_dev_addr_mode(scsi3addr)) {
+		is_logical_dev_addr_mode(scsi3addr))
 		hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level);
-		this_device->format_in_progress =
-			hpsa_format_in_progress(h, scsi3addr);
-	} else {
+	else
 		this_device->raid_level = RAID_UNKNOWN;
-		this_device->format_in_progress = 0;
-	}
 
 	if (is_OBDR_device) {
 		/* See if this is a One-Button-Disaster-Recovery device
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 04074f5..5f3f72f 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -46,7 +46,6 @@ struct hpsa_scsi_dev_t {
 	unsigned char vendor[8];        /* bytes 8-15 of inquiry data */
 	unsigned char model[16];        /* bytes 16-31 of inquiry data */
 	unsigned char raid_level;	/* from inquiry page 0xC1 */
-	unsigned char format_in_progress;
 };
 
 struct reply_pool {


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

* [PATCH 3/9] hpsa: return 0 from driver probe function on success, not 1
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
  2013-12-04 23:09 ` [PATCH 1/9] hpsa: revert bring logical drives online when format completes Stephen M. Cameron
  2013-12-04 23:09 ` [PATCH 2/9] hpsa: revert hide logical drives with format in progress from linux Stephen M. Cameron
@ 2013-12-04 23:10 ` Stephen M. Cameron
  2013-12-04 23:10 ` [PATCH 4/9] hpsa: use workqueue instead of kernel thread for lockup detection Stephen M. Cameron
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:10 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

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

A return value of 1 is interpreted as an error.  See
pci-driver.c in local_pci_probe().  If you're wondering how
this ever could have worked, it's because it used to be the
case that only return values less than zero were interpreted
as failure.  But even in the current kernel if the driver
registers its various entry points with the kernel, and then
returns a value which is interpreted as failure, those
registrations aren't undone, so the driver still mostly works.
However, the driver's remove function wouldn't be called on
rmmod, and pci power management functions wouldn't work.  In
the case of Smart Array, since it has a battery backed cache
(or else no cache) even if the driver is not shut down
properly as long as there is no outstanding i/o, nothing too
bad happens, which is why it took so long to
notice.

Requesting backport to stable because the change to pci-driver.c
which requires driver probe functions to return 0 occurred between
2.6.35 and 2.6.36 (the pci power management breakage) and again
between 3.7 and 3.8 (pci_dev->driver getting set to NULL in
local_pci_probe() preventing driver remove function from being
called on rmmod.)

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Cc: stable@vger.kernel.org
---
 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 75800f7..14f662d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5004,7 +5004,7 @@ reinit_after_soft_reset:
 	hpsa_hba_inquiry(h);
 	hpsa_register_scsi(h);	/* hook ourselves into SCSI subsystem */
 	start_controller_lockup_detector(h);
-	return 1;
+	return 0;
 
 clean4:
 	hpsa_free_sg_chain_blocks(h);


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

* [PATCH 4/9] hpsa: use workqueue instead of kernel thread for lockup detection
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
                   ` (2 preceding siblings ...)
  2013-12-04 23:10 ` [PATCH 3/9] hpsa: return 0 from driver probe function on success, not 1 Stephen M. Cameron
@ 2013-12-04 23:10 ` Stephen M. Cameron
  2013-12-04 23:10 ` [PATCH 5/9] hpsa: rename scsi prefetch field Stephen M. Cameron
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:10 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

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

Much simpler and avoids races starting/stopping the thread.

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 14f662d..a502718 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -168,10 +168,6 @@ static struct board_type products[] = {
 
 static int number_of_controllers;
 
-static struct list_head hpsa_ctlr_list = LIST_HEAD_INIT(hpsa_ctlr_list);
-static spinlock_t lockup_detector_lock;
-static struct task_struct *hpsa_lockup_detector;
-
 static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id);
 static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id);
 static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg);
@@ -4715,16 +4711,6 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
 	kfree(h);
 }
 
-static void remove_ctlr_from_lockup_detector_list(struct ctlr_info *h)
-{
-	assert_spin_locked(&lockup_detector_lock);
-	if (!hpsa_lockup_detector)
-		return;
-	if (h->lockup_detected)
-		return; /* already stopped the lockup detector */
-	list_del(&h->lockup_list);
-}
-
 /* Called when controller lockup detected. */
 static void fail_all_cmds_on_list(struct ctlr_info *h, struct list_head *list)
 {
@@ -4743,8 +4729,6 @@ static void controller_lockup_detected(struct ctlr_info *h)
 {
 	unsigned long flags;
 
-	assert_spin_locked(&lockup_detector_lock);
-	remove_ctlr_from_lockup_detector_list(h);
 	h->access.set_intr_mask(h, HPSA_INTR_OFF);
 	spin_lock_irqsave(&h->lock, flags);
 	h->lockup_detected = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
@@ -4764,7 +4748,6 @@ static void detect_controller_lockup(struct ctlr_info *h)
 	u32 heartbeat;
 	unsigned long flags;
 
-	assert_spin_locked(&lockup_detector_lock);
 	now = get_jiffies_64();
 	/* If we've received an interrupt recently, we're ok. */
 	if (time_after64(h->last_intr_timestamp +
@@ -4794,68 +4777,22 @@ static void detect_controller_lockup(struct ctlr_info *h)
 	h->last_heartbeat_timestamp = now;
 }
 
-static int detect_controller_lockup_thread(void *notused)
-{
-	struct ctlr_info *h;
-	unsigned long flags;
-
-	while (1) {
-		struct list_head *this, *tmp;
-
-		schedule_timeout_interruptible(HEARTBEAT_SAMPLE_INTERVAL);
-		if (kthread_should_stop())
-			break;
-		spin_lock_irqsave(&lockup_detector_lock, flags);
-		list_for_each_safe(this, tmp, &hpsa_ctlr_list) {
-			h = list_entry(this, struct ctlr_info, lockup_list);
-			detect_controller_lockup(h);
-		}
-		spin_unlock_irqrestore(&lockup_detector_lock, flags);
-	}
-	return 0;
-}
-
-static void add_ctlr_to_lockup_detector_list(struct ctlr_info *h)
+static void hpsa_monitor_ctlr_worker(struct work_struct *work)
 {
 	unsigned long flags;
-
-	h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
-	spin_lock_irqsave(&lockup_detector_lock, flags);
-	list_add_tail(&h->lockup_list, &hpsa_ctlr_list);
-	spin_unlock_irqrestore(&lockup_detector_lock, flags);
-}
-
-static void start_controller_lockup_detector(struct ctlr_info *h)
-{
-	/* Start the lockup detector thread if not already started */
-	if (!hpsa_lockup_detector) {
-		spin_lock_init(&lockup_detector_lock);
-		hpsa_lockup_detector =
-			kthread_run(detect_controller_lockup_thread,
-						NULL, HPSA);
-	}
-	if (!hpsa_lockup_detector) {
-		dev_warn(&h->pdev->dev,
-			"Could not start lockup detector thread\n");
+	struct ctlr_info *h = container_of(to_delayed_work(work),
+					struct ctlr_info, monitor_ctlr_work);
+	detect_controller_lockup(h);
+	if (h->lockup_detected)
+		return;
+	spin_lock_irqsave(&h->lock, flags);
+	if (h->remove_in_progress) {
+		spin_unlock_irqrestore(&h->lock, flags);
 		return;
 	}
-	add_ctlr_to_lockup_detector_list(h);
-}
-
-static void stop_controller_lockup_detector(struct ctlr_info *h)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&lockup_detector_lock, flags);
-	remove_ctlr_from_lockup_detector_list(h);
-	/* If the list of ctlr's to monitor is empty, stop the thread */
-	if (list_empty(&hpsa_ctlr_list)) {
-		spin_unlock_irqrestore(&lockup_detector_lock, flags);
-		kthread_stop(hpsa_lockup_detector);
-		spin_lock_irqsave(&lockup_detector_lock, flags);
-		hpsa_lockup_detector = NULL;
-	}
-	spin_unlock_irqrestore(&lockup_detector_lock, flags);
+	schedule_delayed_work(&h->monitor_ctlr_work,
+				h->heartbeat_sample_interval);
+	spin_unlock_irqrestore(&h->lock, flags);
 }
 
 static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -5003,7 +4940,12 @@ reinit_after_soft_reset:
 
 	hpsa_hba_inquiry(h);
 	hpsa_register_scsi(h);	/* hook ourselves into SCSI subsystem */
-	start_controller_lockup_detector(h);
+
+	/* Monitor the controller for firmware lockups */
+	h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
+	INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
+	schedule_delayed_work(&h->monitor_ctlr_work,
+				h->heartbeat_sample_interval);
 	return 0;
 
 clean4:
@@ -5078,13 +5020,20 @@ static void hpsa_free_device_info(struct ctlr_info *h)
 static void hpsa_remove_one(struct pci_dev *pdev)
 {
 	struct ctlr_info *h;
+	unsigned long flags;
 
 	if (pci_get_drvdata(pdev) == NULL) {
 		dev_err(&pdev->dev, "unable to remove device\n");
 		return;
 	}
 	h = pci_get_drvdata(pdev);
-	stop_controller_lockup_detector(h);
+
+	/* Get rid of any controller monitoring work items */
+	spin_lock_irqsave(&h->lock, flags);
+	h->remove_in_progress = 1;
+	cancel_delayed_work(&h->monitor_ctlr_work);
+	spin_unlock_irqrestore(&h->lock, flags);
+
 	hpsa_unregister_scsi(h);	/* unhook from SCSI subsystem */
 	hpsa_shutdown(pdev);
 	iounmap(h->vaddr);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 5f3f72f..01c3283 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -135,7 +135,8 @@ struct ctlr_info {
 	u32 heartbeat_sample_interval;
 	atomic_t firmware_flash_in_progress;
 	u32 lockup_detected;
-	struct list_head lockup_list;
+	struct delayed_work monitor_ctlr_work;
+	int remove_in_progress;
 	u32 fifo_recently_full;
 	/* Address of h->q[x] is passed to intr handler to know which queue */
 	u8 q[MAX_REPLY_QUEUES];


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

* [PATCH 5/9] hpsa: rename scsi prefetch field
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
                   ` (3 preceding siblings ...)
  2013-12-04 23:10 ` [PATCH 4/9] hpsa: use workqueue instead of kernel thread for lockup detection Stephen M. Cameron
@ 2013-12-04 23:10 ` Stephen M. Cameron
  2013-12-04 23:10 ` [PATCH 6/9] hpsa: enable unit attention reporting Stephen M. Cameron
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:10 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

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

The field contains more bits than just the one
to indicate whether scsi prefetch should be turned on.

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a502718..2b0f578 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4381,15 +4381,15 @@ static inline bool hpsa_CISS_signature_present(struct ctlr_info *h)
 	return true;
 }
 
-/* Need to enable prefetch in the SCSI core for 6400 in x86 */
-static inline void hpsa_enable_scsi_prefetch(struct ctlr_info *h)
+static inline void hpsa_set_driver_support_bits(struct ctlr_info *h)
 {
 #ifdef CONFIG_X86
-	u32 prefetch;
+	/* Need to enable prefetch in the SCSI core for 6400 in x86 */
+	u32 driver_support;
 
-	prefetch = readl(&(h->cfgtable->SCSI_Prefetch));
-	prefetch |= 0x100;
-	writel(prefetch, &(h->cfgtable->SCSI_Prefetch));
+	driver_support = readl(&(h->cfgtable->driver_support));
+	driver_support |= ENABLE_SCSI_PREFETCH;
+	writel(driver_support, &(h->cfgtable->driver_support));
 #endif
 }
 
@@ -4500,7 +4500,7 @@ static int hpsa_pci_init(struct ctlr_info *h)
 		err = -ENODEV;
 		goto err_out_free_res;
 	}
-	hpsa_enable_scsi_prefetch(h);
+	hpsa_set_driver_support_bits(h);
 	hpsa_p600_dma_prefetch_quirk(h);
 	err = hpsa_enter_simple_mode(h);
 	if (err)
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index a894f2e..5158709 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -356,7 +356,8 @@ struct CfgTable {
 	u32           TransMethodOffset;
 	u8            ServerName[16];
 	u32           HeartBeat;
-	u32           SCSI_Prefetch;
+	u32           driver_support;
+#define			ENABLE_SCSI_PREFETCH 0x100
 	u32	 	MaxScatterGatherElements;
 	u32		MaxLogicalUnits;
 	u32		MaxPhysicalDevices;


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

* [PATCH 6/9] hpsa: enable unit attention reporting
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
                   ` (4 preceding siblings ...)
  2013-12-04 23:10 ` [PATCH 5/9] hpsa: rename scsi prefetch field Stephen M. Cameron
@ 2013-12-04 23:10 ` Stephen M. Cameron
  2013-12-04 23:10 ` [PATCH 7/9] hpsa: do not discard scsi status on aborted commands Stephen M. Cameron
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:10 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

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

This used to be the default, but at some point the firmware guys
changed the default and I failed to notice.  Now to get unit
attention notifications, you must twiddle a bit indicating you
want them.

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 2b0f578..069640f 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4383,14 +4383,15 @@ static inline bool hpsa_CISS_signature_present(struct ctlr_info *h)
 
 static inline void hpsa_set_driver_support_bits(struct ctlr_info *h)
 {
-#ifdef CONFIG_X86
-	/* Need to enable prefetch in the SCSI core for 6400 in x86 */
 	u32 driver_support;
 
+#ifdef CONFIG_X86
+	/* Need to enable prefetch in the SCSI core for 6400 in x86 */
 	driver_support = readl(&(h->cfgtable->driver_support));
 	driver_support |= ENABLE_SCSI_PREFETCH;
-	writel(driver_support, &(h->cfgtable->driver_support));
 #endif
+	driver_support |= ENABLE_UNIT_ATTN;
+	writel(driver_support, &(h->cfgtable->driver_support));
 }
 
 /* Disable DMA prefetch for the P600.  Otherwise an ASIC bug may result
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 5158709..bfc8c4e 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -358,6 +358,7 @@ struct CfgTable {
 	u32           HeartBeat;
 	u32           driver_support;
 #define			ENABLE_SCSI_PREFETCH 0x100
+#define			ENABLE_UNIT_ATTN 0x01
 	u32	 	MaxScatterGatherElements;
 	u32		MaxLogicalUnits;
 	u32		MaxPhysicalDevices;


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

* [PATCH 7/9] hpsa: do not discard scsi status on aborted commands
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
                   ` (5 preceding siblings ...)
  2013-12-04 23:10 ` [PATCH 6/9] hpsa: enable unit attention reporting Stephen M. Cameron
@ 2013-12-04 23:10 ` Stephen M. Cameron
  2013-12-04 23:10 ` [PATCH 8/9] hpsa: do not require board "not ready" status after hard reset Stephen M. Cameron
  2013-12-04 23:10 ` [PATCH 9/9] hpsa: allow SCSI mid layer to handle unit attention Stephen M. Cameron
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:10 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

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

We inadvertantly discarded the scsi status for aborted commands.
For some commands (e.g. reads from tape drives) these can't be retried,
and if we discarded the scsi status, the scsi mid layer couldn't notice
anything was wrong and the error was not reported.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Cc: stable@vger.kernel.org
---
 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 069640f..162405e 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1281,7 +1281,7 @@ static void complete_scsi_command(struct CommandList *cp)
 					"has check condition: aborted command: "
 					"ASC: 0x%x, ASCQ: 0x%x\n",
 					cp, asc, ascq);
-				cmd->result = DID_SOFT_ERROR << 16;
+				cmd->result |= DID_SOFT_ERROR << 16;
 				break;
 			}
 			/* Must be some other type of check condition */


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

* [PATCH 8/9] hpsa: do not require board "not ready" status after hard reset
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
                   ` (6 preceding siblings ...)
  2013-12-04 23:10 ` [PATCH 7/9] hpsa: do not discard scsi status on aborted commands Stephen M. Cameron
@ 2013-12-04 23:10 ` Stephen M. Cameron
  2013-12-04 23:10 ` [PATCH 9/9] hpsa: allow SCSI mid layer to handle unit attention Stephen M. Cameron
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:10 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

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

Immediately following a hard board reset, There are some
mandatory delays during which we must not access the board
and during which we might miss the "not ready" status,
therefore it is a mistake to look for and expect to see
the "not ready" status.

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 162405e..693c801 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4047,23 +4047,6 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	   need a little pause here */
 	msleep(HPSA_POST_RESET_PAUSE_MSECS);
 
-	if (!use_doorbell) {
-		/* Wait for board to become not ready, then ready.
-		 * (if we used the doorbell, then we already waited 5 secs
-		 * so the "not ready" state is already gone by so we
-		 * won't catch it.)
-		 */
-		dev_info(&pdev->dev, "Waiting for board to reset.\n");
-		rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
-		if (rc) {
-			dev_warn(&pdev->dev,
-				"failed waiting for board to reset."
-				" Will try soft reset.\n");
-			/* Not expected, but try soft reset later */
-			rc = -ENOTSUPP;
-			goto unmap_cfgtable;
-		}
-	}
 	rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY);
 	if (rc) {
 		dev_warn(&pdev->dev,


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

* [PATCH 9/9] hpsa: allow SCSI mid layer to handle unit attention
  2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
                   ` (7 preceding siblings ...)
  2013-12-04 23:10 ` [PATCH 8/9] hpsa: do not require board "not ready" status after hard reset Stephen M. Cameron
@ 2013-12-04 23:10 ` Stephen M. Cameron
  8 siblings, 0 replies; 10+ messages in thread
From: Stephen M. Cameron @ 2013-12-04 23:10 UTC (permalink / raw)
  To: james.bottomley; +Cc: stephenmcameron, mikem, thenzl, linux-scsi, scott.teel

From: Matt Gates <matthew.gates@hp.com>

We were clobbering the SCSI status and setting
cmd->result = DID_SOFT_ERROR << 16; to get a retry,
but better to let the mid layer handle the unit
attention.

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

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 693c801..107f3c4 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1240,10 +1240,8 @@ static void complete_scsi_command(struct CommandList *cp)
 		}
 
 		if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
-			if (check_for_unit_attention(h, cp)) {
-				cmd->result = DID_SOFT_ERROR << 16;
+			if (check_for_unit_attention(h, cp))
 				break;
-			}
 			if (sense_key == ILLEGAL_REQUEST) {
 				/*
 				 * SCSI REPORT_LUNS is commonly unsupported on


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

end of thread, other threads:[~2013-12-04 23:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-04 23:09 [PATCH 0/9] hpsa: resend of November 2013 patches Stephen M. Cameron
2013-12-04 23:09 ` [PATCH 1/9] hpsa: revert bring logical drives online when format completes Stephen M. Cameron
2013-12-04 23:09 ` [PATCH 2/9] hpsa: revert hide logical drives with format in progress from linux Stephen M. Cameron
2013-12-04 23:10 ` [PATCH 3/9] hpsa: return 0 from driver probe function on success, not 1 Stephen M. Cameron
2013-12-04 23:10 ` [PATCH 4/9] hpsa: use workqueue instead of kernel thread for lockup detection Stephen M. Cameron
2013-12-04 23:10 ` [PATCH 5/9] hpsa: rename scsi prefetch field Stephen M. Cameron
2013-12-04 23:10 ` [PATCH 6/9] hpsa: enable unit attention reporting Stephen M. Cameron
2013-12-04 23:10 ` [PATCH 7/9] hpsa: do not discard scsi status on aborted commands Stephen M. Cameron
2013-12-04 23:10 ` [PATCH 8/9] hpsa: do not require board "not ready" status after hard reset Stephen M. Cameron
2013-12-04 23:10 ` [PATCH 9/9] hpsa: allow SCSI mid layer to handle unit attention Stephen M. Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).