|
27 | 27 | #include <linux/delay.h> |
28 | 28 | #include <linux/slab.h> |
29 | 29 | #include <linux/lockdep.h> |
| 30 | +#include <linux/dmi.h> |
| 31 | +#include <linux/of.h> |
30 | 32 |
|
31 | 33 | #include <scsi/scsi.h> |
32 | 34 | #include <scsi/scsi_cmnd.h> |
@@ -8446,6 +8448,70 @@ lpfc_set_host_tm(struct lpfc_hba *phba) |
8446 | 8448 | return rc; |
8447 | 8449 | } |
8448 | 8450 |
|
| 8451 | +/** |
| 8452 | + * lpfc_get_platform_uuid - Attempts to extract a platform uuid |
| 8453 | + * @phba: pointer to lpfc hba data structure. |
| 8454 | + * |
| 8455 | + * This routine attempts to first read SMBIOS DMI data for the System |
| 8456 | + * Information structure offset 08h called System UUID. Else, no platform |
| 8457 | + * UUID will be advertised. |
| 8458 | + **/ |
| 8459 | +static void |
| 8460 | +lpfc_get_platform_uuid(struct lpfc_hba *phba) |
| 8461 | +{ |
| 8462 | + int rc; |
| 8463 | + const char *uuid; |
| 8464 | + char pni[17] = {0}; /* 16 characters + '\0' */ |
| 8465 | + bool is_ff = true, is_00 = true; |
| 8466 | + u8 i; |
| 8467 | + |
| 8468 | + /* First attempt SMBIOS DMI */ |
| 8469 | + uuid = dmi_get_system_info(DMI_PRODUCT_UUID); |
| 8470 | + if (uuid) { |
| 8471 | + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 8472 | + "2088 SMBIOS UUID %s\n", |
| 8473 | + uuid); |
| 8474 | + } else { |
| 8475 | + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 8476 | + "2099 Could not extract UUID\n"); |
| 8477 | + } |
| 8478 | + |
| 8479 | + if (uuid && uuid_is_valid(uuid)) { |
| 8480 | + /* Generate PNI from UUID format. |
| 8481 | + * |
| 8482 | + * 1.) Extract lower 64 bits from UUID format. |
| 8483 | + * 2.) Set 3h for NAA Locally Assigned Name Identifier format. |
| 8484 | + * |
| 8485 | + * e.g. xxxxxxxx-xxxx-xxxx-yyyy-yyyyyyyyyyyy |
| 8486 | + * |
| 8487 | + * extract the yyyy-yyyyyyyyyyyy portion |
| 8488 | + * final PNI 3yyyyyyyyyyyyyyy |
| 8489 | + */ |
| 8490 | + scnprintf(pni, sizeof(pni), "3%c%c%c%s", |
| 8491 | + uuid[20], uuid[21], uuid[22], &uuid[24]); |
| 8492 | + |
| 8493 | + /* Sanitize the converted PNI */ |
| 8494 | + for (i = 1; i < 16 && (is_ff || is_00); i++) { |
| 8495 | + if (pni[i] != '0') |
| 8496 | + is_00 = false; |
| 8497 | + if (pni[i] != 'f' && pni[i] != 'F') |
| 8498 | + is_ff = false; |
| 8499 | + } |
| 8500 | + |
| 8501 | + /* Convert from char* to unsigned long */ |
| 8502 | + rc = kstrtoul(pni, 16, &phba->pni); |
| 8503 | + if (!rc && !is_ff && !is_00) { |
| 8504 | + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 8505 | + "2100 PNI 0x%016lx\n", phba->pni); |
| 8506 | + } else { |
| 8507 | + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 8508 | + "2101 PNI %s generation status %d\n", |
| 8509 | + pni, rc); |
| 8510 | + phba->pni = 0; |
| 8511 | + } |
| 8512 | + } |
| 8513 | +} |
| 8514 | + |
8449 | 8515 | /** |
8450 | 8516 | * lpfc_sli4_hba_setup - SLI4 device initialization PCI function |
8451 | 8517 | * @phba: Pointer to HBA context object. |
@@ -8529,6 +8595,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) |
8529 | 8595 | clear_bit(HBA_FCOE_MODE, &phba->hba_flag); |
8530 | 8596 | } |
8531 | 8597 |
|
| 8598 | + /* Obtain platform UUID, only for SLI4 FC adapters */ |
| 8599 | + if (!test_bit(HBA_FCOE_MODE, &phba->hba_flag)) |
| 8600 | + lpfc_get_platform_uuid(phba); |
| 8601 | + |
8532 | 8602 | if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) == |
8533 | 8603 | LPFC_DCBX_CEE_MODE) |
8534 | 8604 | set_bit(HBA_FIP_SUPPORT, &phba->hba_flag); |
|
0 commit comments