Commit 00c2cae6 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Martin K. Petersen

scsi: lpfc: Fix lpfc_name struct packing

clang points out that the lpfc_name structure has an 8-byte alignment
requirement on most architectures, but is embedded in a number of other
structures that are forced to be only 1-byte aligned:

drivers/scsi/lpfc/lpfc_hw.h:1516:30: error: field pe within 'struct lpfc_fdmi_reg_port_list' is less aligned than 'struct lpfc_fdmi_port_entry' and is usually due to 'struct lpfc_fdmi_reg_port_list' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]
        struct lpfc_fdmi_port_entry pe;
drivers/scsi/lpfc/lpfc_hw.h:850:19: error: field portName within 'struct _ADISC' is less aligned than 'struct lpfc_name' and is usually due to 'struct _ADISC' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]
drivers/scsi/lpfc/lpfc_hw.h:851:19: error: field nodeName within 'struct _ADISC' is less aligned than 'struct lpfc_name' and is usually due to 'struct _ADISC' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]
drivers/scsi/lpfc/lpfc_hw.h:922:19: error: field portName within 'struct _RNID' is less aligned than 'struct lpfc_name' and is usually due to 'struct _RNID' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]
drivers/scsi/lpfc/lpfc_hw.h:923:19: error: field nodeName within 'struct _RNID' is less aligned than 'struct lpfc_name' and is usually due to 'struct _RNID' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]

From the git history, I can see that all the __packed annotations were done
specifically to avoid introducing implicit padding around the lpfc_name
instances, though this was probably the wrong approach.

To improve this, only annotate the one uint64_t field inside of lpfc_name
as packed, with an explicit 4-byte alignment, as is the default already on
the 32-bit x86 ABI but not on most others. With this, the other __packed
annotations can be removed again, as this avoids the incorrect padding.

Two other structures change their layout as a result of this change:

 - struct _LOGO never gained a __packed annotation even though it has the
   same alignment problem as the others but is not used anywhere in the
   driver today.

 - struct serv_param similarly has this issue, and it is used, my guess is
   that this is only an internal structure rather than part of a binary
   interface, so the padding has no negative effect here.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20230616090705.2623408-1-arnd@kernel.orgReviewed-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent af92c02f
...@@ -365,7 +365,7 @@ struct lpfc_name { ...@@ -365,7 +365,7 @@ struct lpfc_name {
uint8_t IEEE[6]; /* FC IEEE address */ uint8_t IEEE[6]; /* FC IEEE address */
} s; } s;
uint8_t wwn[8]; uint8_t wwn[8];
uint64_t name; uint64_t name __packed __aligned(4);
} u; } u;
}; };
...@@ -850,7 +850,7 @@ typedef struct _ADISC { /* Structure is in Big Endian format */ ...@@ -850,7 +850,7 @@ typedef struct _ADISC { /* Structure is in Big Endian format */
struct lpfc_name portName; struct lpfc_name portName;
struct lpfc_name nodeName; struct lpfc_name nodeName;
uint32_t DID; uint32_t DID;
} __packed ADISC; } ADISC;
typedef struct _FARP { /* Structure is in Big Endian format */ typedef struct _FARP { /* Structure is in Big Endian format */
uint32_t Mflags:8; uint32_t Mflags:8;
...@@ -880,7 +880,7 @@ typedef struct _FAN { /* Structure is in Big Endian format */ ...@@ -880,7 +880,7 @@ typedef struct _FAN { /* Structure is in Big Endian format */
uint32_t Fdid; uint32_t Fdid;
struct lpfc_name FportName; struct lpfc_name FportName;
struct lpfc_name FnodeName; struct lpfc_name FnodeName;
} __packed FAN; } FAN;
typedef struct _SCR { /* Structure is in Big Endian format */ typedef struct _SCR { /* Structure is in Big Endian format */
uint8_t resvd1; uint8_t resvd1;
...@@ -924,7 +924,7 @@ typedef struct _RNID { /* Structure is in Big Endian format */ ...@@ -924,7 +924,7 @@ typedef struct _RNID { /* Structure is in Big Endian format */
union { union {
RNID_TOP_DISC topologyDisc; /* topology disc (0xdf) */ RNID_TOP_DISC topologyDisc; /* topology disc (0xdf) */
} un; } un;
} __packed RNID; } RNID;
struct RLS { /* Structure is in Big Endian format */ struct RLS { /* Structure is in Big Endian format */
uint32_t rls; uint32_t rls;
...@@ -1514,7 +1514,7 @@ struct lpfc_fdmi_hba_ident { ...@@ -1514,7 +1514,7 @@ struct lpfc_fdmi_hba_ident {
struct lpfc_fdmi_reg_port_list { struct lpfc_fdmi_reg_port_list {
__be32 EntryCnt; __be32 EntryCnt;
struct lpfc_fdmi_port_entry pe; struct lpfc_fdmi_port_entry pe;
} __packed; };
/* /*
* Register HBA(RHBA) * Register HBA(RHBA)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment