forked from Minki/linux
mei: revamp mei extension header structure layout.
The mei extension header was build as array of flexible structures which will not work if actually more headers are added. (Currently only vtag header was used). Sparse reports: drivers/misc/mei/hw.h:253:32: warning: array of flexible structures Use basic type u8 for the variable sized extension. Define explicitly mei_ext_hdr_vtag structure. And also fix mei_ext_next() function to point correctly to the end of the header. Note: the headers are part of firmware interface and need to be __packed. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Link: https://lore.kernel.org/r/20210621193756.134027-2-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
09f8c33a4c
commit
4029238364
@ -1726,12 +1726,15 @@ nortpm:
|
||||
return rets;
|
||||
}
|
||||
|
||||
static inline u8 mei_ext_hdr_set_vtag(struct mei_ext_hdr *ext, u8 vtag)
|
||||
static inline u8 mei_ext_hdr_set_vtag(void *ext, u8 vtag)
|
||||
{
|
||||
ext->type = MEI_EXT_HDR_VTAG;
|
||||
ext->ext_payload[0] = vtag;
|
||||
ext->length = mei_data2slots(sizeof(*ext));
|
||||
return ext->length;
|
||||
struct mei_ext_hdr_vtag *vtag_hdr = ext;
|
||||
|
||||
vtag_hdr->hdr.type = MEI_EXT_HDR_VTAG;
|
||||
vtag_hdr->hdr.length = mei_data2slots(sizeof(*vtag_hdr));
|
||||
vtag_hdr->vtag = vtag;
|
||||
vtag_hdr->reserved = 0;
|
||||
return vtag_hdr->hdr.length;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1745,7 +1748,6 @@ static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)
|
||||
{
|
||||
size_t hdr_len;
|
||||
struct mei_ext_meta_hdr *meta;
|
||||
struct mei_ext_hdr *ext;
|
||||
struct mei_msg_hdr *mei_hdr;
|
||||
bool is_ext, is_vtag;
|
||||
|
||||
@ -1764,7 +1766,7 @@ static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)
|
||||
|
||||
hdr_len += sizeof(*meta);
|
||||
if (is_vtag)
|
||||
hdr_len += sizeof(*ext);
|
||||
hdr_len += sizeof(struct mei_ext_hdr_vtag);
|
||||
|
||||
setup_hdr:
|
||||
mei_hdr = kzalloc(hdr_len, GFP_KERNEL);
|
||||
|
@ -235,9 +235,8 @@ enum mei_ext_hdr_type {
|
||||
struct mei_ext_hdr {
|
||||
u8 type;
|
||||
u8 length;
|
||||
u8 ext_payload[2];
|
||||
u8 hdr[];
|
||||
};
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct mei_ext_meta_hdr - extend header meta data
|
||||
@ -250,8 +249,21 @@ struct mei_ext_meta_hdr {
|
||||
u8 count;
|
||||
u8 size;
|
||||
u8 reserved[2];
|
||||
struct mei_ext_hdr hdrs[];
|
||||
};
|
||||
u8 hdrs[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct mei_ext_hdr_vtag - extend header for vtag
|
||||
*
|
||||
* @hdr: standard extend header
|
||||
* @vtag: virtual tag
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct mei_ext_hdr_vtag {
|
||||
struct mei_ext_hdr hdr;
|
||||
u8 vtag;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Extended header iterator functions
|
||||
@ -266,7 +278,7 @@ struct mei_ext_meta_hdr {
|
||||
*/
|
||||
static inline struct mei_ext_hdr *mei_ext_begin(struct mei_ext_meta_hdr *meta)
|
||||
{
|
||||
return meta->hdrs;
|
||||
return (struct mei_ext_hdr *)meta->hdrs;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -295,7 +307,7 @@ static inline bool mei_ext_last(struct mei_ext_meta_hdr *meta,
|
||||
*/
|
||||
static inline struct mei_ext_hdr *mei_ext_next(struct mei_ext_hdr *ext)
|
||||
{
|
||||
return (struct mei_ext_hdr *)(ext->hdr + (ext->length * 4));
|
||||
return (struct mei_ext_hdr *)((u8 *)ext + (ext->length * 4));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,13 +123,13 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
|
||||
|
||||
if (mei_hdr->extended) {
|
||||
struct mei_ext_hdr *ext;
|
||||
struct mei_ext_hdr *vtag = NULL;
|
||||
struct mei_ext_hdr_vtag *vtag_hdr = NULL;
|
||||
|
||||
ext = mei_ext_begin(meta);
|
||||
do {
|
||||
switch (ext->type) {
|
||||
case MEI_EXT_HDR_VTAG:
|
||||
vtag = ext;
|
||||
vtag_hdr = (struct mei_ext_hdr_vtag *)ext;
|
||||
break;
|
||||
case MEI_EXT_HDR_NONE:
|
||||
fallthrough;
|
||||
@ -141,20 +141,20 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
|
||||
ext = mei_ext_next(ext);
|
||||
} while (!mei_ext_last(meta, ext));
|
||||
|
||||
if (!vtag) {
|
||||
if (!vtag_hdr) {
|
||||
cl_dbg(dev, cl, "vtag not found in extended header.\n");
|
||||
cb->status = -EPROTO;
|
||||
goto discard;
|
||||
}
|
||||
|
||||
cl_dbg(dev, cl, "vtag: %d\n", vtag->ext_payload[0]);
|
||||
if (cb->vtag && cb->vtag != vtag->ext_payload[0]) {
|
||||
cl_dbg(dev, cl, "vtag: %d\n", vtag_hdr->vtag);
|
||||
if (cb->vtag && cb->vtag != vtag_hdr->vtag) {
|
||||
cl_err(dev, cl, "mismatched tag: %d != %d\n",
|
||||
cb->vtag, vtag->ext_payload[0]);
|
||||
cb->vtag, vtag_hdr->vtag);
|
||||
cb->status = -EPROTO;
|
||||
goto discard;
|
||||
}
|
||||
cb->vtag = vtag->ext_payload[0];
|
||||
cb->vtag = vtag_hdr->vtag;
|
||||
}
|
||||
|
||||
if (!mei_cl_is_connected(cl)) {
|
||||
@ -331,7 +331,6 @@ int mei_irq_read_handler(struct mei_device *dev,
|
||||
struct mei_ext_meta_hdr *meta_hdr = NULL;
|
||||
struct mei_cl *cl;
|
||||
int ret;
|
||||
u32 ext_meta_hdr_u32;
|
||||
u32 hdr_size_left;
|
||||
u32 hdr_size_ext;
|
||||
int i;
|
||||
@ -367,14 +366,12 @@ int mei_irq_read_handler(struct mei_device *dev,
|
||||
|
||||
if (mei_hdr->extended) {
|
||||
if (!dev->rd_msg_hdr[1]) {
|
||||
ext_meta_hdr_u32 = mei_read_hdr(dev);
|
||||
dev->rd_msg_hdr[1] = ext_meta_hdr_u32;
|
||||
dev->rd_msg_hdr[1] = mei_read_hdr(dev);
|
||||
dev->rd_msg_hdr_count++;
|
||||
(*slots)--;
|
||||
dev_dbg(dev->dev, "extended header is %08x\n",
|
||||
ext_meta_hdr_u32);
|
||||
dev_dbg(dev->dev, "extended header is %08x\n", dev->rd_msg_hdr[1]);
|
||||
}
|
||||
meta_hdr = ((struct mei_ext_meta_hdr *)dev->rd_msg_hdr + 1);
|
||||
meta_hdr = ((struct mei_ext_meta_hdr *)&dev->rd_msg_hdr[1]);
|
||||
if (check_add_overflow((u32)sizeof(*meta_hdr),
|
||||
mei_slots2data(meta_hdr->size),
|
||||
&hdr_size_ext)) {
|
||||
|
Loading…
Reference in New Issue
Block a user