[Intel-gfx] [PATCH v4 01/15] mei: add support to GSC extended header
Greg Kroah-Hartman
gregkh at linuxfoundation.org
Fri Sep 9 06:11:35 UTC 2022
On Thu, Sep 08, 2022 at 05:15:58PM -0700, Daniele Ceraolo Spurio wrote:
> From: Tomas Winkler <tomas.winkler at intel.com>
>
> GSC extend header is of variable size and data
> is provided in a sgl list inside the header
> and not in the data buffers, need to enable the path.
>
> V2:
> 1. Add missing kdoc for mei_cl_cb
> 2. In mei_me_hbuf_write()
> use dev_err() when validationg parameters instead of WARN_ON()
This stuff goes below the --- line, as the documentation states, right?
Why is it here?
>
> Signed-off-by: Tomas Winkler <tomas.winkler at intel.com>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> Cc: Vitaly Lubart <vitaly.lubart at intel.com>
> Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
> ---
> drivers/misc/mei/client.c | 55 ++++++++++++++++++++++++----------
> drivers/misc/mei/hbm.c | 13 ++++++++
> drivers/misc/mei/hw-me.c | 7 ++++-
> drivers/misc/mei/hw.h | 57 ++++++++++++++++++++++++++++++++++++
> drivers/misc/mei/interrupt.c | 47 ++++++++++++++++++++++++-----
> drivers/misc/mei/mei_dev.h | 4 +++
> 6 files changed, 160 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
> index 0b2fbe1335a7..6c8b71ae32c8 100644
> --- a/drivers/misc/mei/client.c
> +++ b/drivers/misc/mei/client.c
> @@ -322,6 +322,7 @@ void mei_io_cb_free(struct mei_cl_cb *cb)
>
> list_del(&cb->list);
> kfree(cb->buf.data);
> + kfree(cb->ext_hdr);
> kfree(cb);
> }
>
> @@ -401,6 +402,7 @@ static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,
> cb->buf_idx = 0;
> cb->fop_type = type;
> cb->vtag = 0;
> + cb->ext_hdr = NULL;
>
> return cb;
> }
> @@ -1740,6 +1742,17 @@ static inline u8 mei_ext_hdr_set_vtag(void *ext, u8 vtag)
> return vtag_hdr->hdr.length;
> }
>
> +static inline bool mei_ext_hdr_is_gsc(struct mei_ext_hdr *ext)
> +{
> + return ext && ext->type == MEI_EXT_HDR_GSC;
> +}
> +
> +static inline u8 mei_ext_hdr_set_gsc(struct mei_ext_hdr *ext, struct mei_ext_hdr *gsc_hdr)
> +{
> + memcpy(ext, gsc_hdr, mei_ext_hdr_len(gsc_hdr));
> + return ext->length;
> +}
> +
> /**
> * mei_msg_hdr_init - allocate and initialize mei message header
> *
> @@ -1752,14 +1765,17 @@ 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_msg_hdr *mei_hdr;
> - bool is_ext, is_vtag;
> + bool is_ext, is_hbm, is_gsc, is_vtag;
> + struct mei_ext_hdr *next_ext;
>
> if (!cb)
> return ERR_PTR(-EINVAL);
>
> /* Extended header for vtag is attached only on the first fragment */
> is_vtag = (cb->vtag && cb->buf_idx == 0);
> - is_ext = is_vtag;
> + is_hbm = cb->cl->me_cl->client_id == 0;
> + is_gsc = ((!is_hbm) && cb->cl->dev->hbm_f_gsc_supported && mei_ext_hdr_is_gsc(cb->ext_hdr));
> + is_ext = is_vtag || is_gsc;
>
> /* Compute extended header size */
> hdr_len = sizeof(*mei_hdr);
> @@ -1771,6 +1787,9 @@ static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)
> if (is_vtag)
> hdr_len += sizeof(struct mei_ext_hdr_vtag);
>
> + if (is_gsc)
> + hdr_len += mei_ext_hdr_len(cb->ext_hdr);
> +
> setup_hdr:
> mei_hdr = kzalloc(hdr_len, GFP_KERNEL);
> if (!mei_hdr)
> @@ -1785,10 +1804,20 @@ static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)
> goto out;
>
> meta = (struct mei_ext_meta_hdr *)mei_hdr->extension;
> + meta->size = 0;
> + next_ext = (struct mei_ext_hdr *)meta->hdrs;
> if (is_vtag) {
> meta->count++;
> - meta->size += mei_ext_hdr_set_vtag(meta->hdrs, cb->vtag);
> + meta->size += mei_ext_hdr_set_vtag(next_ext, cb->vtag);
> + next_ext = mei_ext_next(next_ext);
> + }
> +
> + if (is_gsc) {
> + meta->count++;
> + meta->size += mei_ext_hdr_set_gsc(next_ext, cb->ext_hdr);
> + next_ext = mei_ext_next(next_ext);
> }
> +
> out:
> mei_hdr->length = hdr_len - sizeof(*mei_hdr);
> return mei_hdr;
> @@ -1812,14 +1841,14 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
> struct mei_msg_hdr *mei_hdr = NULL;
> size_t hdr_len;
> size_t hbuf_len, dr_len;
> - size_t buf_len;
> + size_t buf_len = 0;
> size_t data_len;
> int hbuf_slots;
> u32 dr_slots;
> u32 dma_len;
> int rets;
> bool first_chunk;
> - const void *data;
> + const void *data = NULL;
>
> if (WARN_ON(!cl || !cl->dev))
> return -ENODEV;
> @@ -1839,8 +1868,10 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
> return 0;
> }
>
> - buf_len = buf->size - cb->buf_idx;
> - data = buf->data + cb->buf_idx;
> + if (buf->data) {
> + buf_len = buf->size - cb->buf_idx;
> + data = buf->data + cb->buf_idx;
> + }
> hbuf_slots = mei_hbuf_empty_slots(dev);
> if (hbuf_slots < 0) {
> rets = -EOVERFLOW;
> @@ -1858,9 +1889,6 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
> goto err;
> }
>
> - cl_dbg(dev, cl, "Extended Header %d vtag = %d\n",
> - mei_hdr->extended, cb->vtag);
> -
> hdr_len = sizeof(*mei_hdr) + mei_hdr->length;
>
> /**
> @@ -1889,7 +1917,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
> }
> mei_hdr->length += data_len;
>
> - if (mei_hdr->dma_ring)
> + if (mei_hdr->dma_ring && buf->data)
> mei_dma_ring_write(dev, buf->data + cb->buf_idx, buf_len);
> rets = mei_write_message(dev, mei_hdr, hdr_len, data, data_len);
>
> @@ -1983,9 +2011,6 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
> goto err;
> }
>
> - cl_dbg(dev, cl, "Extended Header %d vtag = %d\n",
> - mei_hdr->extended, cb->vtag);
> -
> hdr_len = sizeof(*mei_hdr) + mei_hdr->length;
>
> if (rets == 0) {
> @@ -2030,7 +2055,7 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
>
> mei_hdr->length += data_len;
>
> - if (mei_hdr->dma_ring)
> + if (mei_hdr->dma_ring && buf->data)
> mei_dma_ring_write(dev, buf->data, buf_len);
> rets = mei_write_message(dev, mei_hdr, hdr_len, data, data_len);
>
> diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
> index de712cbf5d07..12a62a911e42 100644
> --- a/drivers/misc/mei/hbm.c
> +++ b/drivers/misc/mei/hbm.c
> @@ -340,9 +340,13 @@ static int mei_hbm_capabilities_req(struct mei_device *dev)
> req.hbm_cmd = MEI_HBM_CAPABILITIES_REQ_CMD;
> if (dev->hbm_f_vt_supported)
> req.capability_requested[0] |= HBM_CAP_VT;
> +
> if (dev->hbm_f_cd_supported)
> req.capability_requested[0] |= HBM_CAP_CD;
>
> + if (dev->hbm_f_gsc_supported)
> + req.capability_requested[0] |= HBM_CAP_GSC;
> +
> ret = mei_hbm_write_message(dev, &mei_hdr, &req);
> if (ret) {
> dev_err(dev->dev,
> @@ -1200,6 +1204,12 @@ static void mei_hbm_config_features(struct mei_device *dev)
> dev->version.minor_version >= HBM_MINOR_VERSION_VT))
> dev->hbm_f_vt_supported = 1;
>
> + /* GSC support */
> + if (dev->version.major_version > HBM_MAJOR_VERSION_GSC ||
> + (dev->version.major_version == HBM_MAJOR_VERSION_GSC &&
> + dev->version.minor_version >= HBM_MINOR_VERSION_GSC))
> + dev->hbm_f_gsc_supported = 1;
> +
> /* Capability message Support */
> dev->hbm_f_cap_supported = 0;
> if (dev->version.major_version > HBM_MAJOR_VERSION_CAP ||
> @@ -1367,6 +1377,9 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
> if (!(capability_res->capability_granted[0] & HBM_CAP_CD))
> dev->hbm_f_cd_supported = 0;
>
> + if (!(capability_res->capability_granted[0] & HBM_CAP_GSC))
> + dev->hbm_f_gsc_supported = 0;
> +
> if (dev->hbm_f_dr_supported) {
> if (mei_dmam_ring_alloc(dev))
> dev_info(dev->dev, "running w/o dma ring\n");
> diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
> index 9e2f781c6ed5..da4ef0b51954 100644
> --- a/drivers/misc/mei/hw-me.c
> +++ b/drivers/misc/mei/hw-me.c
> @@ -590,9 +590,14 @@ static int mei_me_hbuf_write(struct mei_device *dev,
> u32 dw_cnt;
> int empty_slots;
>
> - if (WARN_ON(!hdr || !data || hdr_len & 0x3))
> + if (WARN_ON(!hdr || hdr_len & 0x3))
> return -EINVAL;
Again, please remove the WARN_ON(), don't add to it.
>
> + if (!data && data_len) {
> + dev_err(dev->dev, "wrong parameters null data with data_len = %zu\n", data_len);
> + return -EINVAL;
> + }
> +
> dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM((struct mei_msg_hdr *)hdr));
>
> empty_slots = mei_hbuf_empty_slots(dev);
> diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
> index e7e020dba6b1..14f89d96216b 100644
> --- a/drivers/misc/mei/hw.h
> +++ b/drivers/misc/mei/hw.h
> @@ -92,6 +92,12 @@
> #define HBM_MINOR_VERSION_VT 2
> #define HBM_MAJOR_VERSION_VT 2
>
> +/*
> + * MEI version with GSC support
> + */
> +#define HBM_MINOR_VERSION_GSC 2
> +#define HBM_MAJOR_VERSION_GSC 2
> +
> /*
> * MEI version with capabilities message support
> */
> @@ -229,10 +235,12 @@ enum mei_cl_disconnect_status {
> *
> * @MEI_EXT_HDR_NONE: sentinel
> * @MEI_EXT_HDR_VTAG: vtag header
> + * @MEI_EXT_HDR_GSC: gsc header
> */
> enum mei_ext_hdr_type {
> MEI_EXT_HDR_NONE = 0,
> MEI_EXT_HDR_VTAG = 1,
> + MEI_EXT_HDR_GSC = 2,
> };
>
> /**
> @@ -305,6 +313,39 @@ static inline bool mei_ext_last(struct mei_ext_meta_hdr *meta,
> return (u8 *)ext >= (u8 *)meta + sizeof(*meta) + (meta->size * 4);
> }
>
> +struct mei_gsc_sgl {
> + u32 low;
> + u32 high;
> + u32 length;
> +} __packed;
> +
> +#define GSC_HECI_MSG_KERNEL 0
> +#define GSC_HECI_MSG_USER 1
> +
> +#define GSC_ADDRESS_TYPE_GTT 0
> +#define GSC_ADDRESS_TYPE_PPGTT 1
> +#define GSC_ADDRESS_TYPE_PHYSICAL_CONTINUOUS 2 /* max of 64K */
> +#define GSC_ADDRESS_TYPE_PHYSICAL_SGL 3
> +
> +struct mei_ext_hdr_gsc_h2f {
> + struct mei_ext_hdr hdr;
> + u8 client_id;
> + u8 addr_type;
> + u32 fence_id;
> + u8 input_address_count;
> + u8 output_address_count;
> + u8 reserved[2];
> + struct mei_gsc_sgl sgl[];
> +} __packed;
Why is this structure here if you do not use it?
And that's some really odd alignment of the fields, is this coming from
the hardware?
> +
> +struct mei_ext_hdr_gsc_f2h {
> + struct mei_ext_hdr hdr;
> + u8 client_id;
> + u8 reserved;
> + u32 fence_id;
> + u32 written;
> +} __packed;
> +
> /**
> * mei_ext_next - following extended header on the TLV list
> *
> @@ -320,6 +361,18 @@ static inline struct mei_ext_hdr *mei_ext_next(struct mei_ext_hdr *ext)
> return (struct mei_ext_hdr *)((u8 *)ext + (ext->length * 4));
> }
>
> +/**
> + * mei_ext_hdr_len - get ext header length in bytes
> + *
> + * @ext: extend header
> + *
> + * Return: extend header length in bytes
> + */
> +static inline u32 mei_ext_hdr_len(struct mei_ext_hdr *ext)
> +{
> + return (ext) ? ext->length * sizeof(u32) : 0;
Odd spacing :(
And please just spell out ? : statements with a real if () statement.
There is no difference from the generated code and you write code for
people first, compilers second.
And how can ext be NULL here?
thanks,
greg k-h
More information about the Intel-gfx
mailing list