diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 76b8b7eed0c0..617802855233 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -1634,7 +1634,10 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) ssize_t vpd_size; char vpd_data[CXLFLASH_VPD_LEN]; char tmp_buf[WWPN_BUF_LEN] = { 0 }; - char *wwpn_vpd_tags[MAX_FC_PORTS] = { "V5", "V6", "V7", "V8" }; + const struct dev_dependent_vals *ddv = (struct dev_dependent_vals *) + cfg->dev_id->driver_data; + const bool wwpn_vpd_required = ddv->flags & CXLFLASH_WWPN_VPD_REQUIRED; + const char *wwpn_vpd_tags[MAX_FC_PORTS] = { "V5", "V6", "V7", "V8" }; /* Get the VPD data from the device */ vpd_size = cxl_read_adapter_vpd(pdev, vpd_data, sizeof(vpd_data)); @@ -1671,17 +1674,24 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) * value. Note that we must copy to a temporary buffer * because the conversion service requires that the ASCII * string be terminated. + * + * Allow for WWPN not being found for all devices, setting + * the returned WWPN to zero when not found. Notify with a + * log error for cards that should have had WWPN keywords + * in the VPD - cards requiring WWPN will not have their + * ports programmed and operate in an undefined state. */ for (k = 0; k < cfg->num_fc_ports; k++) { j = ro_size; i = ro_start + PCI_VPD_LRDT_TAG_SIZE; i = pci_vpd_find_info_keyword(vpd_data, i, j, wwpn_vpd_tags[k]); - if (unlikely(i < 0)) { - dev_err(dev, "%s: Port %d WWPN not found in VPD\n", - __func__, k); - rc = -ENODEV; - goto out; + if (i < 0) { + if (wwpn_vpd_required) + dev_err(dev, "%s: Port %d WWPN not found\n", + __func__, k); + wwpn[k] = 0ULL; + continue; } j = pci_vpd_info_field_size(&vpd_data[i]); @@ -3145,7 +3155,7 @@ static struct scsi_host_template driver_template = { * Device dependent values */ static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS, - 0ULL }; + CXLFLASH_WWPN_VPD_REQUIRED }; static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS, CXLFLASH_NOTIFY_SHUTDOWN }; static struct dev_dependent_vals dev_briard_vals = { CXLFLASH_MAX_SECTORS, diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h index 880e348ed5c9..ba0108a7a9c2 100644 --- a/drivers/scsi/cxlflash/main.h +++ b/drivers/scsi/cxlflash/main.h @@ -95,7 +95,8 @@ enum undo_level { struct dev_dependent_vals { u64 max_sectors; u64 flags; -#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL +#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL +#define CXLFLASH_WWPN_VPD_REQUIRED 0x0000000000000002ULL }; struct asyc_intr_info {