/* SPDX-License-Identifier: GPL-2.0 */ /* * mctp-usb.h - MCTP USB transport binding: common definitions, * based on DMTF0283 specification: * https://www.dmtf.org/sites/default/files/standards/documents/DSP0283_1.1.0.pdf * * These are protocol-level definitions, that may be shared between host * and gadget drivers. * * Copyright (C) 2024-2025 Code Construct Pty Ltd */ #ifndef __LINUX_USB_MCTP_USB_H #define __LINUX_USB_MCTP_USB_H #include #include #include /* * MCTP-over-USB transport header. DSP0283 v1.0 has an 8-bit length field * (preceded by 8 reserved bits), v1.1 has a 13-bit length field (preceded by * 3 reserved bits). We use a be16 for our length to handle the larger v1.1 * representation, and mask as appropriate. */ struct mctp_usb_hdr { __be16 id; __be16 len; } __packed; /* max transfer size for DSP0283 v1.0 */ #define MCTP_USB_1_0_XFER_SIZE 512 #define MCTP_USB_BTU 68 #define MCTP_USB_MTU_MIN MCTP_USB_BTU #define MCTP_USB_1_0_PKTLEN_MAX U8_MAX #define MCTP_USB_1_0_MTU_MAX (MCTP_USB_1_0_PKTLEN_MAX - sizeof(struct mctp_usb_hdr)) #define MCTP_USB_1_1_PKTLEN_MAX GENMASK(12, 0) #define MCTP_USB_1_1_MTU_MAX (MCTP_USB_1_1_PKTLEN_MAX - sizeof(struct mctp_usb_hdr)) #define MCTP_USB_DMTF_ID 0x1ab4 /* mctp-usblib */ /* * RX handle: drivers will typically create one on init, which persists for * the life of the driver. The same handle is used for progressive * prepare -> complete operations (for each incoming USB transfer), which * result in netif_rx()-ing the MCTP packets received */ struct mctp_usblib_rx { struct sk_buff *skb; u16 ep_pktlen; bool span; }; int mctp_usblib_rx_init(struct mctp_usblib_rx *rx, u16 ep_pktlen, bool span); void mctp_usblib_rx_fini(struct mctp_usblib_rx *rx); int mctp_usblib_rx_prepare(struct net_device *netdev, struct mctp_usblib_rx *rx, void **bufp, size_t *lenp, gfp_t gfp); int mctp_usblib_rx_complete(struct net_device *netdev, struct mctp_usblib_rx *rx, size_t len); void mctp_usblib_rx_cancel(struct mctp_usblib_rx *rx); /* * TX handle: created by mctp_usblib_tx_push() during the tx path, and * may persist across multiple packet transmits. */ struct mctp_usblib_tx_ctx; struct mctp_usblib_tx_ops { /* Start a USB TX for @data. On returning success, the implementation * must arrange for mctp_usblib_tx_send_complete() to be called at some * later point (eg., on urb completion). */ int (*send)(struct mctp_usblib_tx_ctx *tx_ctx, void *data, size_t len); }; struct mctp_usblib_tx { struct mctp_usblib_tx_ops ops; void *priv; bool span; /* protects access to cur_ctx */ spinlock_t lock; /* context to which we are adding packets, cleared on send */ struct mctp_usblib_tx_ctx *cur_ctx; }; void mctp_usblib_tx_init(struct mctp_usblib_tx *tx, const struct mctp_usblib_tx_ops *ops, void *priv, bool span); void mctp_usblib_tx_fini(struct mctp_usblib_tx *tx); void *mctp_usblib_tx_ctx_priv(struct mctp_usblib_tx_ctx *tx_ctx); int mctp_usblib_tx_push(struct net_device *dev, struct mctp_usblib_tx *tx, struct sk_buff *skb, bool more); void mctp_usblib_tx_send_complete(struct mctp_usblib_tx_ctx *tx_ctx, struct net_device *dev, bool ok); void mctp_usblib_tx_cancel(struct mctp_usblib_tx *tx, struct net_device *dev, enum skb_drop_reason reason); #endif /* __LINUX_USB_MCTP_USB_H */