hpsa: supplemental February 2014 driver updates
Subsystems (2)
cover hpsa: supplemental February 2014 driver updates
The following series applies on top of the 35 patches I sent on Feb 18 (see http://thread.gmane.org/gmane.linux.scsi/88433 )
The two main changes are to bring temporarily offline devices (e.g. logical drives undergoing "rapid parity initialization") online automatically when they become ready, and adding support for "hba mode" for controllers which support this feature, to expose physical disks to the OS.
---
Stephen M. Cameron (5):
hpsa: remove unused kthread.h header
hpsa: bring format-in-progress drives online when ready
hpsa: remove unused struct request from CommandList
hpsa: Add hba mode to the hpsa driver
hpsa: Do not zero fields of ioaccel2 command structure twice
Tomas Henzl (1):
hpsa: increase the probability of a reported success after a device reset
drivers/scsi/hpsa.c | 410 +++++++++++++++++++++++++++++++++++++++++++---- drivers/scsi/hpsa.h | 50 ++++++ drivers/scsi/hpsa_cmd.h | 21 ++ 3 files changed, 446 insertions(+), 35 deletions(-)
Signature · 1 line
-- steve
PATCH 1/6 hpsa: remove unused kthread.h header
From: Stephen M. Cameron <[email protected]>
--- drivers/scsi/hpsa.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/scsi/hpsa.c +0 -1
@@ -47,7 +47,6 @@#include <linux/string.h> #include <linux/bitmap.h> #include <linux/atomic.h> -#include <linux/kthread.h> #include <linux/jiffies.h> #include <asm/div64.h> #include "hpsa_cmd.h"
PATCH 2/6 hpsa: bring format-in-progress drives online when ready
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
Do not expose drives that are undergoing a format immediately to the OS, instead wait until they are ready before bringing them online. This is so that logical drives created with "rapid parity initialization" do not get immediately kicked off the system for being unresponsive.
--- drivers/scsi/hpsa.c | 311 +++++++++++++++++++++++++++++++++++++++++++---- drivers/scsi/hpsa.h | 9 + drivers/scsi/hpsa_cmd.h | 15 ++ 3 files changed, 311 insertions(+), 24 deletions(-)
drivers/scsi/hpsa.c +287 -24
@@ -1133,6 +1133,9 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,return DEVICE_UPDATED ;return DEVICE_SAME ; }else { +/* Keep offline devices offline */ +if (needle->volume_offline) +return DEVICE_NOT_FOUND ;return DEVICE_CHANGED ; } }
@@ -1141,6 +1144,110 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,return DEVICE_NOT_FOUND ; } +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); +spin_unlock_irqrestore (&h->offline_device_lock, flags); +} + +/* Print a message explaining various offline volume states */ +static void hpsa_show_volume_status (struct ctlr_info *h, +struct hpsa_scsi_dev_t *sd) +{ +if (sd->volume_offline ==HPSA_VPD_LV_STATUS_UNSUPPORTED ) +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume status is not available through vital product data pages.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +switch (sd->volume_offline) { +case HPSA_LV_OK : +break ; +case HPSA_LV_UNDERGOING_ERASE : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is undergoing background erase process.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_UNDERGOING_RPI : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is undergoing rapid parity initialization process.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_PENDING_RPI : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is queued for rapid parity initialization process.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_ENCRYPTED_NO_KEY : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is encrypted and cannot be accessed because key is not present.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_PLAINTEXT_IN_ENCRYPT_ONLY_CONTROLLER : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is not encrypted and cannot be accessed because controller is in encryption-only mode.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_UNDERGOING_ENCRYPTION : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is undergoing encryption process.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_UNDERGOING_ENCRYPTION_REKEYING : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is undergoing encryption re-keying process.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_ENCRYPTED_IN_NON_ENCRYPTED_CONTROLLER : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is encrypted and cannot be accessed because controller does not have encryption enabled.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_PENDING_ENCRYPTION : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is pending migration to encrypted state, but process has not started.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; +case HPSA_LV_PENDING_ENCRYPTION_REKEYING : +dev_info (&h->pdev->dev, +"C%d:B%d:T%d:L%d Volume is encrypted and is pending encryption rekeying.\n" , + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); +break ; + } +} +static void adjust_hpsa_scsi_table (struct ctlr_info *h,int hostno,struct hpsa_scsi_dev_t *sd[],int nsds) {
@@ -1205,6 +1312,20 @@ 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]->volume_offline) { +hpsa_show_volume_status (h, sd[i]); +dev_info (&h->pdev->dev,"c%db%dt%dl%d: temporarily 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 ) {
@@ -1223,6 +1344,17 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, }spin_unlock_irqrestore (&h->devlock, flags); +/* Monitor devices which are in one of several NOT READY states 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]->volume_offline) +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.
@@ -2326,6 +2458,117 @@ static inline void hpsa_set_bus_target_lun(struct hpsa_scsi_dev_t *device, device->lun = lun; } +/* Use VPD inquiry to get details of volume status */ +static int hpsa_get_volume_status (struct ctlr_info *h, +unsigned char scsi3addr[]) +{ +int rc; +int status; +int size; +unsigned char *buf; + + buf =kzalloc (64 ,GFP_KERNEL ); +if (!buf) +return HPSA_VPD_LV_STATUS_UNSUPPORTED ; + +/* Does controller have VPD for logical volume status? */ +if (!hpsa_vpd_page_supported (h, scsi3addr,HPSA_VPD_LV_STATUS )) { +dev_warn (&h->pdev->dev,"Logical volume status VPD page is unsupported.\n" ); + goto exit_failed; + } + +/* Get the size of the VPD return buffer */ + rc =hpsa_scsi_do_inquiry (h, scsi3addr,VPD_PAGE |HPSA_VPD_LV_STATUS , + buf,HPSA_VPD_HEADER_SZ ); +if (rc !=0 ) { +dev_warn (&h->pdev->dev,"Logical volume status VPD inquiry failed.\n" ); + goto exit_failed; + } + size = buf[3 ]; + +/* Now get the whole VPD buffer */ + rc =hpsa_scsi_do_inquiry (h, scsi3addr,VPD_PAGE |HPSA_VPD_LV_STATUS , + buf, size +HPSA_VPD_HEADER_SZ ); +if (rc !=0 ) { +dev_warn (&h->pdev->dev,"Logical volume status VPD inquiry failed.\n" ); + goto exit_failed; + } + status = buf[4 ];/* status byte */ + +kfree (buf); +return status; +exit_failed: +kfree (buf); +return HPSA_VPD_LV_STATUS_UNSUPPORTED ; +} + +/* Determine offline status of a volume. +* Return either: +* 0 (not offline) +* -1 (offline for unknown reasons) +* # (integer code indicating one of several NOT READY states +* describing why a volume is to be kept offline) +*/ +static unsigned char hpsa_volume_offline (struct ctlr_info *h, +unsigned char scsi3addr[]) +{ +struct CommandList *c; +unsigned char *sense, sense_key, asc, ascq; +int ldstat =0 ; +u16 cmd_status; +u8 scsi_status; +#define ASC_LUN_NOT_READY 0x04 +#define ASCQ_LUN_NOT_READY_FORMAT_IN_PROGRESS 0x04 +#define ASCQ_LUN_NOT_READY_INITIALIZING_CMD_REQ 0x02 + + c =cmd_alloc (h); +if (!c) +return 0 ; + (void )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 ]; + cmd_status = c->err_info->CommandStatus; + scsi_status = c->err_info->ScsiStatus; +cmd_free (h, c); +/* Is the volume 'not ready'? */ +if (cmd_status !=CMD_TARGET_STATUS || + scsi_status !=SAM_STAT_CHECK_CONDITION || + sense_key !=NOT_READY || + asc !=ASC_LUN_NOT_READY ) { +return 0 ; + } + +/* Determine the reason for not ready state */ + ldstat =hpsa_get_volume_status (h, scsi3addr); + +/* Keep volume offline in certain cases: */ +switch (ldstat) { +case HPSA_LV_UNDERGOING_ERASE : +case HPSA_LV_UNDERGOING_RPI : +case HPSA_LV_PENDING_RPI : +case HPSA_LV_ENCRYPTED_NO_KEY : +case HPSA_LV_PLAINTEXT_IN_ENCRYPT_ONLY_CONTROLLER : +case HPSA_LV_UNDERGOING_ENCRYPTION : +case HPSA_LV_UNDERGOING_ENCRYPTION_REKEYING : +case HPSA_LV_ENCRYPTED_IN_NON_ENCRYPTED_CONTROLLER : +return ldstat; +case HPSA_VPD_LV_STATUS_UNSUPPORTED : +/* If VPD status page isn't available, +* use ASC/ASCQ to determine state +*/ +if ((ascq ==ASCQ_LUN_NOT_READY_FORMAT_IN_PROGRESS ) || + (ascq ==ASCQ_LUN_NOT_READY_INITIALIZING_CMD_REQ )) +return ldstat; +break ; +default : +break ; + } +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)
@@ -2368,10 +2611,13 @@ static int hpsa_update_device_info(struct ctlr_info *h,hpsa_get_raid_level (h, scsi3addr, &this_device->raid_level);if (h->fw_support &MISC_FW_RAID_OFFLOAD_BASIC )hpsa_get_ioaccel_status (h, scsi3addr, this_device); + this_device->volume_offline = +hpsa_volume_offline (h, scsi3addr); }else { this_device->raid_level =RAID_UNKNOWN ; this_device->offload_config =0 ; this_device->offload_enabled =0 ; + this_device->volume_offline =0 ; }if (is_OBDR_device) {
@@ -6442,7 +6688,7 @@ static void detect_controller_lockup(struct ctlr_info *h) h->last_heartbeat_timestamp = now; } -static int hpsa_kickoff_rescan (struct ctlr_info *h) +static void hpsa_ack_ctlr_events (struct ctlr_info *h) {int i;char *event_type;
@@ -6485,42 +6731,49 @@ static int hpsa_kickoff_rescan(struct ctlr_info *h)hpsa_wait_for_mode_change_ack (h);#endif } - -/* Something in the device list may have changed to trigger -* the event, so do a rescan. -*/ -hpsa_scan_start (h->scsi_host); -/* release reference taken on scsi host in check_controller_events */ -scsi_host_put (h->scsi_host); -return 0 ; +return ; }/* Check a register on the controller to see if there are configuration * changes (added/changed/removed logical drives, etc.) which mean that * we should rescan the controller for devices. * Also check flag for driver-initiated rescan. -* If either flag or controller event indicate rescan, add the controller -* to the list of controllers needing to be rescanned, and gets a -* reference to the associated scsi_host. */ -static void hpsa_ctlr_needs_rescan (struct ctlr_info *h) +static int hpsa_ctlr_needs_rescan (struct ctlr_info *h) { +if (h->drv_req_rescan) +return 1 ; +if (!(h->fw_support &MISC_FW_EVENT_NOTIFY )) -return ; +return 0 ; h->events =readl (&(h->cfgtable->event_notify)); -if (!(h->events &RESCAN_REQUIRED_EVENT_BITS ) && !h->drv_req_rescan) -return ; +return h->events &RESCAN_REQUIRED_EVENT_BITS ; +} -/* -* Take a reference on scsi host for the duration of the scan -* Release in hpsa_kickoff_rescan(). No lock needed for scan_list -* as only a single thread accesses this list. -*/ -scsi_host_get (h->scsi_host); -hpsa_kickoff_rescan (h); +/* +* Check if any of the offline devices have become ready +*/ +static int hpsa_offline_devices_ready (struct ctlr_info *h) +{ +unsigned long flags; +struct offline_device_entry *d; +struct list_head *this, *tmp; + +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_volume_offline (h, d->scsi3addr)) +return 1 ; +spin_lock_irqsave (&h->offline_device_lock, flags); + } +spin_unlock_irqrestore (&h->offline_device_lock, flags); +return 0 ; } +static void hpsa_monitor_ctlr_worker (struct work_struct *work) {unsigned long flags;
@@ -6529,7 +6782,15 @@ static void hpsa_monitor_ctlr_worker(struct work_struct *work)detect_controller_lockup (h);if (h->lockup_detected)return ; -hpsa_ctlr_needs_rescan (h); + +if (hpsa_ctlr_needs_rescan (h) ||hpsa_offline_devices_ready (h)) { +scsi_host_get (h->scsi_host); + h->drv_req_rescan =0 ; +hpsa_ack_ctlr_events (h); +hpsa_scan_start (h->scsi_host); +scsi_host_put (h->scsi_host); + } +spin_lock_irqsave (&h->lock, flags);if (h->remove_in_progress) {spin_unlock_irqrestore (&h->lock, flags);
@@ -6579,7 +6840,9 @@ 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->offline_device_lock);spin_lock_init (&h->scan_lock);spin_lock_init (&h->passthru_count_lock); rc =hpsa_pci_init (h);
drivers/scsi/hpsa.h +9 -0
@@ -46,6 +46,7 @@ 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 volume_offline;/* discovered via TUR or VPD */ u32 ioaccel_handle;int offload_config;/* I/O accel RAID offload configured */ int offload_enabled;/* I/O accel RAID offload enabled */
@@ -197,10 +198,18 @@ struct ctlr_info {CTLR_STATE_CHANGE_EVENT_REDUNDANT_CNTRL | \CTLR_STATE_CHANGE_EVENT_AIO_ENABLED_DISABLED | \ CTLR_STATE_CHANGE_EVENT_AIO_CONFIG_CHANGE) + spinlock_t offline_device_lock; +struct list_head offline_device_list;int acciopath_status;int drv_req_rescan;/* flag for driver to request rescan event */ int raid_offload_debug; }; + +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
drivers/scsi/hpsa_cmd.h +15 -0
@@ -147,8 +147,23 @@#define HPSA_VPD_SUPPORTED_PAGES 0x00#define HPSA_VPD_LV_DEVICE_GEOMETRY 0xC1#define HPSA_VPD_LV_IOACCEL_STATUS 0xC2 +#define HPSA_VPD_LV_STATUS 0xC3#define HPSA_VPD_HEADER_SZ 4 +/* Logical volume states */ +#define HPSA_VPD_LV_STATUS_UNSUPPORTED -1 +#define HPSA_LV_OK 0x0 +#define HPSA_LV_UNDERGOING_ERASE 0x0F +#define HPSA_LV_UNDERGOING_RPI 0x12 +#define HPSA_LV_PENDING_RPI 0x13 +#define HPSA_LV_ENCRYPTED_NO_KEY 0x14 +#define HPSA_LV_PLAINTEXT_IN_ENCRYPT_ONLY_CONTROLLER 0x15 +#define HPSA_LV_UNDERGOING_ENCRYPTION 0x16 +#define HPSA_LV_UNDERGOING_ENCRYPTION_REKEYING 0x17 +#define HPSA_LV_ENCRYPTED_IN_NON_ENCRYPTED_CONTROLLER 0x18 +#define HPSA_LV_PENDING_ENCRYPTION 0x19 +#define HPSA_LV_PENDING_ENCRYPTION_REKEYING 0x1A +struct vals32 {u32 lower;u32 upper;
PATCH 3/6 hpsa: increase the probability of a reported success after a device reset
In reply to Stephen M. CameronFrom: Tomas Henzl <[email protected]>
rc is set in the loop, and it isn't set back to zero anywhere this patch fixes it
--- drivers/scsi/hpsa.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/scsi/hpsa.c +2 -1
@@ -4142,7 +4142,7 @@ static int hpsa_register_scsi(struct ctlr_info *h)static int wait_for_device_to_become_ready (struct ctlr_info *h,unsigned char lunaddr[]) { -int rc =0 ; +int rc;int count =0 ;int waittime =1 ;/* seconds */ struct CommandList *c;
@@ -4162,6 +4162,7 @@ static int wait_for_device_to_become_ready(struct ctlr_info *h,*/ msleep (1000 * waittime); count++; + rc =0 ;/* Device ready. */ /* Increase wait time with each try, up to a point. */ if (waittime <HPSA_MAX_WAIT_INTERVAL_SECS )
PATCH 4/6 hpsa: remove unused struct request from CommandList
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
--- drivers/scsi/hpsa_cmd.h | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
drivers/scsi/hpsa_cmd.h +2 -3
@@ -386,7 +386,6 @@ struct CommandList {int cmd_type;long cmdindex;struct list_head list; -struct request *rq;struct completion *waiting;void *scsi_cmd;
@@ -399,8 +398,8 @@ struct CommandList {*/ #define IS_32_BIT ((8 - sizeof(long))/4)#define IS_64_BIT (!IS_32_BIT) -#define PAD_32 (36) -#define PAD_64 (4) +#define PAD_32 (40) +#define PAD_64 (12)#define COMMANDLIST_PAD (IS_32_BIT * PAD_32 + IS_64_BIT * PAD_64)u8 pad[COMMANDLIST_PAD ]; };
PATCH 5/6 hpsa: Add hba mode to the hpsa driver
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
This allows exposing physical disks behind Smart
Array controllers to the OS (if the controller
has the right firmware and is in "hba" mode)
--- drivers/scsi/hpsa.c | 93 +++++++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/hpsa.h | 41 +++++++++++++++++++++ drivers/scsi/hpsa_cmd.h | 1 + 3 files changed, 131 insertions(+), 4 deletions(-)
drivers/scsi/hpsa.c +89 -4
@@ -2128,6 +2128,37 @@ out:return rc; } +static int hpsa_bmic_ctrl_mode_sense (struct ctlr_info *h, +unsigned char *scsi3addr,unsigned char page, +struct bmic_controller_parameters *buf,size_t bufsize) +{ +int rc =IO_OK ; +struct CommandList *c; +struct ErrorInfo *ei; + + c =cmd_special_alloc (h); + +if (c ==NULL ) {/* trouble... */ +dev_warn (&h->pdev->dev,"cmd_special_alloc returned NULL!\n" ); +return -ENOMEM ; + } + +if (fill_cmd (c,BMIC_SENSE_CONTROLLER_PARAMETERS , h, buf, bufsize, + page, scsi3addr,TYPE_CMD )) { + rc =-1 ; + goto out; + } +hpsa_scsi_do_simple_cmd_with_retry (h, c,PCI_DMA_FROMDEVICE ); + ei = c->err_info; +if (ei->CommandStatus !=0 && ei->CommandStatus !=CMD_DATA_UNDERRUN ) { +hpsa_scsi_interpret_error (h, c); + rc =-1 ; + } +out: +cmd_special_free (h, c); +return rc; + } +static int hpsa_send_reset (struct ctlr_info *h,unsigned char *scsi3addr,u8 reset_type) {
@@ -2929,6 +2960,24 @@ u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, int i,return NULL ; } +static int hpsa_hba_mode_enabled (struct ctlr_info *h) +{ +int rc; +struct bmic_controller_parameters *ctlr_params; + ctlr_params =kzalloc (sizeof (struct bmic_controller_parameters ), +GFP_KERNEL ); + +if (!ctlr_params) +return 0 ; + rc =hpsa_bmic_ctrl_mode_sense (h,RAID_CTLR_LUNID ,0 , ctlr_params, +sizeof (struct bmic_controller_parameters )); +if (rc !=0 ) { +kfree (ctlr_params); +return 0 ; + } +return ctlr_params->nvram_flags & (1 <<3 ) ?1 :0 ; +} +static void hpsa_update_scsi_devices (struct ctlr_info *h,int hostno) {/* the idea here is we could get notified
@@ -2952,6 +3001,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)int reportlunsize =sizeof (*physdev_list) +HPSA_MAX_PHYS_LUN *24 ;int i, n_ext_target_devs, ndevs_to_allocate;int raid_ctlr_position; +u8 rescan_hba_mode;DECLARE_BITMAP (lunzerobits,MAX_EXT_TARGETS ); currentsd =kzalloc (sizeof (*currentsd) *HPSA_MAX_DEVICES ,GFP_KERNEL );
@@ -2965,6 +3015,15 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) }memset (lunzerobits,0 ,sizeof (lunzerobits)); + rescan_hba_mode =hpsa_hba_mode_enabled (h); + +if (!h->hba_mode_enabled && rescan_hba_mode) +dev_warn (&h->pdev->dev,"HBA mode enabled\n" ); +else if (h->hba_mode_enabled && !rescan_hba_mode) +dev_warn (&h->pdev->dev,"HBA mode disabled\n" ); + + h->hba_mode_enabled = rescan_hba_mode; +if (hpsa_gather_lun_info (h, reportlunsize, (struct ReportLUNdata *) physdev_list, &nphysicals, &physical_mode, logdev_list, &nlogicals))
@@ -3048,7 +3107,19 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) ncurrent++;break ;case TYPE_DISK : -if (i >= nphysicals) { +if (h->hba_mode_enabled) { +/* never use raid mapper in HBA mode */ + this_device->offload_enabled =0 ; + ncurrent++; +break ; + }else if (h->acciopath_status) { +if (i >= nphysicals) { + ncurrent++; +break ; + } + }else { +if (i < nphysicals) +break ; ncurrent++;break ; }
@@ -4116,7 +4187,10 @@ static int hpsa_register_scsi(struct ctlr_info *h) sh->max_lun =HPSA_MAX_LUN ; sh->max_id =HPSA_MAX_LUN ; sh->can_queue = h->nr_cmds; - sh->cmd_per_lun = h->nr_cmds; +if (h->hba_mode_enabled) + sh->cmd_per_lun =7 ; +else + sh->cmd_per_lun = h->nr_cmds; sh->sg_tablesize = h->maxsgentries; h->scsi_host = sh; sh->hostdata[0 ] = (unsigned long ) h;
@@ -5261,6 +5335,16 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[8 ] = (size >>8 ) &0xFF ; c->Request.CDB[9 ] = size &0xFF ;break ; +case BMIC_SENSE_CONTROLLER_PARAMETERS : + c->Request.CDBLen =10 ; + c->Request.Type.Attribute =ATTR_SIMPLE ; + c->Request.Type.Direction =XFER_READ ; + c->Request.Timeout =0 ; + c->Request.CDB[0 ] =BMIC_READ ; + c->Request.CDB[6 ] =BMIC_SENSE_CONTROLLER_PARAMETERS ; + c->Request.CDB[7 ] = (size >>16 ) &0xFF ; + c->Request.CDB[8 ] = (size >>8 ) &0xFF ; +break ;default :dev_warn (&h->pdev->dev,"unknown command 0x%c\n" , cmd);BUG ();
@@ -6885,6 +6969,7 @@ reinit_after_soft_reset:pci_set_drvdata (pdev, h); h->ndevices =0 ; + h->hba_mode_enabled =0 ; h->scsi_host =NULL ;spin_lock_init (&h->devlock);hpsa_put_ctlr_into_performant_mode (h);
@@ -6944,8 +7029,8 @@ reinit_after_soft_reset: goto reinit_after_soft_reset; } -/* Enable Accelerated IO path at driver layer */ - h->acciopath_status =1 ; +/* Enable Accelerated IO path at driver layer */ + h->acciopath_status =1 ; h->drv_req_rescan =0 ;
drivers/scsi/hpsa.h +41 -0
53 lines not on this page · raw message
drivers/scsi/hpsa_cmd.h +1 -0
@@ -257,6 +257,7 @@ struct SenseSubsystem_info {#define BMIC_CACHE_FLUSH 0xc2#define HPSA_CACHE_FLUSH 0x01/* C2 was already being used by HPSA */ #define BMIC_FLASH_FIRMWARE 0xF7 +#define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64/* Command List Structure */ union SCSI3Addr {
PATCH 6/6 hpsa: Do not zero fields of ioaccel2 command structure twice
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
Structure was already memset to zero at the top
of hpsa_scsi_ioaccel2_queue_command
--- drivers/scsi/hpsa.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/scsi/hpsa.c +0 -2
@@ -3570,8 +3570,6 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, cp->Tag = (c->cmdindex <<DIRECT_LOOKUP_SHIFT ) |DIRECT_LOOKUP_BIT ;memcpy (cp->cdb, cdb,sizeof (cp->cdb)); -memset (cp->cciss_lun,0 ,sizeof (cp->cciss_lun)); - cp->cmd_priority_task_attr =0 ;/* fill in sg elements */ cp->sg_count = (u8 ) use_sg;