Message ID | 20151104215157.15472.13416.stgit@brunhilda (mailing list archive) |
---|---|
State | Accepted, archived |
Headers | show |
> On Nov 4, 2015, at 3:51 PM, Don Brace <don.brace@pmcs.com> wrote: > > From: Scott Teel <scott.teel@pmcs.com> > > External array LUNs must use target and lun numbers assigned by the > 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. > > Reviewed-by: Scott Teel <scott.teel@pmcs.com> > Reviewed-by: Justin Lindley <justin.lindley@pmcs.com> > Reviewed-by: Kevin Barnett <kevin.barnett@pmcs.com> > Signed-off-by: Don Brace <don.brace@pmcs.com> > --- > drivers/scsi/hpsa.c | 139 ++++++++++++++++++++++++++++++++++++++--------- > drivers/scsi/hpsa.h | 1 > drivers/scsi/hpsa_cmd.h | 11 ++++ > 3 files changed, 125 insertions(+), 26 deletions(-) > > diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c > index 0af4c67..1a67d63 100644 > --- a/drivers/scsi/hpsa.c > +++ b/drivers/scsi/hpsa.c > @@ -275,7 +275,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) > { > @@ -776,7 +775,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, > @@ -3034,6 +3033,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) > @@ -3510,27 +3538,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 > @@ -3554,7 +3561,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); > @@ -3588,7 +3595,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. */ > @@ -3647,6 +3654,27 @@ 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 > @@ -3770,6 +3798,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) > { > /* the idea here is we could get notified > @@ -3785,8 +3839,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) > 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; > @@ -3800,9 +3856,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) > 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; > } > @@ -3816,6 +3873,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) > 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. > @@ -3879,6 +3943,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) > 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]; > @@ -3962,6 +4031,7 @@ out: > kfree(currentsd); > kfree(physdev_list); > kfree(logdev_list); > + kfree(id_ctlr); > kfree(id_phys); > } > > @@ -6414,6 +6484,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; > + For consistency with the other fill_cmd() cases these unnecessary zeroing statements should be removed, either now or at some point in the future. Reviewed-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> > default: > dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd); > BUG(); > diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h > index a4cab12..ffcd4cb 100644 > --- a/drivers/scsi/hpsa.h > +++ b/drivers/scsi/hpsa.h > @@ -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 { > diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h > index c2c0737..c83eaf1 100644 > --- a/drivers/scsi/hpsa_cmd.h > +++ b/drivers/scsi/hpsa_cmd.h > @@ -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 */ > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@vger.kernel.org > 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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 11/05/2015 10:23 AM, Matthew R. Ochs wrote: >> On Nov 4, 2015, at 3:51 PM, Don Brace <don.brace@pmcs.com> wrote: >> >> From: Scott Teel <scott.teel@pmcs.com> >> >> External array LUNs must use target and lun numbers assigned by the >> 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. >> >> Reviewed-by: Scott Teel <scott.teel@pmcs.com> >> Reviewed-by: Justin Lindley <justin.lindley@pmcs.com> >> Reviewed-by: Kevin Barnett <kevin.barnett@pmcs.com> >> Signed-off-by: Don Brace <don.brace@pmcs.com> >> --- >> drivers/scsi/hpsa.c | 139 ++++++++++++++++++++++++++++++++++++++--------- >> drivers/scsi/hpsa.h | 1 >> drivers/scsi/hpsa_cmd.h | 11 ++++ >> 3 files changed, 125 insertions(+), 26 deletions(-) >> >> diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c >> index 0af4c67..1a67d63 100644 >> --- a/drivers/scsi/hpsa.c >> +++ b/drivers/scsi/hpsa.c >> @@ -275,7 +275,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); >> >> >> } >> >> @@ -6414,6 +6484,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; >> + > For consistency with the other fill_cmd() cases these unnecessary zeroing statements > should be removed, either now or at some point in the future. > > Reviewed-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Thanks, unless I have to send up a V3, I'll add this to my next patch set. It does look cleaner with them removed. > >> default: >> dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd); >> BUG(); >> diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h >> index a4cab12..ffcd4cb 100644 >> --- a/drivers/scsi/hpsa.h >> +++ b/drivers/scsi/hpsa.h >> @@ -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 { >> diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h >> index c2c0737..c83eaf1 100644 >> --- a/drivers/scsi/hpsa_cmd.h >> +++ b/drivers/scsi/hpsa_cmd.h >> @@ -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 */ >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in >> the body of a message to majordomo@vger.kernel.org >> 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 majordomo@vger.kernel.org > 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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0af4c67..1a67d63 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -275,7 +275,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) { @@ -776,7 +775,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, @@ -3034,6 +3033,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) @@ -3510,27 +3538,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 @@ -3554,7 +3561,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); @@ -3588,7 +3595,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. */ @@ -3647,6 +3654,27 @@ 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 @@ -3770,6 +3798,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) { /* the idea here is we could get notified @@ -3785,8 +3839,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 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; @@ -3800,9 +3856,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 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; } @@ -3816,6 +3873,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 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. @@ -3879,6 +3943,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 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]; @@ -3962,6 +4031,7 @@ out: kfree(currentsd); kfree(physdev_list); kfree(logdev_list); + kfree(id_ctlr); kfree(id_phys); } @@ -6414,6 +6484,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(); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index a4cab12..ffcd4cb 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -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 { diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index c2c0737..c83eaf1 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -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 */