hpsa updates
Subsystems (3)
cover hpsa updates
These patches are based on Linus's tree
The changes are:
- corrected quirky issue with dev_printk
- add driver requested rescans
- stop rescans on memory allocation failures and skip over unresponsive devices
- correct 0 byte READ(6)/WRITE(6) transfers
- correct issues when looking at CISS_REPORT_PHYS data
- correct mapping of ioaccel2 chain blocks
- make hpsa_get_device_id more generic
- add more information to messages
- simplify device exposure checks
- simplify hpsa_update_scsi_device
- add function is_logical_device
- simplify hpsa_figure_bus_target_lun
- split out scsi_add_device scsi_remove_device calls
- add in SAS transport class for HBA devices
- add in physical target resets
- eliminate fake lun0 enclosures
- add polling for PT RAID devices
- disable report lun data caching
- bumped driver version to match in-box driver
---
Don Brace (10):
hpsa: correct calls to dev_printk
hpsa: allow driver requested rescans
hpsa: abandon rescans on memory alloaction failures.
hpsa: correct transfer length for 6 byte read/write commands
hpsa: fix hpsa_adjust_hpsa_scsi_table
hpsa: correct check for non-disk devices
hpsa: correct ioaccel2 sg chain len
hpsa: enhance hpsa_get_device_id
hpsa: enhance device messages
hpsa: bump the driver version
Kevin Barnett (6):
hpsa: simplify check for device exposure
hpsa: simplify update scsi devices
hpsa: add function is_logical_device
hpsa: refactor hpsa_figure_bus_target_lun
hpsa: move scsi_add_device and scsi_remove_device calls to new function
hpsa: add in sas transport class
Scott Teel (5):
hpsa: fix physical target reset
External array LUNs must use target and lun numbers assigned by the
hpsa: eliminate fake lun0 enclosures
hpsa: add discovery polling for PT RAID devices.
hpsa: disable report lun data caching
drivers/block/cciss.h | 1 drivers/scsi/hpsa.c | 1237 +++++++++++++++++++++++++++++++++++++++-------- drivers/scsi/hpsa.h | 45 ++ drivers/scsi/hpsa_cmd.h | 30 + 4 files changed, 1088 insertions(+), 225 deletions(-)
--
Signature
PATCH 1/21 hpsa: correct calls to dev_printk
was seeing issues passing level into hpsa_show_dev_msg and then using the level as an arguement to dev_printk. For now, switch to dev_warn.
--- drivers/scsi/hpsa.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-)
drivers/scsi/hpsa.c +24 -17
@@ -1137,11 +1137,15 @@ static int hpsa_find_target_lun(struct ctlr_info *h,static inline void hpsa_show_dev_msg (const char *level,struct ctlr_info *h,struct hpsa_scsi_dev_t *dev,char *description) { - dev_printk(level, &h->pdev->dev, +if (dev ==NULL ) +return ; + + dev_warn(&h->pdev->dev, "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", h->scsi_host->host_no, dev->bus, dev->target, dev->lun, description, - scsi_device_type(dev->devtype), + dev->devtype >= 0 ? + scsi_device_type(dev->devtype) : "unknown", dev->vendor, dev->model, dev->raid_level > RAID_UNKNOWN ?
@@ -1220,7 +1224,7 @@ lun_assigned: h->ndevices++; added[*nadded] = device; (*nadded)++; -hpsa_show_dev_msg (KERN_INFO , h, device, +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, device, device->expose_state &HPSA_SCSI_ADD ?"added" :"masked" ); device->offload_to_be_enabled = device->offload_enabled; device->offload_enabled =0 ;
@@ -1271,7 +1275,7 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, offload_enabled = h->dev[entry]->offload_enabled; h->dev[entry]->offload_enabled = h->dev[entry]->offload_to_be_enabled; -hpsa_show_dev_msg (KERN_INFO , h, h->dev[entry],"updated" ); +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, h->dev[entry],"updated" ); h->dev[entry]->offload_enabled = offload_enabled; }
@@ -1298,7 +1302,7 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, h->dev[entry] = new_entry; added[*nadded] = new_entry; (*nadded)++; -hpsa_show_dev_msg (KERN_INFO , h, new_entry,"replaced" ); +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, new_entry,"replaced" ); new_entry->offload_to_be_enabled = new_entry->offload_enabled; new_entry->offload_enabled =0 ; }
@@ -1320,7 +1324,7 @@ static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,for (i = entry; i < h->ndevices-1 ; i++) h->dev[i] = h->dev[i+1 ]; h->ndevices--; -hpsa_show_dev_msg (KERN_INFO , h, sd,"removed" ); +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, sd,"removed" ); }#define SCSI3ADDR_EQ (a, b) ( \
@@ -1710,7 +1714,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,*/ if (sd[i]->volume_offline) {hpsa_show_volume_status (h, sd[i]); -hpsa_show_dev_msg (KERN_INFO , h, sd[i],"offline" ); +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, sd[i], +"offline" );continue ; }
@@ -1774,7 +1779,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,* future cmds to this device will get selection * timeout as if the device was gone. */ -hpsa_show_dev_msg (KERN_WARNING , h, removed[i], +hpsa_show_dev_msg (__stringify (KERN_WARNING ), + h, removed[i],"didn't find device for removal." ); } }
@@ -1789,7 +1795,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,if (scsi_add_device (sh, added[i]->bus, added[i]->target, added[i]->lun) ==0 )continue ; -hpsa_show_dev_msg (KERN_WARNING , h, added[i], +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, added[i],"addition failed, device not added." );/* now we have to remove it from h->dev, * since it didn't get added to scsi mid layer
@@ -5188,7 +5194,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)snprintf (msg,sizeof (msg),"cmd %d RESET FAILED, lockup detected" ,hpsa_get_cmd_index (scsicmd)); -hpsa_show_dev_msg (KERN_WARNING , h, dev, msg); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg);return FAILED ; }
@@ -5197,7 +5203,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)snprintf (msg,sizeof (msg),"cmd %d RESET FAILED, new lockup detected" ,hpsa_get_cmd_index (scsicmd)); -hpsa_show_dev_msg (KERN_WARNING , h, dev, msg); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg);return FAILED ; }
@@ -5205,14 +5211,14 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)if (is_hba_lunid (dev->scsi3addr))return SUCCESS ; -hpsa_show_dev_msg (KERN_WARNING , h, dev,"resetting" ); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"resetting" );/* send a reset to the SCSI LUN which the command was sent to */ rc =hpsa_do_reset (h, dev, dev->scsi3addr,HPSA_RESET_TYPE_LUN ,DEFAULT_REPLY_QUEUE );snprintf (msg,sizeof (msg),"reset %s" , rc ==0 ?"completed successfully" :"failed" ); -hpsa_show_dev_msg (KERN_WARNING , h, dev, msg); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg);return rc ==0 ?SUCCESS :FAILED ; }
@@ -5548,14 +5554,14 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)/* If controller locked up, we can guarantee command won't complete */ if (lockup_detected (h)) { -hpsa_show_dev_msg (KERN_WARNING , h, dev, +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"ABORT FAILED, lockup detected" );return FAILED ; }/* This is a good time to check if controller lockup has occurred */ if (detect_controller_lockup (h)) { -hpsa_show_dev_msg (KERN_WARNING , h, dev, +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"ABORT FAILED, new lockup detected" );return FAILED ; }
@@ -5610,7 +5616,8 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) as->cmd_len, as->cmnd[0 ], as->cmnd[1 ], as->serial_number);dev_warn (&h->pdev->dev,"%s BEING SENT\n" , msg); -hpsa_show_dev_msg (KERN_WARNING , h, dev,"Aborting command" ); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, +"Aborting command" );/* * Command is in flight, or possibly already completed
@@ -5629,7 +5636,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)wake_up_all (&h->abort_cmd_wait_queue);if (rc !=0 ) {dev_warn (&h->pdev->dev,"%s SENT, FAILED\n" , msg); -hpsa_show_dev_msg (KERN_WARNING , h, dev, +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"FAILED to abort command" );cmd_free (h, abort);return FAILED ;
Re: [PATCH 01/21] hpsa: correct calls to dev_printk
Quoted 17 lines · Don Brace
was seeing issues passing level into
hpsa_show_dev_msgand then using the level as an arguement todev_printk. For now, switch todev_warn.Signed-off-by Don Brace <[email protected]>--- drivers/scsi/hpsa.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-)drivers/scsi/hpsa.c +0
-1@@ -1137,11 +1137,15 @@ static int hpsa_find_target_lun(struct ctlr_info *h,static inline void hpsa_show_dev_msg (const char *level,struct ctlr_info *h,struct hpsa_scsi_dev_t *dev,char *description) { - dev_printk(level, &h->pdev->dev,
drivers/scsi/hpsa.c static int hpsa_find_target_lun(struct ctlr_info *h, · line 1148
Quoted 10 lines
drivers/scsi/hpsa.c +6
-1+if (dev ==NULL ) +return ; + + dev_warn(&h->pdev->dev, "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", h->scsi_host->host_no, dev->bus, dev->target, dev->lun, description, - scsi_device_type(dev->devtype), + dev->devtype >= 0 ? + scsi_device_type(dev->devtype) : "unknown",
Can devtype ever be negative? Found only this place in code where it is set "this_device->devtype = (inq_buff[0] & 0x1f);" And if it was negative the scsi_device_type will return "Unknown" anyway. You probably could skip the test now and switch devtype from int to unsigned in the future.
Cheers,
Tomas
Quoted 144 lines
drivers/scsi/hpsa.c +18
-16dev->vendor, dev->model, dev->raid_level > RAID_UNKNOWN ?@@ -1220,7 +1224,7 @@ lun_assigned: h->ndevices++; added[*nadded] = device; (*nadded)++; -hpsa_show_dev_msg (KERN_INFO , h, device, +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, device, device->expose_state &HPSA_SCSI_ADD ?"added" :"masked" ); device->offload_to_be_enabled = device->offload_enabled; device->offload_enabled =0 ;@@ -1271,7 +1275,7 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, offload_enabled = h->dev[entry]->offload_enabled; h->dev[entry]->offload_enabled = h->dev[entry]->offload_to_be_enabled; -hpsa_show_dev_msg (KERN_INFO , h, h->dev[entry],"updated" ); +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, h->dev[entry],"updated" ); h->dev[entry]->offload_enabled = offload_enabled; }@@ -1298,7 +1302,7 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, h->dev[entry] = new_entry; added[*nadded] = new_entry; (*nadded)++; -hpsa_show_dev_msg (KERN_INFO , h, new_entry,"replaced" ); +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, new_entry,"replaced" ); new_entry->offload_to_be_enabled = new_entry->offload_enabled; new_entry->offload_enabled =0 ; }@@ -1320,7 +1324,7 @@ static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,for (i = entry; i < h->ndevices-1 ; i++) h->dev[i] = h->dev[i+1 ]; h->ndevices--; -hpsa_show_dev_msg (KERN_INFO , h, sd,"removed" ); +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, sd,"removed" ); }#define SCSI3ADDR_EQ (a, b) ( \@@ -1710,7 +1714,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,*/ if (sd[i]->volume_offline) {hpsa_show_volume_status (h, sd[i]); -hpsa_show_dev_msg (KERN_INFO , h, sd[i],"offline" ); +hpsa_show_dev_msg (__stringify (KERN_INFO ), h, sd[i], +"offline" );continue ; }@@ -1774,7 +1779,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,* future cmds to this device will get selection * timeout as if the device was gone. */ -hpsa_show_dev_msg (KERN_WARNING , h, removed[i], +hpsa_show_dev_msg (__stringify (KERN_WARNING ), + h, removed[i],"didn't find device for removal." ); } }@@ -1789,7 +1795,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,if (scsi_add_device (sh, added[i]->bus, added[i]->target, added[i]->lun) ==0 )continue ; -hpsa_show_dev_msg (KERN_WARNING , h, added[i], +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, added[i],"addition failed, device not added." );/* now we have to remove it from h->dev, * since it didn't get added to scsi mid layer @@ -5188,7 +5194,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)snprintf (msg,sizeof (msg),"cmd %d RESET FAILED, lockup detected" ,hpsa_get_cmd_index (scsicmd)); -hpsa_show_dev_msg (KERN_WARNING , h, dev, msg); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg);return FAILED ; }@@ -5197,7 +5203,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)snprintf (msg,sizeof (msg),"cmd %d RESET FAILED, new lockup detected" ,hpsa_get_cmd_index (scsicmd)); -hpsa_show_dev_msg (KERN_WARNING , h, dev, msg); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg);return FAILED ; }@@ -5205,14 +5211,14 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)if (is_hba_lunid (dev->scsi3addr))return SUCCESS ; -hpsa_show_dev_msg (KERN_WARNING , h, dev,"resetting" ); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"resetting" );/* send a reset to the SCSI LUN which the command was sent to */ rc =hpsa_do_reset (h, dev, dev->scsi3addr,HPSA_RESET_TYPE_LUN ,DEFAULT_REPLY_QUEUE );snprintf (msg,sizeof (msg),"reset %s" , rc ==0 ?"completed successfully" :"failed" ); -hpsa_show_dev_msg (KERN_WARNING , h, dev, msg); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg);return rc ==0 ?SUCCESS :FAILED ; }@@ -5548,14 +5554,14 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)/* If controller locked up, we can guarantee command won't complete */ if (lockup_detected (h)) { -hpsa_show_dev_msg (KERN_WARNING , h, dev, +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"ABORT FAILED, lockup detected" );return FAILED ; }/* This is a good time to check if controller lockup has occurred */ if (detect_controller_lockup (h)) { -hpsa_show_dev_msg (KERN_WARNING , h, dev, +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"ABORT FAILED, new lockup detected" );return FAILED ; }@@ -5610,7 +5616,8 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) as->cmd_len, as->cmnd[0 ], as->cmnd[1 ], as->serial_number);dev_warn (&h->pdev->dev,"%s BEING SENT\n" , msg); -hpsa_show_dev_msg (KERN_WARNING , h, dev,"Aborting command" ); +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, +"Aborting command" );/* * Command is in flight, or possibly already completed @@ -5629,7 +5636,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)wake_up_all (&h->abort_cmd_wait_queue);if (rc !=0 ) {dev_warn (&h->pdev->dev,"%s SENT, FAILED\n" , msg); -hpsa_show_dev_msg (KERN_WARNING , h, dev, +hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"FAILED to abort command" );cmd_free (h, abort);return FAILED ; --To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 01/21] hpsa: correct calls to dev_printk
Quoted 34 lines · Tomas Henzl
Quoted 17 lines · Don Brace
was seeing issues passing level into
hpsa_show_dev_msgand then using the level as an arguement todev_printk. For now, switch todev_warn.Signed-off-by Don Brace <[email protected]>--- drivers/scsi/hpsa.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-)drivers/scsi/hpsa.c +0
-1@@ -1137,11 +1137,15 @@ static int hpsa_find_target_lun(struct ctlr_info *h,static inline void hpsa_show_dev_msg (const char *level,struct ctlr_info *h,struct hpsa_scsi_dev_t *dev,char *description) { - dev_printk(level, &h->pdev->dev,drivers/scsi/hpsa.c static int hpsa_find_target_lun(struct ctlr_info *h, · line 1148
Quoted 10 lines
drivers/scsi/hpsa.c +6
-1+if (dev ==NULL ) +return ; + + dev_warn(&h->pdev->dev, "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", h->scsi_host->host_no, dev->bus, dev->target, dev->lun, description, - scsi_device_type(dev->devtype), + dev->devtype >= 0 ? + scsi_device_type(dev->devtype) : "unknown",Can devtype ever be negative? Found only this place in code where it is set "
this_device->devtype= (inq_buff[0] &0x1f);" And if it was negative thescsi_device_typewill return "Unknown" anyway. You probably could skip the test now and switch devtype from int to unsigned in the future.
Quoted 4 lines
Cheers,
Tomas
Thanks, changed to unsigned and removed check.
Quoted 4 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/21 hpsa: allow driver requested rescans
In reply to Don Brace--- drivers/scsi/hpsa.c | 16 ++++++++++++++-- drivers/scsi/hpsa.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-)
drivers/scsi/hpsa.c +14 -2
@@ -3745,9 +3745,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) }memset (lunzerobits,0 ,sizeof (lunzerobits)); + h->drv_req_rescan =0 ;/* cancel scheduled rescan - we're doing it. */ +if (hpsa_gather_lun_info (h, physdev_list, &nphysicals, - logdev_list, &nlogicals)) + logdev_list, &nlogicals)) { + h->drv_req_rescan =1 ; goto out; + }/* We might see up to the maximum number of logical and physical disks * plus external target devices, and a device for the local RAID
@@ -3768,6 +3772,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)if (!currentsd[i]) {dev_warn (&h->pdev->dev,"out of memory at %s:%d\n" , __FILE__, __LINE__); + h->drv_req_rescan =1 ; goto out; } ndev_allocated++;
@@ -3795,8 +3800,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)/* Get device type, vendor, model, device id */ if (hpsa_update_device_info (h, lunaddrbytes, tmpdevice, - &is_OBDR)) + &is_OBDR)) { + h->drv_req_rescan =1 ;continue ;/* skip it if we can't talk to it. */ + }figure_bus_target_lun (h, lunaddrbytes, tmpdevice);hpsa_update_device_supports_aborts (h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent];
@@ -7867,6 +7874,11 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h)*/ static int hpsa_ctlr_needs_rescan (struct ctlr_info *h) { +if (h->drv_req_rescan) { + h->drv_req_rescan =0 ; +return 1 ; + } +if (!(h->fw_support &MISC_FW_EVENT_NOTIFY ))return 0 ;
drivers/scsi/hpsa.h +1 -0
@@ -262,6 +262,7 @@ struct ctlr_info {spinlock_t offline_device_lock;struct list_head offline_device_list;int acciopath_status; +int drv_req_rescan;int raid_offload_debug;int needs_abort_tags_swizzled;struct workqueue_struct *resubmit_wq;
Re: [PATCH 02/21] hpsa: allow driver requested rescans
Quoted 4 lines · Don Brace
Reviewed-by Scott Teel <[email protected]>Reviewed-by Justin Lindley <[email protected]>Reviewed-by Kevin Barnett <[email protected]>Signed-off-by Don Brace <[email protected]>
Tomas
PATCH 3/21 hpsa: abandon rescans on memory alloaction failures.
In reply to Don BraceAbandon and reschedule rescan process only if device inquiries fail due to mem alloc failures, which are likely to occur for all devices.
Otherwise, skip device if inquiry fails for other reasons, and continue rescanning process for other devices.
--- drivers/scsi/hpsa.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
drivers/scsi/hpsa.c +19 -5
@@ -3357,10 +3357,13 @@ static int hpsa_update_device_info(struct ctlr_info *h,unsigned char *inq_buff;unsigned char *obdr_sig; +int rc =0 ; inq_buff =kzalloc (OBDR_TAPE_INQ_SIZE ,GFP_KERNEL ); -if (!inq_buff) +if (!inq_buff) { + rc = -ENOMEM ; goto bail_out; + }/* Do an inquiry to the device to see what it is. */ if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
@@ -3368,6 +3371,7 @@ static int hpsa_update_device_info(struct ctlr_info *h,/* Inquiry failed (msg printed already) */ dev_err (&h->pdev->dev,"hpsa_update_device_info: inquiry failed\n" ); + rc =1 ; goto bail_out; }
@@ -3417,7 +3421,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, bail_out:kfree (inq_buff); -return 1 ; +return rc; } static void hpsa_update_device_supports_aborts(struct ctlr_info *h,
@@ -3787,6 +3791,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) n_ext_target_devs =0 ;for (i =0 ; i < nphysicals + nlogicals +1 ; i++) {u8 *lunaddrbytes, is_OBDR =0 ; +int rc =0 ;/* Figure out where the LUN ID info is coming from */ lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
@@ -3799,11 +3804,20 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)continue ;/* Get device type, vendor, model, device id */ -if (hpsa_update_device_info (h, lunaddrbytes, tmpdevice, - &is_OBDR)) { + rc =hpsa_update_device_info (h, lunaddrbytes, tmpdevice, + &is_OBDR); +if (rc == -ENOMEM ) { +dev_warn (&h->pdev->dev, +"Out of memory, rescan stopped.\n" ); h->drv_req_rescan =1 ; -continue ;/* skip it if we can't talk to it. */ + goto out; } +if (rc) { +dev_warn (&h->pdev->dev, +"Inquiry failed, skipping device.\n" ); +continue ; + } +figure_bus_target_lun (h, lunaddrbytes, tmpdevice);hpsa_update_device_supports_aborts (h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent];
Re: [PATCH 03/21] hpsa: abandon rescans on memory alloaction failures.
Quoted 60 lines · Don Brace
Abandon and reschedule rescan process only if device inquiries fail due to mem alloc failures, which are likely to occur for all devices.
Otherwise, skip device if inquiry fails for other reasons, and continue rescanning process for other devices.
Reviewed-by Scott Teel <[email protected]>Reviewed-by Justin Lindley <[email protected]>Reviewed-by Kevin Barnett <[email protected]>Signed-off-by Don Brace <[email protected]>--- drivers/scsi/hpsa.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)drivers/scsi/hpsa.c +7
-2@@ -3357,10 +3357,13 @@ static int hpsa_update_device_info(struct ctlr_info *h,unsigned char *inq_buff;unsigned char *obdr_sig; +int rc =0 ; inq_buff =kzalloc (OBDR_TAPE_INQ_SIZE ,GFP_KERNEL ); -if (!inq_buff) +if (!inq_buff) { + rc = -ENOMEM ; goto bail_out; + }/* Do an inquiry to the device to see what it is. */ if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,@@ -3368,6 +3371,7 @@ static int hpsa_update_device_info(struct ctlr_info *h,/* Inquiry failed (msg printed already) */ dev_err (&h->pdev->dev,"hpsa_update_device_info: inquiry failed\n" ); + rc =1 ; goto bail_out; }@@ -3417,7 +3421,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, bail_out:kfree (inq_buff); -return 1 ; +return rc; } static void hpsa_update_device_supports_aborts(struct ctlr_info *h,@@ -3787,6 +3791,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) n_ext_target_devs =0 ;for (i =0 ; i < nphysicals + nlogicals +1 ; i++) {u8 *lunaddrbytes, is_OBDR =0 ; +int rc =0 ;/* Figure out where the LUN ID info is coming from */ lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
drivers/scsi/hpsa.c static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) · line 3811
Quoted 10 lines
drivers/scsi/hpsa.c +5
-2@@ -3799,11 +3804,20 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)continue ;/* Get device type, vendor, model, device id */ -if (hpsa_update_device_info (h, lunaddrbytes, tmpdevice, - &is_OBDR)) { + rc =hpsa_update_device_info (h, lunaddrbytes, tmpdevice, + &is_OBDR); +if (rc == -ENOMEM ) { +dev_warn (&h->pdev->dev, +"Out of memory, rescan stopped.\n" );
What about 'rescan deferred" instead of "rescan stopped?
Quoted 18 lines
drivers/scsi/hpsa.c +7
-2h->drv_req_rescan =1 ; -continue ;/* skip it if we can't talk to it. */ + goto out; } +if (rc) { +dev_warn (&h->pdev->dev, +"Inquiry failed, skipping device.\n" ); +continue ; + } +figure_bus_target_lun (h, lunaddrbytes, tmpdevice);hpsa_update_device_supports_aborts (h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; --To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 03/21] hpsa: abandon rescans on memory alloaction failures.
Quoted 24 lines · Tomas Henzl
Quoted 23 lines · Don Brace
Abandon and reschedule rescan process only if device inquiries fail due to mem alloc failures, which are likely to occur for all devices.
Otherwise, skip device if inquiry fails for other reasons, and continue rescanning process for other devices.
Reviewed-by Scott Teel <[email protected]>Reviewed-by Justin Lindley <[email protected]>Reviewed-by Kevin Barnett <[email protected]>Signed-off-by Don Brace <[email protected]>--- drivers/scsi/hpsa.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)drivers/scsi/hpsa.c +0
-0@@ -3799,11 +3804,20 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)continue ;
Quoted 9 lines
drivers/scsi/hpsa.c static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) · line 3811
Quoted 8 lines
drivers/scsi/hpsa.c +5
-2/* Get device type, vendor, model, device id */ -if (hpsa_update_device_info (h, lunaddrbytes, tmpdevice, - &is_OBDR)) { + rc =hpsa_update_device_info (h, lunaddrbytes, tmpdevice, + &is_OBDR); +if (rc == -ENOMEM ) { +dev_warn (&h->pdev->dev, +"Out of memory, rescan stopped.\n" );What about 'rescan deferred" instead of "rescan stopped?
I can do either "rescan deferred" or "rescan rescheduled"
Quoted 24 lines
Quoted 17 lines
drivers/scsi/hpsa.c +7
-2h->drv_req_rescan =1 ; -continue ;/* skip it if we can't talk to it. */ + goto out; } +if (rc) { +dev_warn (&h->pdev->dev, +"Inquiry failed, skipping device.\n" ); +continue ; + } +figure_bus_target_lun (h, lunaddrbytes, tmpdevice);hpsa_update_device_supports_aborts (h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; --Quoted 3 lines
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 03/21] hpsa: abandon rescans on memory alloaction failures.
Quoted 34 lines · Don Brace
Quoted 24 lines · Tomas Henzl
Quoted 23 lines · Don Brace
Abandon and reschedule rescan process only if device inquiries fail due to mem alloc failures, which are likely to occur for all devices.
Otherwise, skip device if inquiry fails for other reasons, and continue rescanning process for other devices.
Reviewed-by Scott Teel <[email protected]>Reviewed-by Justin Lindley <[email protected]>Reviewed-by Kevin Barnett <[email protected]>Signed-off-by Don Brace <[email protected]>--- drivers/scsi/hpsa.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)drivers/scsi/hpsa.c +0
-0@@ -3799,11 +3804,20 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)continue ;Quoted 9 lines
drivers/scsi/hpsa.c static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) · line 3811
Quoted 8 lines
drivers/scsi/hpsa.c +5
-2/* Get device type, vendor, model, device id */ -if (hpsa_update_device_info (h, lunaddrbytes, tmpdevice, - &is_OBDR)) { + rc =hpsa_update_device_info (h, lunaddrbytes, tmpdevice, + &is_OBDR); +if (rc == -ENOMEM ) { +dev_warn (&h->pdev->dev, +"Out of memory, rescan stopped.\n" );What about 'rescan deferred" instead of "rescan stopped?
Quoted 1 line
I can do either "rescan deferred" or "rescan rescheduled"
Do what you prefer, it's your language.
Quoted 29 lines
Quoted 17 lines
Quoted 17 lines
drivers/scsi/hpsa.c +7
-1h->drv_req_rescan =1 ; -continue ;/* skip it if we can't talk to it. */ + goto out; } +if (rc) { +dev_warn (&h->pdev->dev, +"Inquiry failed, skipping device.\n" ); +continue ; + } +figure_bus_target_lun (h, lunaddrbytes, tmpdevice);hpsa_update_device_supports_aborts (h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent];Quoted 8 lines
Quoted 4 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Tomas Henzl
Reviewed-byRe: [PATCH 03/21] hpsa: abandon rescans on memory alloaction failures.
Quoted 35 lines · Tomas Henzl
Quoted 34 lines · Don Brace
Quoted 33 lines · Tomas Henzl
Quoted 21 lines · Don Brace
Abandon and reschedule rescan process only if device inquiries fail due to mem alloc failures, which are likely to occur for all devices.
Otherwise, skip device if inquiry fails for other reasons, and continue rescanning process for other devices.
Reviewed-by Scott Teel <[email protected]>Reviewed-by Justin Lindley <[email protected]>Reviewed-by Kevin Barnett <[email protected]>Signed-off-by Don Brace <[email protected]>--- drivers/scsi/hpsa.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)drivers/scsi/hpsa.c +0
-0drivers/scsi/hpsa.c static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) · line 3811
Quoted 10 lines
drivers/scsi/hpsa.c +5
-2@@ -3799,11 +3804,20 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)continue ;/* Get device type, vendor, model, device id */ -if (hpsa_update_device_info (h, lunaddrbytes, tmpdevice, - &is_OBDR)) { + rc =hpsa_update_device_info (h, lunaddrbytes, tmpdevice, + &is_OBDR); +if (rc == -ENOMEM ) { +dev_warn (&h->pdev->dev, +"Out of memory, rescan stopped.\n" );What about 'rescan deferred" instead of "rescan stopped?
Quoted 2 lines
Quoted 1 line
I can do either "rescan deferred" or "rescan rescheduled"
Do what you prefer, it's your language.
And with any option you may add -
Tomas
Quoted 33 lines
Quoted 25 lines
Quoted 17 lines
Quoted 17 lines
drivers/scsi/hpsa.c +7
-1h->drv_req_rescan =1 ; -continue ;/* skip it if we can't talk to it. */ + goto out; } +if (rc) { +dev_warn (&h->pdev->dev, +"Inquiry failed, skipping device.\n" ); +continue ; + } +figure_bus_target_lun (h, lunaddrbytes, tmpdevice);hpsa_update_device_supports_aborts (h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent];Quoted 8 lines
Quoted 4 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.htmlQuoted 4 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 4/21 hpsa: correct transfer length for 6 byte read/write commands
In reply to Don Bracehandle block counts of 0. Cleanup block and block count calculations.
--- drivers/scsi/hpsa.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-)
drivers/scsi/hpsa.c +6 -13
@@ -4005,19 +4005,14 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len)case READ_6 :case READ_12 :if (*cdb_len ==6 ) { - block = (((u32 ) cdb[2 ]) <<8 ) | cdb[3 ]; + block =get_unaligned_be16 (&cdb[2 ]); block_cnt = cdb[4 ]; +if (block_cnt ==0 ) + block_cnt =256 ; }else {BUG_ON (*cdb_len !=12 ); - block = (((u32 ) cdb[2 ]) <<24 ) | - (((u32 ) cdb[3 ]) <<16 ) | - (((u32 ) cdb[4 ]) <<8 ) | - cdb[5 ]; - block_cnt = - (((u32 ) cdb[6 ]) <<24 ) | - (((u32 ) cdb[7 ]) <<16 ) | - (((u32 ) cdb[8 ]) <<8 ) | - cdb[9 ]; + block =get_unaligned_be32 (&cdb[2 ]); + block_cnt =get_unaligned_be32 (&cdb[6 ]); }if (block_cnt >0xffff )return IO_ACCEL_INELIGIBLE ;
@@ -4403,9 +4398,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,case WRITE_6 : is_write =1 ;case READ_6 : - first_block = - (((u64 ) cmd->cmnd[2 ]) <<8 ) | - cmd->cmnd[3 ]; + first_block =get_unaligned_be16 (&cmd->cmnd[2 ]); block_cnt = cmd->cmnd[4 ];if (block_cnt ==0 ) block_cnt =256 ;
Re: [PATCH 04/21] hpsa: correct transfer length for 6 byte read/write commands
Quoted 6 lines · Don Brace
handle block counts of 0. Cleanup block and block count calculations.
Reviewed-by Scott Teel <[email protected]>Reviewed-by Justin Lindley <[email protected]>Reviewed-by Kevin Barnett <[email protected]>Signed-off-by Don Brace <[email protected]>
Tomas
PATCH 5/21 hpsa: fix hpsa_adjust_hpsa_scsi_table
In reply to Don BraceFix a NULL pointer issue in the driver when devices are removed during a reset.
--- drivers/block/cciss.h | 1 + drivers/scsi/hpsa.c | 16 ++++++++++++++++ drivers/scsi/hpsa.h | 1 + 3 files changed, 18 insertions(+)
drivers/block/cciss.h +1 -0
@@ -155,6 +155,7 @@ struct ctlr_infosize_t reply_pool_size;unsigned char reply_pool_wraparound;u32 *blockFetchTable; +atomic_t reset_in_progress; };/* Defining the diffent access_methods
drivers/scsi/hpsa.c +16 -0
@@ -1656,6 +1656,11 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,int nadded, nremoved;struct Scsi_Host *sh =NULL ; +if (atomic_read (&h->reset_in_progress)) { + h->drv_req_rescan =1 ; +return ; + } + added =kzalloc (sizeof (*added) *HPSA_MAX_DEVICES ,GFP_KERNEL ); removed =kzalloc (sizeof (*removed) *HPSA_MAX_DEVICES ,GFP_KERNEL );
@@ -1764,8 +1769,14 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, goto free_and_out; sh = h->scsi_host; +if (sh ==NULL ) { +dev_warn (&h->pdev->dev,"%s: scsi_host is null\n" , __func__); +return ; + }/* Notify scsi mid layer of any removed devices */ for (i =0 ; i < nremoved; i++) { +if (!removed[i]) +continue ;if (removed[i]->expose_state &HPSA_SCSI_ADD ) {struct scsi_device *sdev = scsi_device_lookup(sh, removed[i]->bus,
@@ -1790,6 +1801,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,/* Notify scsi mid layer of any added devices */ for (i =0 ; i < nadded; i++) { +if (!added[i]) +continue ;if (!(added[i]->expose_state &HPSA_SCSI_ADD ))continue ; if (scsi_add_device(sh, added[i]->bus,
@@ -5227,12 +5240,15 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"resetting" ); +atomic_set (&h->reset_in_progress,1 ); +/* send a reset to the SCSI LUN which the command was sent to */ rc =hpsa_do_reset (h, dev, dev->scsi3addr,HPSA_RESET_TYPE_LUN ,DEFAULT_REPLY_QUEUE );snprintf (msg,sizeof (msg),"reset %s" , rc ==0 ?"completed successfully" :"failed" );hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg); +atomic_set (&h->reset_in_progress,0 );return rc ==0 ?SUCCESS :FAILED ; }
drivers/scsi/hpsa.h +1 -0
@@ -271,6 +271,7 @@ struct ctlr_info {wait_queue_head_t abort_cmd_wait_queue;wait_queue_head_t event_sync_wait_queue;struct mutex reset_mutex; +atomic_t reset_in_progress; };struct offline_device_entry {
Re: [PATCH 05/21] hpsa: fix hpsa_adjust_hpsa_scsi_table
Quoted 27 lines · Don Brace
Fix a NULL pointer issue in the driver when devices are removed during a reset.
Signed-off-by Don Brace <[email protected]>--- drivers/block/cciss.h | 1 + drivers/scsi/hpsa.c | 16 ++++++++++++++++ drivers/scsi/hpsa.h | 1 + 3 files changed, 18 insertions(+)drivers/block/cciss.h +1
-0@@ -155,6 +155,7 @@ struct ctlr_infosize_t reply_pool_size;unsigned char reply_pool_wraparound;u32 *blockFetchTable; +atomic_t reset_in_progress; };/* Defining the diffent access_methods drivers/scsi/hpsa.c +0
-0
drivers/scsi/hpsa.c static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, · line 1662
Quoted 7 lines
drivers/scsi/hpsa.c +4
-0@@ -1656,6 +1656,11 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,int nadded, nremoved;struct Scsi_Host *sh =NULL ; +if (atomic_read (&h->reset_in_progress)) { + h->drv_req_rescan =1 ; +return ; + }
Is it safe, what happens when a reset is invoked at this point? Is it possible to somehow reuse the scan_lock or scan_finished and change the logic and wait with the reset?
(maybe break and reschedule the scan)
Btw. why is an atomic variable needed here?
--tm
Quoted 61 lines
drivers/scsi/hpsa.c +12
-0+ added =kzalloc (sizeof (*added) *HPSA_MAX_DEVICES ,GFP_KERNEL ); removed =kzalloc (sizeof (*removed) *HPSA_MAX_DEVICES ,GFP_KERNEL );@@ -1764,8 +1769,14 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, goto free_and_out; sh = h->scsi_host; +if (sh ==NULL ) { +dev_warn (&h->pdev->dev,"%s: scsi_host is null\n" , __func__); +return ; + }/* Notify scsi mid layer of any removed devices */ for (i =0 ; i < nremoved; i++) { +if (!removed[i]) +continue ;if (removed[i]->expose_state &HPSA_SCSI_ADD ) {struct scsi_device *sdev = scsi_device_lookup(sh, removed[i]->bus,@@ -1790,6 +1801,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,/* Notify scsi mid layer of any added devices */ for (i =0 ; i < nadded; i++) { +if (!added[i]) +continue ;if (!(added[i]->expose_state &HPSA_SCSI_ADD ))continue ; if (scsi_add_device(sh, added[i]->bus,@@ -5227,12 +5240,15 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"resetting" ); +atomic_set (&h->reset_in_progress,1 ); +/* send a reset to the SCSI LUN which the command was sent to */ rc =hpsa_do_reset (h, dev, dev->scsi3addr,HPSA_RESET_TYPE_LUN ,DEFAULT_REPLY_QUEUE );snprintf (msg,sizeof (msg),"reset %s" , rc ==0 ?"completed successfully" :"failed" );hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg); +atomic_set (&h->reset_in_progress,0 );return rc ==0 ?SUCCESS :FAILED ; }drivers/scsi/hpsa.h +1
-1@@ -271,6 +271,7 @@ struct ctlr_info {wait_queue_head_t abort_cmd_wait_queue;wait_queue_head_t event_sync_wait_queue;struct mutex reset_mutex; +atomic_t reset_in_progress; };struct offline_device_entry { --To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 05/21] hpsa: fix hpsa_adjust_hpsa_scsi_table
Quoted 31 lines · Tomas Henzl
Quoted 30 lines · Don Brace
Fix a NULL pointer issue in the driver when devices are removed during a reset.
Signed-off-by Don Brace <[email protected]>--- drivers/block/cciss.h | 1 + drivers/scsi/hpsa.c | 16 ++++++++++++++++ drivers/scsi/hpsa.h | 1 + 3 files changed, 18 insertions(+)drivers/block/cciss.h +1
-0@@ -155,6 +155,7 @@ struct ctlr_infosize_t reply_pool_size;unsigned char reply_pool_wraparound;u32 *blockFetchTable; +atomic_t reset_in_progress; };/* Defining the diffent access_methods drivers/scsi/hpsa.c +0
-0@@ -1656,6 +1656,11 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,int nadded, nremoved;struct Scsi_Host *sh =NULL ;
Quoted 8 lines
drivers/scsi/hpsa.c static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, · line 1662
Quoted 4 lines
drivers/scsi/hpsa.c +4
-0+if (atomic_read (&h->reset_in_progress)) { + h->drv_req_rescan =1 ; +return ; + }Is it safe, what happens when a reset is invoked at this point? Is it possible to somehow reuse the
scan_lockorscan_finishedand change the logic and wait with the reset?
(maybe break and reschedule the scan)
I wanted to reschedule the scan to see what happened after a reset.
There also seems to be some raciness between the reset handler and the re-scan procedure.
Quoted 1 line
Btw. why is an atomic variable needed here?
Overkill. I can change reset_in_progress to an int.
Quoted 68 lines
--tm
Quoted 58 lines
drivers/scsi/hpsa.c +12
-0+ added =kzalloc (sizeof (*added) *HPSA_MAX_DEVICES ,GFP_KERNEL ); removed =kzalloc (sizeof (*removed) *HPSA_MAX_DEVICES ,GFP_KERNEL );@@ -1764,8 +1769,14 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, goto free_and_out; sh = h->scsi_host; +if (sh ==NULL ) { +dev_warn (&h->pdev->dev,"%s: scsi_host is null\n" , __func__); +return ; + }/* Notify scsi mid layer of any removed devices */ for (i =0 ; i < nremoved; i++) { +if (!removed[i]) +continue ;if (removed[i]->expose_state &HPSA_SCSI_ADD ) {struct scsi_device *sdev = scsi_device_lookup(sh, removed[i]->bus,@@ -1790,6 +1801,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,/* Notify scsi mid layer of any added devices */ for (i =0 ; i < nadded; i++) { +if (!added[i]) +continue ;if (!(added[i]->expose_state &HPSA_SCSI_ADD ))continue ; if (scsi_add_device(sh, added[i]->bus,@@ -5227,12 +5240,15 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"resetting" ); +atomic_set (&h->reset_in_progress,1 ); +/* send a reset to the SCSI LUN which the command was sent to */ rc =hpsa_do_reset (h, dev, dev->scsi3addr,HPSA_RESET_TYPE_LUN ,DEFAULT_REPLY_QUEUE );snprintf (msg,sizeof (msg),"reset %s" , rc ==0 ?"completed successfully" :"failed" );hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg); +atomic_set (&h->reset_in_progress,0 );return rc ==0 ?SUCCESS :FAILED ; }drivers/scsi/hpsa.h +1
-1@@ -271,6 +271,7 @@ struct ctlr_info {wait_queue_head_t abort_cmd_wait_queue;wait_queue_head_t event_sync_wait_queue;struct mutex reset_mutex; +atomic_t reset_in_progress; };struct offline_device_entry { --Quoted 3 lines
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 6/21 hpsa: fix physical target reset
In reply to Don BraceFrom: Scott Teel <[email protected]>
Set reset type in device_reset_handler to do either logical unit reset for logical devices, or physical target reset, for physical devices.
--- drivers/scsi/hpsa.c | 33 +++++++++++++++++++++++++++------ drivers/scsi/hpsa.h | 1 + 2 files changed, 28 insertions(+), 6 deletions(-)
drivers/scsi/hpsa.c +27 -6
@@ -2728,9 +2728,8 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr,/* fill_cmd can't fail here, no data buffer to map. */ - (void )fill_cmd (c,HPSA_DEVICE_RESET_MSG , h,NULL ,0 ,0 , + (void )fill_cmd (c, reset_type, h,NULL ,0 ,0 , scsi3addr,TYPE_MSG ); - c->Request.CDB[1 ] = reset_type;/* fill_cmd defaults to LUN reset */ rc =hpsa_scsi_do_simple_cmd (h, c, reply_queue,NO_TIMEOUT );if (rc) {dev_warn (&h->pdev->dev,"Failed to send reset command\n" );
@@ -5200,6 +5199,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)int rc;struct ctlr_info *h;struct hpsa_scsi_dev_t *dev; +u8 reset_type;char msg[48 ];/* find the controller to which the command to be aborted was sent */
@@ -5238,15 +5238,22 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)if (is_hba_lunid (dev->scsi3addr))return SUCCESS ; -hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev,"resetting" ); +if (is_logical_dev_addr_mode (dev->scsi3addr)) + reset_type =HPSA_DEVICE_RESET_MSG ; +else + reset_type =HPSA_PHYS_TARGET_RESET ; + +sprintf (msg,"resetting %s" , + reset_type ==HPSA_DEVICE_RESET_MSG ?"logical " :"physical " );atomic_set (&h->reset_in_progress,1 );/* send a reset to the SCSI LUN which the command was sent to */ - rc =hpsa_do_reset (h, dev, dev->scsi3addr,HPSA_RESET_TYPE_LUN , + rc =hpsa_do_reset (h, dev, dev->scsi3addr, reset_type,DEFAULT_REPLY_QUEUE ); -snprintf (msg,sizeof (msg),"reset %s" , - rc ==0 ?"completed successfully" :"failed" ); +sprintf (msg,"reset %s %s" , + reset_type ==HPSA_DEVICE_RESET_MSG ?"logical " :"physical " , + rc ==0 ?"completed successfully" :"failed" );hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, dev, msg);atomic_set (&h->reset_in_progress,0 );return rc ==0 ?SUCCESS :FAILED ;
@@ -6364,6 +6371,20 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, }else if (cmd_type ==TYPE_MSG ) {switch (cmd) { +case HPSA_PHYS_TARGET_RESET : + c->Request.CDBLen =16 ; + c->Request.type_attr_dir = +TYPE_ATTR_DIR (cmd_type,ATTR_SIMPLE ,XFER_NONE ); + c->Request.Timeout =0 ;/* Don't time out */ +memset (&c->Request.CDB[0 ],0 ,sizeof (c->Request.CDB)); + c->Request.CDB[0 ] =HPSA_RESET ; + c->Request.CDB[1 ] =HPSA_TARGET_RESET_TYPE ; +/* Physical target reset needs no control bytes 4-7*/ + c->Request.CDB[4 ] =0x00 ; + c->Request.CDB[5 ] =0x00 ; + c->Request.CDB[6 ] =0x00 ; + c->Request.CDB[7 ] =0x00 ; +break ;case HPSA_DEVICE_RESET_MSG : c->Request.CDBLen =16 ; c->Request.type_attr_dir =
drivers/scsi/hpsa.h +1 -0
@@ -285,6 +285,7 @@ struct offline_device_entry {#define HPSA_RESET_TYPE_BUS 0x01#define HPSA_RESET_TYPE_TARGET 0x03#define HPSA_RESET_TYPE_LUN 0x04 +#define HPSA_PHYS_TARGET_RESET 0x99/* not defined by cciss spec */ #define HPSA_MSG_SEND_RETRY_LIMIT 10#define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS (10000)
PATCH 7/21 hpsa: correct check for non-disk devices
In reply to Don BraceThe driver is using two MACROs which seemingly are looking in the wrong location for the device_flags returned from CISS_REPORT_PHYS. Both MACROs, NON_DISK_PHYS_DEV and PHYS_IOACCEL, are using the pointer returned from figure_lunaddrbytes which is the address of the LUN.lunid element in
the extended CISS_REPORT_PHYS. But the MACROS are using offsets beyond the range of the element (offset 17 of an 8 byte element).
These MACROs actually are looking at the correct location but they fail static checker analysis. It also will not work if any new elements are added to the extended LUN structure.
Change the code to use the structure elements directly since this MACRO is only used in one location.
--- drivers/scsi/hpsa.c | 28 +++++++++++++++------------- drivers/scsi/hpsa_cmd.h | 2 -- 2 files changed, 15 insertions(+), 15 deletions(-)
drivers/scsi/hpsa.c +15 -13
@@ -3672,19 +3672,18 @@ static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position,/* get physical drive ioaccel handle and queue depth */ static void hpsa_get_ioaccel_drive_info (struct ctlr_info *h,struct hpsa_scsi_dev_t *dev, -u8 *lunaddrbytes, +struct ReportExtendedLUNdata *rlep,int rle_index,struct bmic_identify_physical_device *id_phys) {int rc; -struct ext_report_lun_entry *rle = - (struct ext_report_lun_entry *) lunaddrbytes; +struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; dev->ioaccel_handle = rle->ioaccel_handle; -if (PHYS_IOACCEL (lunaddrbytes) && dev->ioaccel_handle) +if ((rle->device_flags &0x08 ) && dev->ioaccel_handle) dev->hba_ioaccel_enabled =1 ;memset (id_phys,0 ,sizeof (*id_phys)); - rc =hpsa_bmic_id_physical_device (h, lunaddrbytes, -GET_BMIC_DRIVE_NUMBER (lunaddrbytes), id_phys, + rc =hpsa_bmic_id_physical_device (h, &rle->lunid[0 ], +GET_BMIC_DRIVE_NUMBER (&rle->lunid[0 ]), id_phys,sizeof (*id_phys));if (!rc)/* Reserve space for FW operations */
@@ -3700,11 +3699,12 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, }static void hpsa_get_path_info (struct hpsa_scsi_dev_t *this_device, -u8 *lunaddrbytes, +struct ReportExtendedLUNdata *rlep,int rle_index,struct bmic_identify_physical_device *id_phys) { -if (PHYS_IOACCEL (lunaddrbytes) - && this_device->ioaccel_handle) +struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; + +if ((rle->device_flags &0x08 ) && this_device->ioaccel_handle) this_device->hba_ioaccel_enabled =1 ; memcpy(&this_device->active_path_index,
@@ -3804,6 +3804,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)for (i =0 ; i < nphysicals + nlogicals +1 ; i++) {u8 *lunaddrbytes, is_OBDR =0 ;int rc =0 ; +int phys_dev_index = i - (raid_ctlr_position ==0 );/* Figure out where the LUN ID info is coming from */ lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
@@ -3812,7 +3813,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)/* skip masked non-disk devices */ if (MASKED_DEVICE (lunaddrbytes))if (i < nphysicals + (raid_ctlr_position ==0 ) && -NON_DISK_PHYS_DEV (lunaddrbytes)) + (physdev_list-> + LUN[phys_dev_index].device_flags &0x01 ))continue ;/* Get device type, vendor, model, device id */
@@ -3877,9 +3879,9 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)/* Never use RAID mapper in HBA mode. */ this_device->offload_enabled =0 ;hpsa_get_ioaccel_drive_info (h, this_device, - lunaddrbytes, id_phys); -hpsa_get_path_info (this_device, lunaddrbytes, - id_phys); + physdev_list, phys_dev_index, id_phys); +hpsa_get_path_info (this_device, + physdev_list, phys_dev_index, id_phys); } ncurrent++;break ;
drivers/scsi/hpsa_cmd.h +0 -2
@@ -260,8 +260,6 @@ struct ext_report_lun_entry {u8 wwid[8 ];u8 device_type;u8 device_flags; -#define NON_DISK_PHYS_DEV (x) ((x)[17] & 0x01) -#define PHYS_IOACCEL (x) ((x)[17] & 0x08)u8 lun_count;/* multi-lun device, how many luns */ u8 redundant_paths;u32 ioaccel_handle;/* ioaccel1 only uses lower 16 bits */
PATCH 8/21 hpsa: correct ioaccel2 sg chain len
In reply to Don Brace--- drivers/scsi/hpsa.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/scsi/hpsa.c +3 -2
@@ -1974,7 +1974,7 @@ static int hpsa_map_ioaccel2_sg_chain_block(struct ctlr_info *h,u32 chain_size; chain_block = h->ioaccel2_cmd_sg_list[c->cmdindex]; - chain_size =le32_to_cpu (cp->data_len); + chain_size =le32_to_cpu (cp->sg[0 ].length); temp64 =pci_map_single (h->pdev, chain_block, chain_size,PCI_DMA_TODEVICE );if (dma_mapping_error (&h->pdev->dev, temp64)) {
@@ -1995,7 +1995,7 @@ static void hpsa_unmap_ioaccel2_sg_chain_block(struct ctlr_info *h, chain_sg = cp->sg; temp64 =le64_to_cpu (chain_sg->address); - chain_size =le32_to_cpu (cp->data_len); + chain_size =le32_to_cpu (cp->sg[0 ].length);pci_unmap_single (h->pdev, temp64, chain_size,PCI_DMA_TODEVICE ); }
@@ -4308,6 +4308,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,/* fill in sg elements */ if (use_sg > h->ioaccel_maxsg) { cp->sg_count =1 ; + cp->sg[0 ].length =cpu_to_le32 (use_sg *sizeof (cp->sg[0 ]));if (hpsa_map_ioaccel2_sg_chain_block (h, cp, c)) {atomic_dec (&phys_disk->ioaccel_cmds_out);scsi_dma_unmap (cmd);
PATCH 9/21 hpsa: simplify check for device exposure
In reply to Don BraceFrom: Kevin Barnett <[email protected]>
remove macros and cleanup device exposure checking
--- drivers/scsi/hpsa.c | 25 +++++++++++-------------- drivers/scsi/hpsa.h | 6 +----- 2 files changed, 12 insertions(+), 19 deletions(-)
drivers/scsi/hpsa.c +11 -14
@@ -791,8 +791,7 @@ static ssize_t path_info_show(struct device *dev,PATH_STRING_LEN ,"PORT: %.2s " , phys_connector); -if (hdev->devtype ==TYPE_DISK && - hdev->expose_state !=HPSA_DO_NOT_EXPOSE ) { +if (hdev->devtype ==TYPE_DISK && hdev->expose_device) {if (box ==0 || box ==0xFF ) { output_len += snprintf(path[i] + output_len, PATH_STRING_LEN,
@@ -1152,7 +1151,7 @@ static inline void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, "RAID-?" : raid_label[dev->raid_level], dev->offload_config ?'+' :'-' , dev->offload_enabled ?'+' :'-' , - dev->expose_state); + dev->expose_device); }/* Add an entry into h->dev[] array. */
@@ -1225,7 +1224,7 @@ lun_assigned: added[*nadded] = device; (*nadded)++;hpsa_show_dev_msg (__stringify (KERN_INFO ), h, device, - device->expose_state &HPSA_SCSI_ADD ?"added" :"masked" ); + device->expose_device ?"added" :"masked" ); device->offload_to_be_enabled = device->offload_enabled; device->offload_enabled =0 ;return 0 ;
@@ -1777,7 +1776,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,for (i =0 ; i < nremoved; i++) {if (!removed[i])continue ; -if (removed[i]->expose_state &HPSA_SCSI_ADD ) { +if (removed[i]->expose_device) {struct scsi_device *sdev =scsi_device_lookup (sh, removed[i]->bus, removed[i]->target, removed[i]->lun);
@@ -1803,7 +1802,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,for (i =0 ; i < nadded; i++) {if (!added[i])continue ; -if (!(added[i]->expose_state &HPSA_SCSI_ADD )) +if (!(added[i]->expose_device))continue ;if (scsi_add_device (sh, added[i]->bus, added[i]->target, added[i]->lun) ==0 )
@@ -1852,7 +1851,7 @@ static int hpsa_slave_alloc(struct scsi_device *sdev) sdev_id(sdev), sdev->lun);if (likely (sd)) {atomic_set (&sd->ioaccel_cmds_out,0 ); - sdev->hostdata = (sd->expose_state &HPSA_SCSI_ADD ) ? sd :NULL ; + sdev->hostdata = sd->expose_device ? sd :NULL ; }else sdev->hostdata =NULL ;spin_unlock_irqrestore (&h->devlock, flags);
@@ -1866,7 +1865,7 @@ static int hpsa_slave_configure(struct scsi_device *sdev)int queue_depth; sd = sdev->hostdata; - sdev->no_uld_attach = !sd || !(sd->expose_state &HPSA_ULD_ATTACH ); + sdev->no_uld_attach = !sd || !sd->expose_device;if (sd) queue_depth = sd->queue_depth != 0 ?
@@ -3854,12 +3853,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)/* do not expose masked devices */ if (MASKED_DEVICE (lunaddrbytes) && - i < nphysicals + (raid_ctlr_position ==0 )) { - this_device->expose_state =HPSA_DO_NOT_EXPOSE ; - }else { - this_device->expose_state = -HPSA_SG_ATTACH |HPSA_ULD_ATTACH ; - } + i < nphysicals + (raid_ctlr_position ==0 )) + this_device->expose_device =0 ; +else + this_device->expose_device =1 ;switch (this_device->devtype) {case TYPE_ROM :
drivers/scsi/hpsa.h +1 -5
@@ -37,6 +37,7 @@ struct hpsa_scsi_dev_t {int devtype;int bus, target, lun;/* as presented to the OS */ unsigned char scsi3addr[8 ];/* as presented to the HW */ +u8 expose_device;#define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"unsigned char device_id[16 ];/* from inquiry pg. 0x83 */ unsigned char vendor[8 ];/* bytes 8-15 of inquiry data */
@@ -75,11 +76,6 @@ struct hpsa_scsi_dev_t {struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES ];int nphysical_disks;int supports_aborts; -#define HPSA_DO_NOT_EXPOSE 0x0 -#define HPSA_SG_ATTACH 0x1 -#define HPSA_ULD_ATTACH 0x2 -#define HPSA_SCSI_ADD (HPSA_SG_ATTACH | HPSA_ULD_ATTACH) -u8 expose_state; };struct reply_queue_buffer {
PATCH 10/21 hpsa: simplify update scsi devices
In reply to Don BraceFrom: Kevin Barnett <[email protected]>
remove repeated calculation that checks for physical or logical devices.
--- drivers/scsi/hpsa.c | 23 ++++++++++++++--------- drivers/scsi/hpsa.h | 1 + 2 files changed, 15 insertions(+), 9 deletions(-)
drivers/scsi/hpsa.c +14 -9
@@ -3745,6 +3745,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)int ncurrent =0 ;int i, n_ext_target_devs, ndevs_to_allocate;int raid_ctlr_position; +bool physical_device;DECLARE_BITMAP (lunzerobits,MAX_EXT_TARGETS ); currentsd =kzalloc (sizeof (*currentsd) *HPSA_MAX_DEVICES ,GFP_KERNEL );
@@ -3805,16 +3806,17 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)int rc =0 ;int phys_dev_index = i - (raid_ctlr_position ==0 ); + physical_device = i < nphysicals + (raid_ctlr_position ==0 ); +/* Figure out where the LUN ID info is coming from */ lunaddrbytes =figure_lunaddrbytes (h, raid_ctlr_position, i, nphysicals, nlogicals, physdev_list, logdev_list);/* skip masked non-disk devices */ -if (MASKED_DEVICE (lunaddrbytes)) -if (i < nphysicals + (raid_ctlr_position ==0 ) && - (physdev_list-> - LUN[phys_dev_index].device_flags &0x01 )) -continue ; +if (physical_device && +MASKED_DEVICE (lunaddrbytes) && + (physdev_list->LUN[phys_dev_index].device_flags &0x01 )) +continue ;/* Get device type, vendor, model, device id */ rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
@@ -3850,10 +3852,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) } *this_device = *tmpdevice; + this_device->physical_device = physical_device; -/* do not expose masked devices */ -if (MASKED_DEVICE (lunaddrbytes) && - i < nphysicals + (raid_ctlr_position ==0 )) +/* +* Expose all devices except for physical devices that +* are masked. +*/ +if (MASKED_DEVICE (lunaddrbytes) && this_device->physical_device) this_device->expose_device =0 ;else this_device->expose_device =1 ;
@@ -3871,7 +3876,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) ncurrent++;break ;case TYPE_DISK : -if (i < nphysicals + (raid_ctlr_position ==0 )) { +if (this_device->physical_device) {/* The disk is in HBA mode. */ /* Never use RAID mapper in HBA mode. */ this_device->offload_enabled =0 ;
drivers/scsi/hpsa.h +1 -0
@@ -37,6 +37,7 @@ struct hpsa_scsi_dev_t {int devtype;int bus, target, lun;/* as presented to the OS */ unsigned char scsi3addr[8 ];/* as presented to the HW */ +u8 physical_device;u8 expose_device;#define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"unsigned char device_id[16 ];/* from inquiry pg. 0x83 */
PATCH 11/21 hpsa: add function is_logical_device
In reply to Don BraceFrom: Kevin Barnett <[email protected]>
simplify checking for logical/physical devices
--- drivers/scsi/hpsa.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
drivers/scsi/hpsa.c +12 -7
@@ -617,6 +617,11 @@ static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6",#define HPSA_RAID_ADM 6/* also used for RAID 1+0 ADM */ #define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1) +static inline bool is_logical_device (struct hpsa_scsi_dev_t *device) +{ +return !device->physical_device; +} +static ssize_t raid_level_show (struct device *dev,struct device_attribute *attr,char *buf) {
@@ -637,7 +642,7 @@ static ssize_t raid_level_show(struct device *dev, }/* Is this even a logical drive? */ -if (!is_logical_dev_addr_mode (hdev->scsi3addr)) { +if (!is_logical_device (hdev)) {spin_unlock_irqrestore (&h->lock, flags); l =snprintf (buf,PAGE_SIZE ,"N/A\n" );return l;
@@ -771,8 +776,8 @@ static ssize_t path_info_show(struct device *dev, scsi_device_type(hdev->devtype));if (is_ext_target (h, hdev) || - (hdev->devtype ==TYPE_RAID ) || -is_logical_dev_addr_mode (hdev->scsi3addr)) { + hdev->devtype ==TYPE_RAID || +is_logical_device (hdev)) { output_len +=snprintf (path[i] + output_len,PATH_STRING_LEN ,"%s\n" , active);
@@ -1582,7 +1587,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h,for (j =0 ; j < ndevices; j++) {if (dev[j]->devtype !=TYPE_DISK )continue ; -if (is_logical_dev_addr_mode (dev[j]->scsi3addr)) +if (is_logical_device (dev[j]))continue ;if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle)continue ;
@@ -1625,7 +1630,7 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,for (i =0 ; i < ndevices; i++) {if (dev[i]->devtype !=TYPE_DISK )continue ; -if (!is_logical_dev_addr_mode (dev[i]->scsi3addr)) +if (!is_logical_device (dev[i]))continue ;/*
@@ -2228,7 +2233,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h,* the normal I/O path so the controller can handle whatever's * wrong. */ -if (is_logical_dev_addr_mode (dev->scsi3addr) && +if (is_logical_device (dev) && c2->error_data.serv_response ==IOACCEL2_SERV_RESPONSE_FAILURE ) { if (c2->error_data.status ==
@@ -2348,7 +2353,7 @@ static void complete_scsi_command(struct CommandList *cp)* the normal I/O path so the controller can handle whatever's * wrong. */ -if (is_logical_dev_addr_mode (dev->scsi3addr)) { +if (is_logical_device (dev)) {if (ei->CommandStatus ==CMD_IOACCEL_DISABLED ) dev->offload_enabled =0 ;return hpsa_retry_cmd (h, cp);
PATCH 12/21 hpsa: enhance hpsa_get_device_id
In reply to Don Braceuse an index into vpd data for SAS/SATA drives
--- drivers/scsi/hpsa.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)
drivers/scsi/hpsa.c +20 -3
@@ -3119,7 +3119,7 @@ out:/* Get the device id from inquiry page 0x83 */ static int hpsa_get_device_id (struct ctlr_info *h,unsigned char *scsi3addr, -unsigned char *device_id,int buflen) +unsigned char *device_id,int index,int buflen) {int rc;unsigned char *buf;
@@ -3131,8 +3131,10 @@ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr,return -ENOMEM ; rc =hpsa_scsi_do_inquiry (h, scsi3addr,VPD_PAGE |0x83 , buf,64 );if (rc ==0 ) -memcpy (device_id, &buf[8 ], buflen); +memcpy (device_id, &buf[index], buflen); +kfree (buf); +return rc !=0 ; }
@@ -3361,6 +3363,18 @@ static int hpsa_device_supports_aborts(struct ctlr_info *h,return rc; } +static void sanitize_inquiry_string (unsigned char *s,int len) +{ +bool terminated = false; + +for (; len >0 ; (--len, ++s)) { +if (*s ==0 ) + terminated = true; +if (terminated || *s <0x20 || *s >0x7e ) + *s =' ' ; + } +} +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)
@@ -3391,6 +3405,9 @@ static int hpsa_update_device_info(struct ctlr_info *h, goto bail_out; } +sanitize_inquiry_string (&inq_buff[8 ],8 ); +sanitize_inquiry_string (&inq_buff[16 ],16 ); + this_device->devtype = (inq_buff[0 ] &0x1f );memcpy (this_device->scsi3addr, scsi3addr,8 ); memcpy(this_device->vendor, &inq_buff[8],
@@ -3399,7 +3416,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, sizeof(this_device->model));memset (this_device->device_id,0 ,sizeof (this_device->device_id)); -hpsa_get_device_id (h, scsi3addr, this_device->device_id, +hpsa_get_device_id (h, scsi3addr, this_device->device_id,8 ,sizeof (this_device->device_id)); if (this_device->devtype == TYPE_DISK &&
PATCH 13/21 hpsa: refactor hpsa_figure_bus_target_lun
In reply to Don BraceFrom: Kevin Barnett <[email protected]>
setup for sas transport. Need to set the
bus and target accordingly.
--- drivers/scsi/hpsa.c | 25 ++++++++++++------------- drivers/scsi/hpsa.h | 5 +++++ 2 files changed, 17 insertions(+), 13 deletions(-)
drivers/scsi/hpsa.c +12 -13
@@ -3503,38 +3503,37 @@ static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device)return 0 ; } -/* Helper function to assign bus, target, lun mapping of devices. -* Puts non-external target logical volumes on bus 0, external target logical -* volumes on bus 1, physical devices on bus 2. and the hba on bus 3. +/* +* Helper function to assign bus, target, lun mapping of devices. * Logical drive target and lun are assigned at this time, but * physical device lun and target assignment are deferred (assigned * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.) -*/ +*/ static void figure_bus_target_lun (struct ctlr_info *h,u8 *lunaddrbytes,struct hpsa_scsi_dev_t *device) { -u32 lunid =le32_to_cpu (*((__le32 *) lunaddrbytes)); +u32 lunid =get_unaligned_le32 (lunaddrbytes);if (!is_logical_dev_addr_mode (lunaddrbytes)) {/* physical device, target and lun filled in later */ if (is_hba_lunid (lunaddrbytes)) -hpsa_set_bus_target_lun (device,3 ,0 , lunid &0x3fff ); +hpsa_set_bus_target_lun (device, +HPSA_HBA_BUS ,0 , lunid &0x3fff );else /* defer target, lun assignment for physical devices */ -hpsa_set_bus_target_lun (device,2 ,-1 ,-1 ); +hpsa_set_bus_target_lun (device, +HPSA_PHYSICAL_DEVICE_BUS ,-1 ,-1 );return ; }/* It's a logical device */ if (is_ext_target (h, device)) { -/* external target way, put logicals on bus 1 -* and match target/lun numbers box -* reports, other smart array, bus 0, target 0, match lunid -*/ hpsa_set_bus_target_lun (device, -1 , (lunid >>16 ) &0x3fff , lunid &0x00ff ); +HPSA_EXTERNAL_RAID_VOLUME_BUS , (lunid >>16 ) &0x3fff , + lunid &0x00ff );return ; } -hpsa_set_bus_target_lun (device,0 ,0 , lunid &0x3fff ); +hpsa_set_bus_target_lun (device,HPSA_RAID_VOLUME_BUS , +0 , lunid &0x3fff ); }/*
drivers/scsi/hpsa.h +5 -0
@@ -367,6 +367,11 @@ struct offline_device_entry {#define IOACCEL2_INBOUND_POSTQ_64_LOW 0xd0#define IOACCEL2_INBOUND_POSTQ_64_HI 0xd4 +#define HPSA_PHYSICAL_DEVICE_BUS 0 +#define HPSA_RAID_VOLUME_BUS 1 +#define HPSA_EXTERNAL_RAID_VOLUME_BUS 2 +#define HPSA_HBA_BUS 3 +/* Send the command to the hardware */
PATCH 14/21 hpsa: move scsi_add_device and scsi_remove_device calls to new function
In reply to Don BraceFrom: Kevin Barnett <[email protected]>
preparation for adding the sas transport class
--- drivers/scsi/hpsa.c | 62 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 26 deletions(-)
drivers/scsi/hpsa.c +36 -26
@@ -1646,6 +1646,39 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, } } +static int hpsa_add_device (struct ctlr_info *h,struct hpsa_scsi_dev_t *device) +{ +int rc =0 ; + + rc =scsi_add_device (h->scsi_host, device->bus, + device->target, device->lun); +return rc; +} + +static void hpsa_remove_device (struct ctlr_info *h, +struct hpsa_scsi_dev_t *device) +{ +struct scsi_device *sdev =NULL ; + + sdev =scsi_device_lookup (h->scsi_host, device->bus, + device->target, device->lun); + +if (sdev) { +scsi_remove_device (sdev); +scsi_device_put (sdev); + }else { +/* +* We don't expect to get here. Future commands +* to this device will get a selection timeout as +* if the device were gone. +*/ +dev_warn (&h->pdev->dev, +"didn't find scsi %d:%d:%d:%d for removal." , + h->scsi_host->host_no, device->bus, + device->target, device->lun); + } +} +static void adjust_hpsa_scsi_table (struct ctlr_info *h,int hostno,struct hpsa_scsi_dev_t *sd[],int nsds) {
@@ -1658,7 +1691,6 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,unsigned long flags;struct hpsa_scsi_dev_t **added, **removed;int nadded, nremoved; -struct Scsi_Host *sh =NULL ;if (atomic_read (&h->reset_in_progress)) { h->drv_req_rescan =1 ;
@@ -1772,33 +1804,12 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,if (hostno ==-1 || !changes) goto free_and_out; - sh = h->scsi_host; -if (sh ==NULL ) { -dev_warn (&h->pdev->dev,"%s: scsi_host is null\n" , __func__); -return ; - }/* Notify scsi mid layer of any removed devices */ for (i =0 ; i < nremoved; i++) {if (!removed[i])continue ; -if (removed[i]->expose_device) { -struct scsi_device *sdev = -scsi_device_lookup (sh, removed[i]->bus, - removed[i]->target, removed[i]->lun); -if (sdev !=NULL ) { -scsi_remove_device (sdev); -scsi_device_put (sdev); - }else { -/* -* We don't expect to get here. -* future cmds to this device will get selection -* timeout as if the device was gone. -*/ -hpsa_show_dev_msg (__stringify (KERN_WARNING ), - h, removed[i], -"didn't find device for removal." ); - } - } +if (removed[i]->expose_device) +hpsa_remove_device (h, removed[i]);kfree (removed[i]); removed[i] =NULL ; }
@@ -1809,8 +1820,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,continue ;if (!(added[i]->expose_device))continue ; -if (scsi_add_device (sh, added[i]->bus, - added[i]->target, added[i]->lun) ==0 ) +if (hpsa_add_device (h, added[i]) ==0 )continue ;hpsa_show_dev_msg (__stringify (KERN_WARNING ), h, added[i],"addition failed, device not added." );
PATCH 15/21 External array LUNs must use target and lun numbers assigned by the
In reply to Don BraceFrom: Scott Teel <[email protected]>
external array. So the driver must treat these differently from local LUNs when assigning lun/target.
LUN's 'model' field has been used to detect Lun types that need special treatment, but the desire is to eliminate the need to reference specific array models, and support any external array.
Pass-through RAID (PTRAID) luns are not luns of the local controller, so they are not reported in LUN count of command 'ID controller'. However, they ARE reported in "Report logical Luns" command. Local luns are listed first, then PTRAID LUNs.
The number of luns from "Report LUNs" in excess of those reported by 'ID controller' are therefore the PTRAID LUNS.
We can now remove function is_ext_target, and the 'white list' array of supported model names.
--- drivers/scsi/hpsa.c | 141 ++++++++++++++++++++++++++++++++++++++--------- drivers/scsi/hpsa.h | 1 drivers/scsi/hpsa_cmd.h | 11 ++++ 3 files changed, 127 insertions(+), 26 deletions(-)
drivers/scsi/hpsa.c +115 -26
@@ -274,7 +274,6 @@ 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 is_ext_target (struct ctlr_info *h,struct hpsa_scsi_dev_t *device);static inline struct ctlr_info *sdev_to_hba (struct scsi_device *sdev) {
@@ -775,7 +774,7 @@ static ssize_t path_info_show(struct device *dev, hdev->bus, hdev->target, hdev->lun, scsi_device_type(hdev->devtype)); -if (is_ext_target (h, hdev) || +if (hdev->external || hdev->devtype ==TYPE_RAID ||is_logical_device (hdev)) { output_len += snprintf(path[i] + output_len,
@@ -3016,6 +3015,35 @@ out:return rc; } +static int hpsa_bmic_id_controller (struct ctlr_info *h, +struct bmic_identify_controller *buf,size_t bufsize) +{ +int rc =IO_OK ; +struct CommandList *c; +struct ErrorInfo *ei; + + c =cmd_alloc (h); + + rc =fill_cmd (c,BMIC_IDENTIFY_CONTROLLER , h, buf, bufsize, +0 ,RAID_CTLR_LUNID ,TYPE_CMD ); +if (rc) + goto out; + + rc =hpsa_scsi_do_simple_cmd_with_retry (h, c, +PCI_DMA_FROMDEVICE ,NO_TIMEOUT ); +if (rc) + goto out; + ei = c->err_info; +if (ei->CommandStatus !=0 && ei->CommandStatus !=CMD_DATA_UNDERRUN ) { +hpsa_scsi_interpret_error (h, c); + rc =-1 ; + } +out: +cmd_free (h, c); +return rc; +} + +static int hpsa_bmic_id_physical_device (struct ctlr_info *h,unsigned char scsi3addr[],u16 bmic_device_index,struct bmic_identify_physical_device *buf,size_t bufsize)
@@ -3492,27 +3520,6 @@ static void hpsa_update_device_supports_aborts(struct ctlr_info *h, } } -static unsigned char *ext_target_model[] = { -"MSA2012" , -"MSA2024" , -"MSA2312" , -"MSA2324" , -"P2000 G3 SAS" , -"MSA 2040 SAS" , -NULL , -}; - -static int is_ext_target (struct ctlr_info *h,struct hpsa_scsi_dev_t *device) -{ -int i; - -for (i =0 ; ext_target_model[i]; i++) -if (strncmp (device->model, ext_target_model[i], -strlen (ext_target_model[i])) ==0 ) -return 1 ; -return 0 ; -} -/* * Helper function to assign bus, target, lun mapping of devices. * Logical drive target and lun are assigned at this time, but
@@ -3536,7 +3543,7 @@ static void figure_bus_target_lun(struct ctlr_info *h,return ; }/* It's a logical device */ -if (is_ext_target (h, device)) { +if (device->external) {hpsa_set_bus_target_lun (device,HPSA_EXTERNAL_RAID_VOLUME_BUS , (lunid >>16 ) &0x3fff , lunid &0x00ff );
@@ -3570,7 +3577,7 @@ static int add_ext_target_dev(struct ctlr_info *h,if (!is_logical_dev_addr_mode (lunaddrbytes))return 0 ;/* It's the logical targets that may lack lun 0. */ -if (!is_ext_target (h, tmpdevice)) +if (!tmpdevice->external)return 0 ;/* Only external target devices have this problem. */ if (tmpdevice->lun ==0 )/* if lun is 0, then we have a lun 0. */
@@ -3629,6 +3636,29 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,return 0 ; } +static int figure_external_status (struct ctlr_info *h,int raid_ctlr_position, +int i,int nphysicals,int nlocal_logicals) +{ +/* In report logicals, local logicals are listed first, +* then any externals. +*/ +int logicals_start = nphysicals + (raid_ctlr_position ==0 ); + +if (i == raid_ctlr_position) +return 0 ; + +if (i < logicals_start) +return 0 ; + +/* i is in logicals range, but still within local logicals */ +if ((i - nphysicals - (raid_ctlr_position ==0 )) < nlocal_logicals) +return 0 ; + +return 1 ;/* it's an external lun */ +} + + +/* * Do CISS_REPORT_PHYS and CISS_REPORT_LOG. Data is returned in physdev, * logdev. The number of luns in physdev and logdev are returned in
@@ -3754,6 +3784,32 @@ static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, sizeof(this_device->bay)); } +/* get number of local logical disks. */ +static int hpsa_set_local_logical_count (struct ctlr_info *h, +struct bmic_identify_controller *id_ctlr, +u32 *nlocals) +{ +int rc; + +if (!id_ctlr) { +dev_warn (&h->pdev->dev,"%s: id_ctlr buffer is NULL.\n" , + __func__); +return -ENOMEM ; + } +memset (id_ctlr,0 ,sizeof (*id_ctlr)); + rc =hpsa_bmic_id_controller (h, id_ctlr,sizeof (*id_ctlr)); +if (!rc) +if (id_ctlr->configured_logical_drive_count <256 ) + *nlocals = id_ctlr->configured_logical_drive_count; +else + *nlocals =le16_to_cpu ( + id_ctlr->extended_logical_unit_count); +else + *nlocals =-1 ; +return rc; +} + +static void hpsa_update_scsi_devices (struct ctlr_info *h,int hostno) {/* the idea here is we could get notified
@@ -3769,8 +3825,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)struct ReportExtendedLUNdata *physdev_list =NULL ;struct ReportLUNdata *logdev_list =NULL ;struct bmic_identify_physical_device *id_phys =NULL ; +struct bmic_identify_controller *id_ctlr =NULL ;u32 nphysicals =0 ;u32 nlogicals =0 ; +u32 nlocal_logicals =0 ;u32 ndev_allocated =0 ;struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;int ncurrent =0 ;
@@ -3784,9 +3842,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) logdev_list =kzalloc (sizeof (*logdev_list),GFP_KERNEL ); tmpdevice =kzalloc (sizeof (*tmpdevice),GFP_KERNEL ); id_phys =kzalloc (sizeof (*id_phys),GFP_KERNEL ); + id_ctlr =kzalloc (sizeof (*id_ctlr),GFP_KERNEL );if (!currentsd || !physdev_list || !logdev_list || - !tmpdevice || !id_phys) { + !tmpdevice || !id_phys || !id_ctlr) {dev_err (&h->pdev->dev,"out of memory\n" ); goto out; }
@@ -3800,6 +3859,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) goto out; } +/* Set number of local logicals (non PTRAID) */ +if (hpsa_set_local_logical_count (h, id_ctlr, &nlocal_logicals)) { +dev_warn (&h->pdev->dev, +"%s: Can't determine number of local logical devices.\n" , + __func__); + } +/* We might see up to the maximum number of logical and physical disks * plus external target devices, and a device for the local RAID * controller.
@@ -3864,6 +3930,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)continue ; } +/* Determine if this is a lun from an external target array */ + tmpdevice->external = +figure_external_status (h, raid_ctlr_position, i, + nphysicals, nlocal_logicals); +figure_bus_target_lun (h, lunaddrbytes, tmpdevice);hpsa_update_device_supports_aborts (h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent];
@@ -3947,6 +4018,7 @@ out:kfree (currentsd);kfree (physdev_list);kfree (logdev_list); +kfree (id_ctlr);kfree (id_phys); }
@@ -6399,6 +6471,23 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[7 ] = (size >>16 ) &0xFF ; c->Request.CDB[8 ] = (size >>8 ) &0XFF ;break ; +case BMIC_IDENTIFY_CONTROLLER : + c->Request.CDBLen =10 ; + c->Request.type_attr_dir = +TYPE_ATTR_DIR (cmd_type,ATTR_SIMPLE ,XFER_READ ); + c->Request.Timeout =0 ; + c->Request.CDB[0 ] =BMIC_READ ; + c->Request.CDB[1 ] =0 ; + c->Request.CDB[2 ] =0 ; + c->Request.CDB[3 ] =0 ; + c->Request.CDB[4 ] =0 ; + c->Request.CDB[5 ] =0 ; + c->Request.CDB[6 ] =BMIC_IDENTIFY_CONTROLLER ; + c->Request.CDB[7 ] = (size >>16 ) &0xFF ; + c->Request.CDB[8 ] = (size >>8 ) &0XFF ; + c->Request.CDB[9 ] =0 ; +break ; +default :dev_warn (&h->pdev->dev,"unknown command 0x%c\n" , cmd);BUG ();
drivers/scsi/hpsa.h +1 -0
@@ -77,6 +77,7 @@ struct hpsa_scsi_dev_t {struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES ];int nphysical_disks;int supports_aborts; +int external;/* 1-from external array 0-not <0-unknown */ };struct reply_queue_buffer {
drivers/scsi/hpsa_cmd.h +11 -0
@@ -286,6 +286,7 @@ struct SenseSubsystem_info {#define BMIC_FLASH_FIRMWARE 0xF7#define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64#define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15 +#define BMIC_IDENTIFY_CONTROLLER 0x11/* Command List Structure */ union SCSI3Addr {
@@ -682,6 +683,16 @@ struct hpsa_pci_info {u32 board_id; }; +struct bmic_identify_controller { +u8 configured_logical_drive_count;/* offset 0 */ +u8 pad1[153 ]; +__le16 extended_logical_unit_count;/* offset 154 */ +u8 pad2[136 ]; +u8 controller_mode;/* offset 292 */ +u8 pad3[32 ]; +}; + +struct bmic_identify_physical_device {u8 scsi_bus;/* SCSI Bus number on controller */ u8 scsi_id;/* SCSI ID on this bus */
PATCH 16/21 hpsa: eliminate fake lun0 enclosures
In reply to Don BraceFrom: Scott Teel <[email protected]>
We don't need to create fake enclosure devices at Lun0 in external target array configurations anymore. This was done to support Pre-SCSI rev 5 controllers that didn't suppoprt report luns commands, so the SCSI layer had to scan targets. If there was no LUN at LUN 0, then the target scan would stop, and move to the next target. Lun0 enclosure device was added to prevent sparsely-numbered LUNs from being missed.
--- drivers/scsi/hpsa.c | 68 --------------------------------------------------- 1 file changed, 68 deletions(-)
drivers/scsi/hpsa.c +0 -68
@@ -3553,60 +3553,6 @@ static void figure_bus_target_lun(struct ctlr_info *h, 0, lunid & 0x3fff); } -/* -* If there is no lun 0 on a target, linux won't find any devices. -* For the external targets (arrays), we have to manually detect the enclosure -* which is at lun zero, as CCISS_REPORT_PHYSICAL_LUNS doesn't report -* it for some reason. *tmpdevice is the target we're adding, -* this_device is a pointer into the current element of currentsd[] -* that we're building up in update_scsi_devices(), below. -* lunzerobits is a bitmap that tracks which targets already have a -* lun 0 assigned. -* Returns 1 if an enclosure was added, 0 if not. -*/ -static int add_ext_target_dev (struct ctlr_info *h, -struct hpsa_scsi_dev_t *tmpdevice, -struct hpsa_scsi_dev_t *this_device,u8 *lunaddrbytes, -unsigned long lunzerobits[],int *n_ext_target_devs) -{ -unsigned char scsi3addr[8 ]; - -if (test_bit (tmpdevice->target, lunzerobits)) -return 0 ;/* There is already a lun 0 on this target. */ - -if (!is_logical_dev_addr_mode (lunaddrbytes)) -return 0 ;/* It's the logical targets that may lack lun 0. */ - -if (!tmpdevice->external) -return 0 ;/* Only external target devices have this problem. */ - -if (tmpdevice->lun ==0 )/* if lun is 0, then we have a lun 0. */ -return 0 ; - -memset (scsi3addr,0 ,8 ); - scsi3addr[3 ] = tmpdevice->target; -if (is_hba_lunid (scsi3addr)) -return 0 ;/* Don't add the RAID controller here. */ - -if (is_scsi_rev_5 (h)) -return 0 ;/* p1210m doesn't need to do this. */ - -if (*n_ext_target_devs >=MAX_EXT_TARGETS ) { -dev_warn (&h->pdev->dev,"Maximum number of external " -"target devices exceeded. Check your hardware " -"configuration." ); -return 0 ; - } - -if (hpsa_update_device_info (h, scsi3addr, this_device,NULL )) -return 0 ; - (*n_ext_target_devs)++; -hpsa_set_bus_target_lun (this_device, - tmpdevice->bus, tmpdevice->target,0 ); -hpsa_update_device_supports_aborts (h, this_device, scsi3addr); -set_bit (tmpdevice->target, lunzerobits); -return 1 ; -}/* * Get address of physical disk used for an ioaccel2 mode command:
@@ -3939,20 +3885,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)hpsa_update_device_supports_aborts (h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; -/* -* For external target devices, we have to insert a LUN 0 which -* doesn't show up in CCISS_REPORT_PHYSICAL data, but there -* is nonetheless an enclosure device there. We have to -* present that otherwise linux won't find anything if -* there is no lun 0. -*/ -if (add_ext_target_dev (h, tmpdevice, this_device, - lunaddrbytes, lunzerobits, - &n_ext_target_devs)) { - ncurrent++; - this_device = currentsd[ncurrent]; - } - *this_device = *tmpdevice; this_device->physical_device = physical_device;
PATCH 17/21 hpsa: add discovery polling for PT RAID devices.
In reply to Don BraceFrom: Scott Teel <[email protected]>
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.
--- drivers/scsi/hpsa.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/hpsa.h | 2 + 2 files changed, 72 insertions(+)
drivers/scsi/hpsa.c +70 -0
@@ -274,6 +274,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) {
@@ -1827,6 +1828,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,* since it didn't get added to scsi mid layer */ fixup_botched_add (h, added[i]); +/* reschedule rescans until add succeeds. */ + h->drv_req_rescan =1 ; added[i] =NULL ; }
@@ -3885,6 +3888,18 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)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;
@@ -8013,6 +8028,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;
@@ -8028,6 +8078,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)
@@ -8268,6 +8330,8 @@ reinit_after_soft_reset:/* 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 */
@@ -8275,6 +8339,11 @@ reinit_after_soft_reset: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);
@@ -8359,6 +8428,7 @@ static void hpsa_shutdown(struct pci_dev *pdev)hpsa_flush_cache (h); h->access.set_intr_mask (h,HPSA_INTR_OFF );hpsa_free_irqs (h);/* init_one 4 */ +kfree (h->lastlogicals);hpsa_disable_interrupt_mode (h);/* pci_init 2 */ }
drivers/scsi/hpsa.h +2 -0
@@ -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;
PATCH 18/21 hpsa: disable report lun data caching
In reply to Don BraceFrom: Scott Teel <[email protected]>
When external target arrays are present, disable the firmware's normal behavior of returning a cached copy of the report lun data, and force it to collect new data each time we request a report luns.
This is necessary for external arrays, since there may be no reliable signal from the external array to the smart array when lun configuration changes, and thus when driver requests report luns, it may be stale data.
Use diag options to turn off RPL data caching.
--- drivers/scsi/hpsa.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/hpsa_cmd.h | 3 ++ 2 files changed, 89 insertions(+)
drivers/scsi/hpsa.c +86 -0
@@ -274,6 +274,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 void hpsa_disable_rld_caching (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)
@@ -6369,6 +6370,24 @@ 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_DIAG_OPTIONS : + c->Request.CDBLen =16 ; + c->Request.type_attr_dir = +TYPE_ATTR_DIR (cmd_type,ATTR_SIMPLE ,XFER_READ ); + c->Request.Timeout =0 ; +/* Spec says this should be BMIC_WRITE */ + c->Request.CDB[0 ] =BMIC_READ ; + c->Request.CDB[6 ] =BMIC_SENSE_DIAG_OPTIONS ; +break ; +case BMIC_SET_DIAG_OPTIONS : + c->Request.CDBLen =16 ; + c->Request.type_attr_dir = +TYPE_ATTR_DIR (cmd_type, +ATTR_SIMPLE ,XFER_WRITE ); + c->Request.Timeout =0 ; + c->Request.CDB[0 ] =BMIC_WRITE ; + c->Request.CDB[6 ] =BMIC_SET_DIAG_OPTIONS ; +break ;case HPSA_CACHE_FLUSH : c->Request.CDBLen =12 ; c->Request.type_attr_dir =
@@ -8079,6 +8098,7 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work)hpsa_scan_start (h->scsi_host);scsi_host_put (h->scsi_host); }else if (h->discovery_polling) { +hpsa_disable_rld_caching (h);if (hpsa_luns_changed (h)) {struct Scsi_Host *sh =NULL ;
@@ -8416,6 +8436,72 @@ out:kfree (flush_buf); } +/* Make controller gather fresh report lun data each time we +* send down a report luns request +*/ +static void hpsa_disable_rld_caching (struct ctlr_info *h) +{ +u32 *options; +struct CommandList *c; +int rc; + +/* Don't bother trying to set diag options if locked up */ +if (unlikely (h->lockup_detected)) +return ; + + options =kzalloc (sizeof (*options),GFP_KERNEL ); +if (!options) { +dev_err (&h->pdev->dev, +"Error: failed to disable rld caching, during alloc.\n" ); +return ; + } + + c =cmd_alloc (h); + +/* first, get the current diag options settings */ +if (fill_cmd (c,BMIC_SENSE_DIAG_OPTIONS , h, options,4 ,0 , +RAID_CTLR_LUNID ,TYPE_CMD )) + goto errout; + + rc =hpsa_scsi_do_simple_cmd_with_retry (h, c, +PCI_DMA_FROMDEVICE ,NO_TIMEOUT ); +if ((rc !=0 ) || (c->err_info->CommandStatus !=0 )) + goto errout; + +/* Now, set the bit for disabling the RLD caching */ + *options |=HPSA_DIAG_OPTS_DISABLE_RLD_CACHING ; + +if (fill_cmd (c,BMIC_SET_DIAG_OPTIONS , h, options,4 ,0 , +RAID_CTLR_LUNID ,TYPE_CMD )) + goto errout; + + rc =hpsa_scsi_do_simple_cmd_with_retry (h, c, +PCI_DMA_TODEVICE ,NO_TIMEOUT ); +if ((rc !=0 ) || (c->err_info->CommandStatus !=0 )) + goto errout; + +/* Now verify that it got set: */ +if (fill_cmd (c,BMIC_SENSE_DIAG_OPTIONS , h, options,4 ,0 , +RAID_CTLR_LUNID ,TYPE_CMD )) + goto errout; + + rc =hpsa_scsi_do_simple_cmd_with_retry (h, c, +PCI_DMA_FROMDEVICE ,NO_TIMEOUT ); +if ((rc !=0 ) || (c->err_info->CommandStatus !=0 )) + goto errout; + +if (*options &&HPSA_DIAG_OPTS_DISABLE_RLD_CACHING ) + goto out; +else { +errout: +dev_err (&h->pdev->dev, +"Error: failed to disable report lun data caching.\n" ); + } +out: +cmd_free (h, c); +kfree (options); +} +static void hpsa_shutdown (struct pci_dev *pdev) {struct ctlr_info *h;
drivers/scsi/hpsa_cmd.h +3 -0
@@ -287,6 +287,9 @@ struct SenseSubsystem_info {#define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64#define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15#define BMIC_IDENTIFY_CONTROLLER 0x11 +#define BMIC_SET_DIAG_OPTIONS 0xF4 +#define BMIC_SENSE_DIAG_OPTIONS 0xF5 +#define HPSA_DIAG_OPTS_DISABLE_RLD_CACHING 0x40000000/* Command List Structure */ union SCSI3Addr {
PATCH 19/21 hpsa: enhance device messages
In reply to Don Brace--- drivers/scsi/hpsa.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-)
drivers/scsi/hpsa.c +41 -5
@@ -607,7 +607,7 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[]) }static const char *const raid_label[] = {"0" ,"4" ,"1(+0)" ,"5" ,"5+1" ,"6" , -"1(+0)ADM" ,"UNKNOWN" +"1(+0)ADM" ,"UNKNOWN" ,"PHYS DRV" };#define HPSA_RAID_0 0#define HPSA_RAID_4 1
@@ -616,7 +616,8 @@ static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6",#define HPSA_RAID_51 4#define HPSA_RAID_6 5/* also used for RAID 60 */ #define HPSA_RAID_ADM 6/* also used for RAID 1+0 ADM */ -#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1) +#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 2) +#define PHYSICAL_DRIVE (ARRAY_SIZE(raid_label) - 1)static inline bool is_logical_device (struct hpsa_scsi_dev_t *device) {
@@ -1142,19 +1143,54 @@ static int hpsa_find_target_lun(struct ctlr_info *h,static inline void hpsa_show_dev_msg (const char *level,struct ctlr_info *h,struct hpsa_scsi_dev_t *dev,char *description) { +#define LABEL_SIZE 15 +char label[LABEL_SIZE ]; + +switch (dev->devtype) { +case TYPE_RAID : +snprintf (label,LABEL_SIZE ,"controller" ); +break ; +case TYPE_ENCLOSURE : +snprintf (label,LABEL_SIZE ,"enclosure" ); +break ; +case TYPE_DISK : +if (dev->external) +snprintf (label,LABEL_SIZE ,"external" ); +else if (!is_logical_dev_addr_mode (dev->scsi3addr)) +snprintf (label,LABEL_SIZE ,"%s" , + raid_label[PHYSICAL_DRIVE ]); +else +snprintf (label,LABEL_SIZE ,"RAID-%s" , + dev->raid_level >RAID_UNKNOWN ?"?" : + raid_label[dev->raid_level]); +break ; +case TYPE_ROM : +snprintf (label,LABEL_SIZE ,"rom" ); +break ; +case TYPE_TAPE : +snprintf (label,LABEL_SIZE ,"tape" ); +break ; +case TYPE_MEDIUM_CHANGER : +snprintf (label,LABEL_SIZE ,"changer" ); +break ; +default : +snprintf (label,LABEL_SIZE ,"UNKNOWN" ); +break ; + } + +"scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n" , if (dev == NULL) return;dev_warn (&h->pdev->dev, -"scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n" , +"scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n" , h->scsi_host->host_no, dev->bus, dev->target, dev->lun, description, dev->devtype >=0 ?scsi_device_type (dev->devtype) :"unknown" , dev->vendor, dev->model, - dev->raid_level >RAID_UNKNOWN ? -"RAID-?" : raid_label[dev->raid_level], + label, dev->offload_config ?'+' :'-' , dev->offload_enabled ?'+' :'-' , dev->expose_device);
kbuild test robot
build botRe: [PATCH 19/21] hpsa: enhance device messages
reproduce:
Hi Don,
[auto build test ERROR on scsi/for-next -- if it's inappropriate base, please suggest rules for selecting the more suitable base]
url: https://github.com/0day-ci/linux/commits/Don-Brace/hpsa-updates/20151025-040012 config: x86_64-randconfig-x017-201543 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64
All error/warnings (new ones prefixed by >>):
drivers/scsi/hpsa.c: In function 'hpsa_show_dev_msg':
>> drivers/scsi/hpsa.c:1182:2: error: expected expression before 'if'
if (dev == NULL)
^
>> drivers/scsi/hpsa.c:1181:75: warning: left-hand operand of comma expression has no effect [-Wunused-value]
"scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n",
^vim +/if +1182 drivers/scsi/hpsa.c
4e3d7818 Don Brace 2015-10-24 1175 break; 4e3d7818 Don Brace 2015-10-24 1176 default: 4e3d7818 Don Brace 2015-10-24 1177 snprintf(label, LABEL_SIZE, "UNKNOWN"); 4e3d7818 Don Brace 2015-10-24 1178 break; 4e3d7818 Don Brace 2015-10-24 1179 } 4e3d7818 Don Brace 2015-10-24 1180 4e3d7818 Don Brace 2015-10-24 @1181 "scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n", c59f371e Don Brace 2015-10-24 @1182 if (dev == NULL) c59f371e Don Brace 2015-10-24 1183 return;
c59f371e Don Brace 2015-10-24 1184c59f371e Don Brace 2015-10-24 1185 dev_warn(&h->pdev->dev,
:::::: The code at line 1182 was first introduced by commit
:::::: c59f371efab30f7066af482dc6a1b1cfddd562f0 hpsa: correct calls to dev_printk
:::::: TO: Don Brace <[email protected]>
:::::: CC: 0day robot <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [PATCH 19/21] hpsa: enhance device messages
Quoted 37 lines · kbuild test robot
Hi Don,
[auto build test ERROR on scsi/for-next -- if it's inappropriate base, please suggest rules for selecting the more suitable base]
url: https://github.com/0day-ci/linux/commits/Don-Brace/hpsa-updates/20151025-040012 config: x86_64-randconfig-x017-201543 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64All error/warnings (new ones prefixed by >>):
drivers/scsi/hpsa.c: In function 'hpsa_show_dev_msg':Quoted 1 line
Quoted 1 line
drivers/scsi/hpsa.c:1182:2: error: expected expression before 'if'if (dev == NULL) ^Quoted 1 line
Quoted 1 line
drivers/scsi/hpsa.c:1181:75: warning: left-hand operand of comma expression has no effect [-Wunused-value]"scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n", ^vim +/if +1182
drivers/scsi/hpsa.c4e3d7818 Don Brace 2015-10-24 1175 break; 4e3d7818 Don Brace 2015-10-24 1176 default: 4e3d7818 Don Brace 2015-10-24 1177 snprintf(label, LABEL_SIZE, "UNKNOWN"); 4e3d7818 Don Brace 2015-10-24 1178 break; 4e3d7818 Don Brace 2015-10-24 1179 } 4e3d7818 Don Brace 2015-10-24 1180 4e3d7818 Don Brace 2015-10-24 @1181 "scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n", c59f371e Don Brace 2015-10-24 @1182 if (dev == NULL) c59f371e Don Brace 2015-10-24 1183 return;
c59f371eDon Brace 2015-10-24 1184c59f371eDon Brace 2015-10-24 1185 dev_warn(&h->pdev->dev,:::::: The code at line 1182 was first introduced by commit
::::::c59f371efab30f7066af482dc6a1b1cfddd562f0hpsa: correct calls todev_printk
Quoted 6 lines
:::::: TO: Don Brace <[email protected]>
:::::: CC: 0day robot <[email protected]>---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Wow. I had a merge conflict that kdiff3 auto-resolved. Sorry about that. Anyone else ever have that happen?
I'll send out v1 soon.
Thanks
PATCH 20/21 hpsa: add in sas transport class
In reply to Don BraceFrom: Kevin Barnett <[email protected]>
--- drivers/scsi/hpsa.c | 537 +++++++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/hpsa.h | 27 ++ drivers/scsi/hpsa_cmd.h | 14 + 3 files changed, 554 insertions(+), 24 deletions(-)
drivers/scsi/hpsa.c +513 -24
@@ -41,6 +41,7 @@#include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> #include <scsi/scsi_eh.h> +#include <scsi/scsi_transport_sas.h> #include <scsi/scsi_dbg.h> #include <linux/cciss_ioctl.h> #include <linux/string.h>
@@ -205,6 +206,16 @@ static struct board_type products[] = { {0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; +static struct scsi_transport_template *hpsa_sas_transport_template; +static int hpsa_add_sas_host (struct ctlr_info *h); +static void hpsa_delete_sas_host (struct ctlr_info *h); +static int hpsa_add_sas_device (struct hpsa_sas_node *hpsa_sas_node, +struct hpsa_scsi_dev_t *device); +static void hpsa_remove_sas_device (struct hpsa_scsi_dev_t *device); +static struct hpsa_scsi_dev_t + *hpsa_find_device_by_sas_rphy (struct ctlr_info *h, +struct sas_rphy *rphy); +#define SCSI_CMD_BUSY ((struct scsi_cmnd *)&hpsa_cmd_busy)static const struct scsi_cmnd hpsa_cmd_busy;#define SCSI_CMD_IDLE ((struct scsi_cmnd *)&hpsa_cmd_idle)
@@ -275,6 +286,8 @@ 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 void hpsa_disable_rld_caching (struct ctlr_info *h); +static inline int hpsa_scsi_do_report_phys_luns (struct ctlr_info *h, +struct ReportExtendedLUNdata *buf,int bufsize);static int hpsa_luns_changed (struct ctlr_info *h);static inline struct ctlr_info *sdev_to_hba (struct scsi_device *sdev)
@@ -1687,8 +1700,12 @@ static int hpsa_add_device(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) {int rc =0 ; - rc =scsi_add_device (h->scsi_host, device->bus, +if (is_logical_device (device))/* RAID */ + rc =scsi_add_device (h->scsi_host, device->bus, device->target, device->lun); +else /* HBA */ + rc =hpsa_add_sas_device (h->sas_host, device); +return rc; }
@@ -1697,23 +1714,25 @@ static void hpsa_remove_device(struct ctlr_info *h, {struct scsi_device *sdev =NULL ; - sdev =scsi_device_lookup (h->scsi_host, device->bus, +if (is_logical_device (device)) {/* RAID */ + sdev =scsi_device_lookup (h->scsi_host, device->bus, device->target, device->lun); - -if (sdev) { -scsi_remove_device (sdev); -scsi_device_put (sdev); - }else { -/* -* We don't expect to get here. Future commands -* to this device will get a selection timeout as -* if the device were gone. -*/ -dev_warn (&h->pdev->dev, -"didn't find scsi %d:%d:%d:%d for removal." , - h->scsi_host->host_no, device->bus, - device->target, device->lun); - } +if (sdev) { +scsi_remove_device (sdev); +scsi_device_put (sdev); + }else { +/* +* We don't expect to get here. Future commands +* to this device will get a selection timeout as +* if the device were gone. +*/ +dev_warn (&h->pdev->dev, +"didn't find scsi %d:%d:%d:%d for removal." , + h->scsi_host->host_no, device->bus, + device->target, device->lun); + } + }else /* HBA */ +hpsa_remove_sas_device (device); } static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
@@ -1901,11 +1920,24 @@ static int hpsa_slave_alloc(struct scsi_device *sdev) h =sdev_to_hba (sdev);spin_lock_irqsave (&h->devlock, flags); - sd =lookup_hpsa_scsi_dev (h,sdev_channel (sdev), -sdev_id (sdev), sdev->lun); -if (likely (sd)) { +if (sdev_channel (sdev) ==HPSA_PHYSICAL_DEVICE_BUS ) { +struct scsi_target *starget; +struct sas_rphy *rphy; + + starget =scsi_target (sdev); + rphy =target_to_rphy (starget); + sd =hpsa_find_device_by_sas_rphy (h, rphy); +if (sd) { + sd->target =sdev_id (sdev); + sd->lun = sdev->lun; + } + }else + sd =lookup_hpsa_scsi_dev (h,sdev_channel (sdev), +sdev_id (sdev), sdev->lun); + +if (sd && sd->expose_device) {atomic_set (&sd->ioaccel_cmds_out,0 ); - sdev->hostdata = sd->expose_device ? sd :NULL ; + sdev->hostdata = sd; }else sdev->hostdata =NULL ;spin_unlock_irqrestore (&h->devlock, flags);
@@ -3055,6 +3087,38 @@ out:return rc; } +static int hpsa_bmic_sense_subsystem_information (struct ctlr_info *h, +unsigned char scsi3addr[],u16 bmic_device_index, +struct bmic_sense_subsystem_info *buf,size_t bufsize) +{ +int rc =IO_OK ; +struct CommandList *c; +struct ErrorInfo *ei; + + c =cmd_alloc (h); + + rc =fill_cmd (c,BMIC_SENSE_SUBSYSTEM_INFORMATION , h, buf, bufsize, +0 ,RAID_CTLR_LUNID ,TYPE_CMD ); +if (rc) + goto out; + + c->Request.CDB[2 ] = bmic_device_index &0xff ; + c->Request.CDB[9 ] = (bmic_device_index >>8 ) &0xff ; + + rc =hpsa_scsi_do_simple_cmd_with_retry (h, c, +PCI_DMA_FROMDEVICE ,NO_TIMEOUT ); +if (rc) + goto out; + ei = c->err_info; +if (ei->CommandStatus !=0 && ei->CommandStatus !=CMD_DATA_UNDERRUN ) { +hpsa_scsi_interpret_error (h, c); + rc =-1 ; + } +out: +cmd_free (h, c); +return rc; +} +static int hpsa_bmic_id_controller (struct ctlr_info *h,struct bmic_identify_controller *buf,size_t bufsize) {
@@ -3083,7 +3147,6 @@ out:return rc; } -static int hpsa_bmic_id_physical_device (struct ctlr_info *h,unsigned char scsi3addr[],u16 bmic_device_index,struct bmic_identify_physical_device *buf,size_t bufsize)
@@ -3110,9 +3173,60 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h, } out:cmd_free (h, c); +return rc; } +static u64 hpsa_get_sas_address_from_report_physical (struct ctlr_info *h, +unsigned char *scsi3addr) +{ +struct ReportExtendedLUNdata *physdev; +u32 nphysicals; +u64 sa =0 ; +int i; + + physdev =kzalloc (sizeof (*physdev),GFP_KERNEL ); +if (!physdev) +return 0 ; + +if (hpsa_scsi_do_report_phys_luns (h, physdev,sizeof (*physdev))) { +dev_err (&h->pdev->dev,"report physical LUNs failed.\n" ); +kfree (physdev); +return 0 ; + } + nphysicals =get_unaligned_be32 (physdev->LUNListLength) /24 ; + +for (i =0 ; i < nphysicals; i++) +if (!memcmp (&physdev->LUN[i].lunid[0 ], scsi3addr,8 )) + sa =get_unaligned_be64 (&physdev->LUN[i].wwid[0 ]); + +kfree (physdev); + +return sa; +} + +static void hpsa_get_sas_address (struct ctlr_info *h,unsigned char *scsi3addr, +struct hpsa_scsi_dev_t *dev) +{ +int rc; +u64 sa =0 ; + +if (is_hba_lunid (scsi3addr)) { +struct bmic_sense_subsystem_info ssi; + + rc =hpsa_bmic_sense_subsystem_information (h, + scsi3addr,0 , &ssi,sizeof (ssi)); +if (rc ==0 ) { + sa =get_unaligned_be64 (&ssi.primary_world_wide_id[0 ]); + h->sas_address = sa; + } + }else + sa =hpsa_get_sas_address_from_report_physical (h, scsi3addr); + + dev->sas_address = sa; +} + +/* Get a device id from inquiry page 0x83 */ static int hpsa_vpd_page_supported (struct ctlr_info *h,unsigned char scsi3addr[],u8 page) {
@@ -3949,6 +4063,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)else this_device->expose_device =1 ; + +/* +* Get the SAS address for physical devices that are exposed. +*/ +if (this_device->physical_device && this_device->expose_device) +hpsa_get_sas_address (h, lunaddrbytes, this_device); +switch (this_device->devtype) {case TYPE_ROM :/* We don't *really* support actual CD-ROM devices,
@@ -3994,6 +4115,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)if (ncurrent >=HPSA_MAX_DEVICES )break ; } + +if (h->sas_host ==NULL ) +hpsa_add_sas_host (h); +adjust_hpsa_scsi_table (h, hostno, currentsd, ncurrent); out:kfree (tmpdevice);
@@ -5125,6 +5250,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h) sh->can_queue = h->nr_cmds -HPSA_NRESERVED_CMDS ; sh->cmd_per_lun = sh->can_queue; sh->sg_tablesize = h->maxsgentries; + sh->transportt = hpsa_sas_transport_template; sh->hostdata[0 ] = (unsigned long ) h; sh->irq = h->intr[h->intr_mode]; sh->unique_id = sh->irq;
@@ -6473,6 +6599,16 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[7 ] = (size >>16 ) &0xFF ; c->Request.CDB[8 ] = (size >>8 ) &0XFF ;break ; +case BMIC_SENSE_SUBSYSTEM_INFORMATION : + c->Request.CDBLen =10 ; + c->Request.type_attr_dir = +TYPE_ATTR_DIR (cmd_type,ATTR_SIMPLE ,XFER_READ ); + c->Request.Timeout =0 ; + c->Request.CDB[0 ] =BMIC_READ ; + c->Request.CDB[6 ] =BMIC_SENSE_SUBSYSTEM_INFORMATION ; + c->Request.CDB[7 ] = (size >>16 ) &0xFF ; + c->Request.CDB[8 ] = (size >>8 ) &0XFF ; +break ;case BMIC_IDENTIFY_CONTROLLER : c->Request.CDBLen =10 ; c->Request.type_attr_dir =
@@ -6489,7 +6625,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[8 ] = (size >>8 ) &0XFF ; c->Request.CDB[9 ] =0 ;break ; -default :dev_warn (&h->pdev->dev,"unknown command 0x%c\n" , cmd);BUG ();
@@ -8616,6 +8751,9 @@ static void hpsa_remove_one(struct pci_dev *pdev)free_percpu (h->lockup_detected);/* init_one 2 */ h->lockup_detected =NULL ;/* init_one 2 */ /* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */ + +hpsa_delete_sas_host (h); +kfree (h);/* init_one 1 */ }
@@ -9078,18 +9216,369 @@ static void hpsa_drain_accel_commands(struct ctlr_info *h) }while (1 ); } +static struct hpsa_sas_phy *hpsa_alloc_sas_phy ( +struct hpsa_sas_port *hpsa_sas_port) +{ +struct hpsa_sas_phy *hpsa_sas_phy; +struct sas_phy *phy; + + hpsa_sas_phy =kzalloc (sizeof (*hpsa_sas_phy),GFP_KERNEL ); +if (!hpsa_sas_phy) +return NULL ; + + phy =sas_phy_alloc (hpsa_sas_port->parent_node->parent_dev, + hpsa_sas_port->next_phy_index); +if (!phy) { +kfree (hpsa_sas_phy); +return NULL ; + } + + hpsa_sas_port->next_phy_index++; + hpsa_sas_phy->phy = phy; + hpsa_sas_phy->parent_port = hpsa_sas_port; + +return hpsa_sas_phy; +} + +static void hpsa_free_sas_phy (struct hpsa_sas_phy *hpsa_sas_phy) +{ +struct sas_phy *phy = hpsa_sas_phy->phy; + +sas_port_delete_phy (hpsa_sas_phy->parent_port->port, phy); +sas_phy_free (phy); +if (hpsa_sas_phy->added_to_port) +list_del (&hpsa_sas_phy->phy_list_entry); +kfree (hpsa_sas_phy); +} + +static int hpsa_sas_port_add_phy (struct hpsa_sas_phy *hpsa_sas_phy) +{ +int rc; +struct hpsa_sas_port *hpsa_sas_port; +struct sas_phy *phy; +struct sas_identify *identify; + + hpsa_sas_port = hpsa_sas_phy->parent_port; + phy = hpsa_sas_phy->phy; + + identify = &phy->identify; +memset (identify,0 ,sizeof (*identify)); + identify->sas_address = hpsa_sas_port->sas_address; + identify->device_type =SAS_END_DEVICE ; + identify->initiator_port_protocols =SAS_PROTOCOL_STP ; + identify->target_port_protocols =SAS_PROTOCOL_STP ; + phy->minimum_linkrate_hw =SAS_LINK_RATE_UNKNOWN ; + phy->maximum_linkrate_hw =SAS_LINK_RATE_UNKNOWN ; + phy->minimum_linkrate =SAS_LINK_RATE_UNKNOWN ; + phy->maximum_linkrate =SAS_LINK_RATE_UNKNOWN ; + phy->negotiated_linkrate =SAS_LINK_RATE_UNKNOWN ; + + rc =sas_phy_add (hpsa_sas_phy->phy); +if (rc) +return rc; + +sas_port_add_phy (hpsa_sas_port->port, hpsa_sas_phy->phy); +list_add_tail (&hpsa_sas_phy->phy_list_entry, + &hpsa_sas_port->phy_list_head); + hpsa_sas_phy->added_to_port = true; + +return 0 ; +} + +static int +hpsa_sas_port_add_rphy (struct hpsa_sas_port *hpsa_sas_port, +struct sas_rphy *rphy) +{ +struct sas_identify *identify; + + identify = &rphy->identify; + identify->sas_address = hpsa_sas_port->sas_address; + identify->initiator_port_protocols =SAS_PROTOCOL_STP ; + identify->target_port_protocols =SAS_PROTOCOL_STP ; + +return sas_rphy_add (rphy); +} + +static struct hpsa_sas_port + *hpsa_alloc_sas_port (struct hpsa_sas_node *hpsa_sas_node, +u64 sas_address) +{ +int rc; +struct hpsa_sas_port *hpsa_sas_port; +struct sas_port *port; + + hpsa_sas_port =kzalloc (sizeof (*hpsa_sas_port),GFP_KERNEL ); +if (!hpsa_sas_port) +return NULL ; + +INIT_LIST_HEAD (&hpsa_sas_port->phy_list_head); + hpsa_sas_port->parent_node = hpsa_sas_node; + + port =sas_port_alloc_num (hpsa_sas_node->parent_dev); +if (!port) + goto free_hpsa_port; + + rc =sas_port_add (port); +if (rc) + goto free_sas_port; + + hpsa_sas_port->port = port; + hpsa_sas_port->sas_address = sas_address; +list_add_tail (&hpsa_sas_port->port_list_entry, + &hpsa_sas_node->port_list_head); + +return hpsa_sas_port; + +free_sas_port: +sas_port_free (port); +free_hpsa_port: +kfree (hpsa_sas_port); + +return NULL ; +} + +static void hpsa_free_sas_port (struct hpsa_sas_port *hpsa_sas_port) +{ +struct hpsa_sas_phy *hpsa_sas_phy; +struct hpsa_sas_phy *next; + +list_for_each_entry_safe (hpsa_sas_phy, next, + &hpsa_sas_port->phy_list_head, phy_list_entry) +hpsa_free_sas_phy (hpsa_sas_phy); + +sas_port_delete (hpsa_sas_port->port); +list_del (&hpsa_sas_port->port_list_entry); +kfree (hpsa_sas_port); +} + +static struct hpsa_sas_node *hpsa_alloc_sas_node (struct device *parent_dev) +{ +struct hpsa_sas_node *hpsa_sas_node; + + hpsa_sas_node =kzalloc (sizeof (*hpsa_sas_node),GFP_KERNEL ); +if (hpsa_sas_node) { + hpsa_sas_node->parent_dev = parent_dev; +INIT_LIST_HEAD (&hpsa_sas_node->port_list_head); + } + +return hpsa_sas_node; +} + +static void hpsa_free_sas_node (struct hpsa_sas_node *hpsa_sas_node) +{ +struct hpsa_sas_port *hpsa_sas_port; +struct hpsa_sas_port *next; + +if (!hpsa_sas_node) +return ; + +list_for_each_entry_safe (hpsa_sas_port, next, + &hpsa_sas_node->port_list_head, port_list_entry) +hpsa_free_sas_port (hpsa_sas_port); + +kfree (hpsa_sas_node); +} + +static struct hpsa_scsi_dev_t + *hpsa_find_device_by_sas_rphy (struct ctlr_info *h, +struct sas_rphy *rphy) +{ +int i; +struct hpsa_scsi_dev_t *device; + +for (i =0 ; i < h->ndevices; i++) { + device = h->dev[i]; +if (!device->sas_port) +continue ; +if (device->sas_port->rphy == rphy) +return device; + } + +return NULL ; +} + +static int hpsa_add_sas_host (struct ctlr_info *h) +{ +int rc; +struct device *parent_dev; +struct hpsa_sas_node *hpsa_sas_node; +struct hpsa_sas_port *hpsa_sas_port; +struct hpsa_sas_phy *hpsa_sas_phy; + + parent_dev = &h->scsi_host->shost_gendev; + + hpsa_sas_node =hpsa_alloc_sas_node (parent_dev); +if (!hpsa_sas_node) +return -ENOMEM ; + + hpsa_sas_port =hpsa_alloc_sas_port (hpsa_sas_node, h->sas_address); +if (!hpsa_sas_port) { + rc = -ENODEV ; + goto free_sas_node; + } + + hpsa_sas_phy =hpsa_alloc_sas_phy (hpsa_sas_port); +if (!hpsa_sas_phy) { + rc = -ENODEV ; + goto free_sas_port; + } + + rc =hpsa_sas_port_add_phy (hpsa_sas_phy); +if (rc) + goto free_sas_phy; + + h->sas_host = hpsa_sas_node; + +return 0 ; + +free_sas_phy: +hpsa_free_sas_phy (hpsa_sas_phy); +free_sas_port: +hpsa_free_sas_port (hpsa_sas_port); +free_sas_node: +hpsa_free_sas_node (hpsa_sas_node); + +return rc; +} + +static void hpsa_delete_sas_host (struct ctlr_info *h) +{ +hpsa_free_sas_node (h->sas_host); +} + +static int hpsa_add_sas_device (struct hpsa_sas_node *hpsa_sas_node, +struct hpsa_scsi_dev_t *device) +{ +int rc; +struct hpsa_sas_port *hpsa_sas_port; +struct sas_rphy *rphy; + + hpsa_sas_port =hpsa_alloc_sas_port (hpsa_sas_node, device->sas_address); +if (!hpsa_sas_port) +return -ENOMEM ; + + rphy =sas_end_device_alloc (hpsa_sas_port->port); +if (!rphy) { + rc = -ENODEV ; + goto free_sas_port; + } + + hpsa_sas_port->rphy = rphy; + device->sas_port = hpsa_sas_port; + + rc =hpsa_sas_port_add_rphy (hpsa_sas_port, rphy); +if (rc) + goto free_sas_port; + +return 0 ; + +free_sas_port: +hpsa_free_sas_port (hpsa_sas_port); + device->sas_port =NULL ; + +return rc; +} + +static void hpsa_remove_sas_device (struct hpsa_scsi_dev_t *device) +{ +if (device->sas_port) { +hpsa_free_sas_port (device->sas_port); + device->sas_port =NULL ; + } +} + +static int +hpsa_sas_get_linkerrors (struct sas_phy *phy) +{ +return 0 ; +} + +static int +hpsa_sas_get_enclosure_identifier (struct sas_rphy *rphy,u64 *identifier) +{ +return 0 ; +} + +static int +hpsa_sas_get_bay_identifier (struct sas_rphy *rphy) +{ +return -ENXIO ; +} + +static int +hpsa_sas_phy_reset (struct sas_phy *phy,int hard_reset) +{ +return 0 ; +} + +static int +hpsa_sas_phy_enable (struct sas_phy *phy,int enable) +{ +return 0 ; +} + +static int +hpsa_sas_phy_setup (struct sas_phy *phy) +{ +return 0 ; +} + +static void +hpsa_sas_phy_release (struct sas_phy *phy) +{ +} + +static int +hpsa_sas_phy_speed (struct sas_phy *phy,struct sas_phy_linkrates *rates) +{ +return -EINVAL ; +} + +/* SMP = Serial Management Protocol */ +static int +hpsa_sas_smp_handler (struct Scsi_Host *shost,struct sas_rphy *rphy, +struct request *req) +{ +return -EINVAL ; +} + +static struct sas_function_template hpsa_sas_transport_functions = { + .get_linkerrors = hpsa_sas_get_linkerrors, + .get_enclosure_identifier = hpsa_sas_get_enclosure_identifier, + .get_bay_identifier = hpsa_sas_get_bay_identifier, + .phy_reset = hpsa_sas_phy_reset, + .phy_enable = hpsa_sas_phy_enable, + .phy_setup = hpsa_sas_phy_setup, + .phy_release = hpsa_sas_phy_release, + .set_phy_speed = hpsa_sas_phy_speed, + .smp_handler = hpsa_sas_smp_handler, +}; +/* * This is it. Register the PCI driver information for the cards we control * the OS will call our registered routines when it finds one of our cards. */ static int __init hpsa_init (void ) { -return pci_register_driver (&hpsa_pci_driver); +int rc; + + hpsa_sas_transport_template = +sas_attach_transport (&hpsa_sas_transport_functions); +if (!hpsa_sas_transport_template) +return -ENODEV ; + + rc =pci_register_driver (&hpsa_pci_driver); + +if (rc) +sas_release_transport (hpsa_sas_transport_template); + +return rc; } static void __exit hpsa_cleanup(void) {pci_unregister_driver (&hpsa_pci_driver); +sas_release_transport (hpsa_sas_transport_template); }static void __attribute__((unused))verify_offsets (void )
drivers/scsi/hpsa.h +27 -0
@@ -33,6 +33,29 @@ struct access_method {unsigned long (*command_completed)(struct ctlr_info *h,u8 q); }; +/* for SAS hosts and SAS expanders */ +struct hpsa_sas_node { +struct device *parent_dev; +struct list_head port_list_head; +}; + +struct hpsa_sas_port { +struct list_head port_list_entry; +u64 sas_address; +struct sas_port *port; +int next_phy_index; +struct list_head phy_list_head; +struct hpsa_sas_node *parent_node; +struct sas_rphy *rphy; +}; + +struct hpsa_sas_phy { +struct list_head phy_list_entry; +struct sas_phy *phy; +struct hpsa_sas_port *parent_port; +bool added_to_port; +}; +struct hpsa_scsi_dev_t {int devtype;int bus, target, lun;/* as presented to the OS */
@@ -41,6 +64,7 @@ struct hpsa_scsi_dev_t {u8 expose_device;#define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"unsigned char device_id[16 ];/* from inquiry pg. 0x83 */ +u64 sas_address;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 */
@@ -77,6 +101,7 @@ struct hpsa_scsi_dev_t {struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES ];int nphysical_disks;int supports_aborts; +struct hpsa_sas_port *sas_port;int external;/* 1-from external array 0-not <0-unknown */ };
@@ -134,6 +159,7 @@ struct ctlr_info {char *product_name;struct pci_dev *pdev;u32 board_id; +u64 sas_address;void __iomem *vaddr;unsigned long paddr;int nr_cmds;/* Number of commands allowed on this controller */
@@ -272,6 +298,7 @@ struct ctlr_info {wait_queue_head_t event_sync_wait_queue;struct mutex reset_mutex;atomic_t reset_in_progress; +struct hpsa_sas_node *sas_host; };struct offline_device_entry {
drivers/scsi/hpsa_cmd.h +14 -0
@@ -290,6 +290,7 @@ struct SenseSubsystem_info {#define BMIC_SET_DIAG_OPTIONS 0xF4#define BMIC_SENSE_DIAG_OPTIONS 0xF5#define HPSA_DIAG_OPTS_DISABLE_RLD_CACHING 0x40000000 +#define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66/* Command List Structure */ union SCSI3Addr {
@@ -828,5 +829,18 @@ struct bmic_identify_physical_device { u8 padding[112]; }; +struct bmic_sense_subsystem_info { +u8 primary_slot_number; +u8 reserved[3 ]; +u8 chasis_serial_number[32 ]; +u8 primary_world_wide_id[8 ]; +u8 primary_array_serial_number[32 ];/* NULL terminated */ +u8 primary_cache_serial_number[32 ];/* NULL terminated */ +u8 reserved_2[8 ]; +u8 secondary_array_serial_number[32 ]; +u8 secondary_cache_serial_number[32 ]; +u8 pad[332 ]; +}; +#pragma pack()#endif /* HPSA_CMD_H */
PATCH 21/21 hpsa: bump the driver version
In reply to Don Brace--- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/hpsa.c +1 -1
@@ -56,7 +56,7 @@#include "hpsa.h" /* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */ -#define HPSA_DRIVER_VERSION "3.4.10-0" +#define HPSA_DRIVER_VERSION "3.4.14-0"#define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"#define HPSA "hpsa"