[PATCH 1/2][next] firewire: Avoid -Wflex-array-member-not-at-end warning

From: Gustavo A. R. Silva
Date: Tue Mar 05 2024 - 12:25:14 EST


-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@xxxxxxxxxx>
---
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 */
};

--
2.34.1