Skip to content

Commit

Permalink
hpsa: add discovery polling for PT RAID devices.
Browse files Browse the repository at this point in the history
There are problems with getting configuration change notification
in pass-through RAID environments.  So, activate flag
h->discovery_polling when one of these devices is detected in
update_scsi_devices.

After discovery_polling is set, execute a report luns from
rescan_controller_worker (every 30 seconds).

If the data from report_luns is different than last
time (binary compare), execute a full rescan via update_scsi_devices.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Reviewed-by: Justin Lindley <justin.lindley@pmcs.com>
Reviewed-by: Kevin Barnett <kevin.barnett@pmcs.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Scott Teel authored and Martin K. Petersen committed Nov 9, 2015
1 parent 2d62a33 commit 3459225
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
68 changes: 68 additions & 0 deletions drivers/scsi/hpsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h,
static void hpsa_command_resubmit_worker(struct work_struct *work);
static u32 lockup_detected(struct ctlr_info *h);
static int detect_controller_lockup(struct ctlr_info *h);
static int hpsa_luns_changed(struct ctlr_info *h);

static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
{
Expand Down Expand Up @@ -3898,6 +3899,18 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes);
this_device = currentsd[ncurrent];

/* Turn on discovery_polling if there are ext target devices.
* Event-based change notification is unreliable for those.
*/
if (!h->discovery_polling) {
if (tmpdevice->external) {
h->discovery_polling = 1;
dev_info(&h->pdev->dev,
"External target, activate discovery polling.\n");
}
}


*this_device = *tmpdevice;
this_device->physical_device = physical_device;

Expand Down Expand Up @@ -8016,6 +8029,41 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h)
return 0;
}

static int hpsa_luns_changed(struct ctlr_info *h)
{
int rc = 1; /* assume there are changes */
struct ReportLUNdata *logdev = NULL;

/* if we can't find out if lun data has changed,
* assume that it has.
*/

if (!h->lastlogicals)
goto out;

logdev = kzalloc(sizeof(*logdev), GFP_KERNEL);
if (!logdev) {
dev_warn(&h->pdev->dev,
"Out of memory, can't track lun changes.\n");
goto out;
}
if (hpsa_scsi_do_report_luns(h, 1, logdev, sizeof(*logdev), 0)) {
dev_warn(&h->pdev->dev,
"report luns failed, can't track lun changes.\n");
goto out;
}
if (memcmp(logdev, h->lastlogicals, sizeof(*logdev))) {
dev_info(&h->pdev->dev,
"Lun changes detected.\n");
memcpy(h->lastlogicals, logdev, sizeof(*logdev));
goto out;
} else
rc = 0; /* no changes detected. */
out:
kfree(logdev);
return rc;
}

static void hpsa_rescan_ctlr_worker(struct work_struct *work)
{
unsigned long flags;
Expand All @@ -8031,6 +8079,18 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work)
hpsa_ack_ctlr_events(h);
hpsa_scan_start(h->scsi_host);
scsi_host_put(h->scsi_host);
} else if (h->discovery_polling) {
if (hpsa_luns_changed(h)) {
struct Scsi_Host *sh = NULL;

dev_info(&h->pdev->dev,
"driver discovery polling rescan.\n");
sh = scsi_host_get(h->scsi_host);
if (sh != NULL) {
hpsa_scan_start(sh);
scsi_host_put(sh);
}
}
}
spin_lock_irqsave(&h->lock, flags);
if (!h->remove_in_progress)
Expand Down Expand Up @@ -8271,13 +8331,20 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)

/* Enable Accelerated IO path at driver layer */
h->acciopath_status = 1;
/* Disable discovery polling.*/
h->discovery_polling = 0;


/* Turn the interrupts on so we can service requests */
h->access.set_intr_mask(h, HPSA_INTR_ON);

hpsa_hba_inquiry(h);

h->lastlogicals = kzalloc(sizeof(*(h->lastlogicals)), GFP_KERNEL);
if (!h->lastlogicals)
dev_info(&h->pdev->dev,
"Can't track change to report lun data\n");

/* Monitor the controller for firmware lockups */
h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
Expand Down Expand Up @@ -8415,6 +8482,7 @@ static void hpsa_remove_one(struct pci_dev *pdev)
hpsa_free_performant_mode(h); /* init_one 7 */
hpsa_free_sg_chain_blocks(h); /* init_one 6 */
hpsa_free_cmd_pool(h); /* init_one 5 */
kfree(h->lastlogicals);

/* hpsa_free_irqs already called via hpsa_shutdown init_one 4 */

Expand Down
2 changes: 2 additions & 0 deletions drivers/scsi/hpsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ struct ctlr_info {
int acciopath_status;
int drv_req_rescan;
int raid_offload_debug;
int discovery_polling;
struct ReportLUNdata *lastlogicals;
int needs_abort_tags_swizzled;
struct workqueue_struct *resubmit_wq;
struct workqueue_struct *rescan_ctlr_wq;
Expand Down

0 comments on commit 3459225

Please sign in to comment.