-Wflex-array-member-not-at-end is coming in GCC-14, and we are getting ready to enable it globally.
There is currently a local structure `u` that is using a flexible `struct fw_iso_packet` as header for an on-stack array `u8 header[256]`.
struct { struct fw_iso_packet packet; u8 header[256]; } u;
However, we are deprecating flexible arrays in the middle of another struct. So, in order to avoid this, we use the `struct_group_tagged()` helper to separate the flexible array from the rest of the members in the flexible structure:
struct fw_iso_packet { struct_group_tagged(fw_iso_packet_hdr, hdr, ... the rest of the members ); u32 header[]; /* tx: Top of 1394 isoch. data_block */ };
With the change described above, we can now declare an object of the type of the tagged struct, without embedding the flexible array in the middle of another struct:
struct { struct fw_iso_packet_hdr packet; u8 header[256]; } u;
We also use `container_of()` whenever we need to retrieve a pointer to the flexible structure, through which the flexible-array member can be accessed, as in this case.
So, with these changes, fix the following warning:
drivers/firewire/core-cdev.c: In function ‘ioctl_queue_iso’: drivers/firewire/core-cdev.c:1129:38: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end] 1129 | struct fw_iso_packet packet; | ^~~~~~
Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org --- drivers/firewire/core-cdev.c | 9 +++++---- include/linux/firewire.h | 16 +++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 6274b86eb943..e1f1daa2e667 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1126,9 +1126,11 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) u32 control; int count; struct { - struct fw_iso_packet packet; + struct fw_iso_packet_hdr packet; u8 header[256]; } u; + struct fw_iso_packet *packet = + container_of(&u.packet, struct fw_iso_packet, hdr);
if (ctx == NULL || a->handle != 0) return -EINVAL; @@ -1192,7 +1194,7 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) if (next > end) return -EINVAL; if (copy_from_user - (u.packet.header, p->header, transmit_header_bytes)) + (packet->header, p->header, transmit_header_bytes)) return -EFAULT; if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT && u.packet.header_length + u.packet.payload_length > 0) @@ -1200,8 +1202,7 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) if (payload + u.packet.payload_length > buffer_end) return -EINVAL;
- if (fw_iso_context_queue(ctx, &u.packet, - &client->buffer, payload)) + if (fw_iso_context_queue(ctx, packet, &client->buffer, payload)) break;
p = next; diff --git a/include/linux/firewire.h b/include/linux/firewire.h index dd9f2d765e68..becd3a60d0fb 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -456,13 +456,15 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc); * scatter-gather streaming (e.g. assembling video frame automatically). */ struct fw_iso_packet { - u16 payload_length; /* Length of indirect payload */ - u32 interrupt:1; /* Generate interrupt on this packet */ - u32 skip:1; /* tx: Set to not send packet at all */ - /* rx: Sync bit, wait for matching sy */ - u32 tag:2; /* tx: Tag in packet header */ - u32 sy:4; /* tx: Sy in packet header */ - u32 header_length:8; /* Length of immediate header */ + struct_group_tagged(fw_iso_packet_hdr, hdr, + u16 payload_length; /* Length of indirect payload */ + u32 interrupt:1; /* Generate interrupt on this packet */ + u32 skip:1; /* tx: Set to not send packet at all */ + /* rx: Sync bit, wait for matching sy */ + u32 tag:2; /* tx: Tag in packet header */ + u32 sy:4; /* tx: Sy in packet header */ + u32 header_length:8; /* Length of immediate header */ + ); u32 header[]; /* tx: Top of 1394 isoch. data_block */ };