Message ID | 20250613202941.62114-1-ssiwinski@atto.com |
---|---|
State | New |
Headers | show |
Series | [1/2] scsi: mpi3mr: Add ATTO vendor support and disable firmware download | expand |
On 14-06-2025 01:59, Steve Siwinski wrote: > This patch adds initialization routines for ATTO 24Gb SAS HBAs. > It introduces the ATTO NVRAM structure and functions to validate > NVRAM contents. > > The `mpi3mr_atto_init` function is added to handle ATTO-specific > controller initialization. This involves reading the ATTO SAS address > from Driver Page 2 and then assigning unique device names and WWIDs > to Manufacturing Page 5. > > Signed-off-by: Steve Siwinski <ssiwinski@atto.com> > --- > drivers/scsi/mpi3mr/mpi3mr.h | 35 ++++ > drivers/scsi/mpi3mr/mpi3mr_fw.c | 310 ++++++++++++++++++++++++++++++++ > 2 files changed, 345 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 9bbc7cb98ca3..05583457ffaa 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -1438,6 +1438,35 @@ struct delayed_evt_ack_node { > u32 event_ctx; > }; > > +/* > + * struct ATTO_SAS_NVRAM - ATTO NVRAM settings > + * @signature: ATTO NVRAM signature > + * @version: ATTO NVRAM version > + * @checksum: NVRAM checksum > + * @sasaddr: ATTO SAS address > + */ > +struct ATTO_SAS_NVRAM { > + u8 signature[4]; > + u8 version; > +#define ATTO_SASNVR_VERSION 0 > + > + u8 checksum; > +#define ATTO_SASNVR_CKSUM_SEED 0x5A > + u8 pad[10]; > + u8 sasaddr[8]; > +#define ATTO_SAS_ADDR_ALIGN 64 > + u8 reserved[232]; > +}; > + > +#define ATTO_SAS_ADDR_DEVNAME_BIAS 63 > + > +union ATTO_SAS_ADDRESS { > + u8 b[8]; > + u16 w[4]; > + u32 d[2]; > + u64 q; > +}; > + > int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc); > void mpi3mr_cleanup_resources(struct mpi3mr_ioc *mrioc); > int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc); > @@ -1533,10 +1562,16 @@ int mpi3mr_cfg_get_sas_io_unit_pg1(struct mpi3mr_ioc *mrioc, > struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1, u16 pg_sz); > int mpi3mr_cfg_set_sas_io_unit_pg1(struct mpi3mr_ioc *mrioc, > struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1, u16 pg_sz); > +int mpi3mr_cfg_get_man_pg5(struct mpi3mr_ioc *mrioc, > + struct mpi3_man_page5 *man_pg5, u16 pg_sz); > +int mpi3mr_cfg_set_man_pg5(struct mpi3mr_ioc *mrioc, > + struct mpi3_man_page5 *man_pg5, u16 pg_sz); > int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc, > struct mpi3_driver_page1 *driver_pg1, u16 pg_sz); > int mpi3mr_cfg_get_driver_pg2(struct mpi3mr_ioc *mrioc, > struct mpi3_driver_page2 *driver_pg2, u16 pg_sz, u8 page_type); > +int mpi3mr_cfg_get_page_size(struct mpi3mr_ioc *mrioc, > + int page_type, int page_num); > > u8 mpi3mr_is_expander_device(u16 device_info); > int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle); > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 1d7901a8f0e4..c0177ad3d200 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -4203,6 +4203,163 @@ static int mpi3mr_enable_events(struct mpi3mr_ioc *mrioc) > return retval; > } > > +/** > + * mpi3mr_atto_validate_nvram - validate the ATTO nvram > + * > + * @mrioc: Adapter instance reference remove extra " " afetr : > + * @nvram: ptr to the ATTO nvram structure > + * Return: 0 for success, non-zero for failure. > + */ > +static int mpi3mr_atto_validate_nvram(struct mpi3mr_ioc *mrioc, struct ATTO_SAS_NVRAM *nvram) > +{ > + int r = -EINVAL; > + union ATTO_SAS_ADDRESS *sasaddr; > + u32 len; > + u8 *pb; > + u8 cksum; > + > + /* validate nvram checksum */ > + pb = (u8 *) nvram; > + cksum = ATTO_SASNVR_CKSUM_SEED; > + len = sizeof(struct ATTO_SAS_NVRAM); > + > + while (len--) > + cksum = cksum + pb[len]; > + > + if (cksum) { > + ioc_err(mrioc, "Invalid ATTO NVRAM checksum\n"); > + return r; > + } > + > + sasaddr = (union ATTO_SAS_ADDRESS *) nvram->sasaddr; > + > + if (nvram->signature[0] != 'E' > + || nvram->signature[1] != 'S' > + || nvram->signature[2] != 'A' > + || nvram->signature[3] != 'S') > + ioc_err(mrioc, "Invalid ATTO NVRAM signature\n"); > + else if (nvram->version > ATTO_SASNVR_VERSION) > + ioc_info(mrioc, "Invalid ATTO NVRAM version"); > + else if ((nvram->sasaddr[7] & (ATTO_SAS_ADDR_ALIGN - 1)) > + || sasaddr->b[0] != 0x50 > + || sasaddr->b[1] != 0x01 > + || sasaddr->b[2] != 0x08 > + || (sasaddr->b[3] & 0xF0) != 0x60 > + || ((sasaddr->b[3] & 0x0F) | le32_to_cpu(sasaddr->d[1])) == 0) { > + ioc_err(mrioc, "Invalid ATTO SAS address\n"); > + } else > + r = 0; > + return r; > +} > + > +/** > + * mpi3mr_atto_get_sas_addr - get the ATTO SAS address from driver page 2 > + * > + * @mrioc: Adapter instance reference > + * @*sas_address: return sas address it should be @sas_address: Pointer to store the sas address. > + * Return: 0 for success, non-zero for failure. > + */ > +static int mpi3mr_atto_get_sas_addr(struct mpi3mr_ioc *mrioc, union ATTO_SAS_ADDRESS *sas_address) > +{ > + struct mpi3_driver_page2 *driver_pg2 = NULL; > + struct ATTO_SAS_NVRAM *nvram; > + u16 sz; > + int r; > + __be64 addr; > + > + sz = mpi3mr_cfg_get_page_size(mrioc, MPI3_CONFIG_PAGETYPE_DRIVER, 2); > + driver_pg2 = kzalloc(sz, GFP_KERNEL); > + if (!driver_pg2) > + goto out; > + > + r = mpi3mr_cfg_get_driver_pg2(mrioc, driver_pg2, sz, MPI3_CONFIG_ACTION_READ_PERSISTENT); > + if (r) > + goto out; > + > + nvram = (struct ATTO_SAS_NVRAM *) &driver_pg2->trigger; > + > + r = mpi3mr_atto_validate_nvram(mrioc, nvram); > + if (r) > + goto out; > + > + addr = *((__be64 *) nvram->sasaddr); > + sas_address->q = cpu_to_le64(be64_to_cpu(addr)); > + > +out: > + kfree(driver_pg2); > + return r; > +} > + > +/** > + * mpi3mr_atto_init - Initialize the controller > + * @mrioc: Adapter instance reference > + * > + * This the ATTO controller initialization routine > + * > + * Return: 0 on success and non-zero on failure. > + */ > +static int mpi3mr_atto_init(struct mpi3mr_ioc *mrioc) > +{ > + int i, bias = 0; > + u16 sz; > + struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; > + struct mpi3_man_page5 *man_pg5 = NULL; > + union ATTO_SAS_ADDRESS base_address; > + union ATTO_SAS_ADDRESS dev_address; > + union ATTO_SAS_ADDRESS sas_address; > + > + sz = mpi3mr_cfg_get_page_size(mrioc, MPI3_CONFIG_PAGETYPE_SAS_IO_UNIT, 0); > + sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); > + if (!sas_io_unit_pg0) > + goto out; > + > + if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out; > + } > + > + sz = mpi3mr_cfg_get_page_size(mrioc, MPI3_CONFIG_PAGETYPE_MANUFACTURING, 5); > + man_pg5 = kzalloc(sz, GFP_KERNEL); > + if (!man_pg5) > + goto out; > + > + if (mpi3mr_cfg_get_man_pg5(mrioc, man_pg5, sz)) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out; > + } > + > + mpi3mr_atto_get_sas_addr(mrioc, &base_address); > + > + dev_address.q = base_address.q; > + dev_address.b[0] += ATTO_SAS_ADDR_DEVNAME_BIAS; > + > + for (i = 0; i < man_pg5->num_phys; i++) { > + if (sas_io_unit_pg0->phy_data[i].phy_flags & > + (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | > + MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY)) > + continue; > + > + sas_address.q = base_address.q; > + sas_address.b[0] += bias++; > + > + man_pg5->phy[i].device_name = dev_address.q; > + man_pg5->phy[i].ioc_wwid = sas_address.q; > + man_pg5->phy[i].sata_wwid = sas_address.q; > + } > + > + if (mpi3mr_cfg_set_man_pg5(mrioc, man_pg5, sz)) > + ioc_info(mrioc, "ATTO set manufacuring page 5 failed\n"); typo manufacuring -> manufacturing > + > +out: > + kfree(sas_io_unit_pg0); > + kfree(man_pg5); > + > + return 0; > +} > + > + Thanks Alok
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h index 96401eb7e231..314eb058c12d 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h @@ -206,6 +206,7 @@ struct mpi3_config_page_header { #define MPI3_TEMP_SENSOR_LOCATION_OUTLET (0x2) #define MPI3_TEMP_SENSOR_LOCATION_DRAM (0x3) #define MPI3_MFGPAGE_VENDORID_BROADCOM (0x1000) +#define MPI3_MFGPAGE_VENDORID_ATTO (0x117C) #define MPI3_MFGPAGE_DEVID_SAS4116 (0x00a5) #define MPI3_MFGPAGE_DEVID_SAS5116_MPI (0x00b3) #define MPI3_MFGPAGE_DEVID_SAS5116_NVME (0x00b4) diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index f36663613950..7e2d23204e6c 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -2691,6 +2691,15 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job) goto out; } + if (mrioc->pdev->subsystem_vendor == MPI3_MFGPAGE_VENDORID_ATTO && + mpi_header->function == MPI3_FUNCTION_CI_DOWNLOAD) { + dprint_bsg_err(mrioc, "%s: Firmware download not supported for ATTO HBA.\n", + __func__); + rval = -EPERM; + mutex_unlock(&mrioc->bsg_cmds.mutex); + goto out; + } + if (mpi_header->function == MPI3_BSG_FUNCTION_NVME_ENCAPSULATED) { nvme_fmt = mpi3mr_get_nvme_data_fmt( (struct mpi3_nvme_encapsulated_request *)mpi_req); diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index ce444efd859e..12914400660a 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -5931,6 +5931,10 @@ static const struct pci_device_id mpi3mr_pci_id_table[] = { PCI_DEVICE_SUB(MPI3_MFGPAGE_VENDORID_BROADCOM, MPI3_MFGPAGE_DEVID_SAS5116_MPI_MGMT, PCI_ANY_ID, PCI_ANY_ID) }, + { + PCI_DEVICE_SUB(MPI3_MFGPAGE_VENDORID_ATTO, + MPI3_MFGPAGE_DEVID_SAS4116, PCI_ANY_ID, PCI_ANY_ID) + }, { 0 } }; MODULE_DEVICE_TABLE(pci, mpi3mr_pci_id_table);
Add support for ATTO HBAs by defining the ATTO vendor ID and adding an entry to the PCI device ID table for SAS4116-based ATTO devices. Since ATTO HBAs use specialized firmware, block firmware downloads to ATTO devices via the MPI3_FUNCTION_CI_DOWNLOAD command and return an error. Signed-off-by: Steve Siwinski <ssiwinski@atto.com> --- drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h | 1 + drivers/scsi/mpi3mr/mpi3mr_app.c | 9 +++++++++ drivers/scsi/mpi3mr/mpi3mr_os.c | 4 ++++ 3 files changed, 14 insertions(+)