Add support for MCTP transport over the Intel vendor-specific mailbox protocol to enable in-band firmware updates for GPU/AMC via PLDM
Signed-off-by: Badal Nilawar <[email protected]> --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_device.c | 3 + drivers/gpu/drm/xe/xe_device_types.h | 4 + drivers/gpu/drm/xe/xe_mctp_mailbox.c | 186 +++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_mctp_mailbox.h | 14 ++ 5 files changed, 208 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_mctp_mailbox.c create mode 100644 drivers/gpu/drm/xe/xe_mctp_mailbox.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 09661f079d03..d427152bc3fd 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -89,6 +89,7 @@ xe-y += xe_bb.o \ xe_late_bind_fw.o \ xe_lrc.o \ xe_mem_pool.o \ + xe_mctp_mailbox.o \ xe_migrate.o \ xe_mmio.o \ xe_mmio_gem.o \ diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 4b45b617a039..ebf456f580d1 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -49,6 +49,7 @@ #include "xe_i2c.h" #include "xe_irq.h" #include "xe_late_bind_fw.h" +#include "xe_mctp_mailbox.h" #include "xe_mmio.h" #include "xe_module.h" #include "xe_nvm.h" @@ -1065,6 +1066,8 @@ int xe_device_probe(struct xe_device *xe) for_each_gt(gt, xe, id) xe_gt_sanitize_freq(gt); + xe_mctp_mailbox_init(xe); + xe_vsec_init(xe); err = xe_sriov_init_late(xe); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 89437de3001a..9cfe70428c71 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -38,6 +38,7 @@ struct drm_pagemap_shrinker; struct intel_display; struct intel_dg_nvm_dev; +struct xe_mctp_mailbox; struct xe_ggtt; struct xe_i2c; struct xe_pat_ops; @@ -500,6 +501,9 @@ struct xe_device { struct llist_head async_list; } bo_device; + /** @mctp_mailbox: mctp mailbox */ + struct xe_mctp_mailbox *mctp_mailbox; + /** @pmu: performance monitoring unit */ struct xe_pmu pmu; diff --git a/drivers/gpu/drm/xe/xe_mctp_mailbox.c b/drivers/gpu/drm/xe/xe_mctp_mailbox.c new file mode 100644 index 000000000000..f1a81208a9a1 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_mctp_mailbox.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: MIT +/* + * MCTP-over-MAILBOX transport for Xe. + * + * Copyright 2026 Intel Corporation + */ + +#include "xe_device_types.h" + +#include <linux/netdevice.h> +#include <linux/jiffies.h> +#include <linux/workqueue.h> + +#include <net/mctp.h> +#include <net/mctpdevice.h> +#include <net/pkt_sched.h> + +#include <uapi/linux/if_arp.h> + +#include "xe_mctp_mailbox.h" + +#define XE_MCTP_MAILBOX_RX_POLL_MS 100 + +/** @mctp_mailbox: Struct for mctp over mailbox */ +struct xe_mctp_mailbox { + /** @mctp_mailbox.netdev: network device */ + struct net_device *netdev; + /** @running: true while netdev is opened */ + bool running; + /** @work: worker to handle mctp requests from firmware */ + struct delayed_work work; + /** @wq: workqueue to schecdule mctp rx worker */ + struct workqueue_struct *wq; +}; + +/* + * mailbox protocol is interrupt free so for receive path i.e. endpoint to host + * there is no irq available so rx handler need to be polled in worker periodically. + */ +static void mctp_mailbox_rx_handler(struct work_struct *work) +{ + struct xe_mctp_mailbox *mctp_mailbox = + container_of(work, struct xe_mctp_mailbox, work.work); + struct net_device *netdev = mctp_mailbox->netdev; + + if (!netdev) + return; + + dev_hold(netdev); + + /* + * if (mctp_mailbox_rx_ready()) { + * Get data over MAILBOX + * Allocate skb and copy rx data to skb + * Queue skb to upper layer + * netif_rx(skb); + } + */ + dev_put(netdev); + + if (mctp_mailbox->running) + queue_delayed_work(mctp_mailbox->wq, &mctp_mailbox->work, + msecs_to_jiffies(XE_MCTP_MAILBOX_RX_POLL_MS)); +} + +static netdev_tx_t mctp_mailbox_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + /* RFC stub: send skb over MAILBOX */ + dev_dstats_tx_dropped(dev); + kfree_skb(skb); + + return NETDEV_TX_OK; +} + +static int mctp_mailbox_open(struct net_device *dev) +{ + struct xe_mctp_mailbox *mctp_mailbox = netdev_priv(dev); + + mctp_mailbox->running = true; + netif_start_queue(dev); + + queue_delayed_work(mctp_mailbox->wq, &mctp_mailbox->work, 0); + + return 0; +} + +static int mctp_mailbox_stop(struct net_device *dev) +{ + struct xe_mctp_mailbox *mctp_mailbox = netdev_priv(dev); + + mctp_mailbox->running = false; + netif_stop_queue(dev); + + cancel_delayed_work_sync(&mctp_mailbox->work); + flush_workqueue(mctp_mailbox->wq); + + return 0; +} + +static const struct net_device_ops mctp_mailbox_netdev_ops = { + .ndo_start_xmit = mctp_mailbox_start_xmit, + .ndo_open = mctp_mailbox_open, + .ndo_stop = mctp_mailbox_stop, +}; + +static void mctp_mailbox_netdev_setup(struct net_device *dev) +{ + /* Populate netdev structure */ + dev->type = ARPHRD_MCTP; + /* + * dev->mtu = MCTP_MAILBOX_MTU_MIN; + * dev->min_mtu = MCTP_MAILBOX_MTU_MIN; + * dev->max_mtu = MCTP_MAILBOX_MTU_MAX; + * + * dev->hard_header_len = sizeof(struct mctp_mailbox_hdr); + * dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN; + */ + dev->flags = IFF_NOARP; + dev->netdev_ops = &mctp_mailbox_netdev_ops; + dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS; +} + +static void xe_mctp_mailbox_fini(void *arg) +{ + struct xe_device *xe = arg; + struct xe_mctp_mailbox *mctp_mailbox = xe->mctp_mailbox; + struct net_device *netdev; + + if (!mctp_mailbox) + return; + + netdev = mctp_mailbox->netdev; + if (!netdev) { + xe->mctp_mailbox = NULL; + return; + } + + if (mctp_mailbox->wq) { + mctp_mailbox->running = false; + cancel_delayed_work_sync(&mctp_mailbox->work); + destroy_workqueue(mctp_mailbox->wq); + mctp_mailbox->wq = NULL; + } + + xe->mctp_mailbox = NULL; + mctp_unregister_netdev(netdev); + free_netdev(netdev); +} + +int xe_mctp_mailbox_init(struct xe_device *xe) +{ + struct xe_mctp_mailbox *mctp_mailbox; + struct net_device *netdev; + int ret, err; + + netdev = alloc_netdev(sizeof(*mctp_mailbox), "mctp_mailbox%d", NET_NAME_ENUM, + mctp_mailbox_netdev_setup); + if (!netdev) + return -ENOMEM; + + SET_NETDEV_DEV(netdev, xe->drm.dev); + mctp_mailbox = netdev_priv(netdev); + mctp_mailbox->netdev = netdev; + + ret = mctp_register_netdev(netdev, NULL, MCTP_PHYS_BINDING_VENDOR); + if (ret) { + free_netdev(netdev); + return ret; + } + + INIT_DELAYED_WORK(&mctp_mailbox->work, mctp_mailbox_rx_handler); + mctp_mailbox->wq = alloc_ordered_workqueue("mctp-mailbox-ordered-wq", 0); + if (!mctp_mailbox->wq) { + mctp_unregister_netdev(netdev); + free_netdev(netdev); + return -ENOMEM; + } + + xe->mctp_mailbox = mctp_mailbox; + err = devm_add_action_or_reset(xe->drm.dev, xe_mctp_mailbox_fini, xe); + if (err) + return err; + + return 0; +} diff --git a/drivers/gpu/drm/xe/xe_mctp_mailbox.h b/drivers/gpu/drm/xe/xe_mctp_mailbox.h new file mode 100644 index 000000000000..318ae173aaa1 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_mctp_mailbox.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* + * + * Copyright 2026 Intel Corporation + */ + +#ifndef _XE_MCTP_MAILBOX_H_ +#define _XE_MCTP_MAILBOX_H_ + +struct xe_device; + +int xe_mctp_mailbox_init(struct xe_device *xe); + +#endif /* _XE_MCTP_MAILBOX_H_ */ -- 2.54.0
