Commit 8f36b3b4 authored by Shuah Khan's avatar Shuah Khan Committed by Greg Kroah-Hartman
Browse files

usbip: add USBIP_URB_* URB transfer flags



USBIP driver packs URB transfer flags in network packets that are
exchanged between Server (usbip_host) and Client (vhci_hcd).

URB_* flags are internal to kernel and could change. Where as USBIP
URB flags exchanged in network packets are USBIP user API must not
change.

Add USBIP_URB* flags to make this an explicit API and change the
client and server to map them. Details as follows:

Client tx path (USBIP_CMD_SUBMIT):
- Maps URB_* to USBIP_URB_* when it sends USBIP_CMD_SUBMIT packet.

Server rx path (USBIP_CMD_SUBMIT):
- Maps USBIP_URB_* to URB_* when it receives USBIP_CMD_SUBMIT packet.

Flags aren't included in USBIP_CMD_UNLINK and USBIP_RET_SUBMIT packets
and no special handling is needed for them in the following cases:

- Server rx path (USBIP_CMD_UNLINK)
- Client rx path & Server tx path (USBIP_RET_SUBMIT)

Update protocol documentation to reflect the change.

Suggested-by: default avatarHongren Zenithal Zheng <i@zenithal.me>
Suggested-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarShuah Khan <skhan@linuxfoundation.org>
Link: https://lore.kernel.org/r/20220824002456.94605-1-skhan@linuxfoundation.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent dff98184
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -340,13 +340,12 @@ USBIP_CMD_SUBMIT:
| 0         | 20     | usbip_header_basic, 'command' shall be 0x00000001 |
+-----------+--------+---------------------------------------------------+
| 0x14      | 4      | transfer_flags: possible values depend on the     |
|           |        | URB transfer_flags (refer to URB doc in           |
|           |        | Documentation/driver-api/usb/URB.rst)             |
|           |        | but with URB_NO_TRANSFER_DMA_MAP masked. Refer to |
|           |        | function usbip_pack_cmd_submit and function       |
|           |        | tweak_transfer_flags in drivers/usb/usbip/        |
|           |        | usbip_common.c. The following fields may also ref |
|           |        | to function usbip_pack_cmd_submit and URB doc     |
|           |        | USBIP_URB transfer_flags.                         |
|           |        | Refer to include/uapi/linux/usbip.h and           |
|           |        | Documentation/driver-api/usb/URB.rst.             |
|           |        | Refer to usbip_pack_cmd_submit() and              |
|           |        | tweak_transfer_flags() in drivers/usb/usbip/      |
|           |        | usbip_common.c.                                   |
+-----------+--------+---------------------------------------------------+
| 0x18      | 4      | transfer_buffer_length:                           |
|           |        | use URB transfer_buffer_length                    |
+2 −2
Original line number Diff line number Diff line
@@ -464,7 +464,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
	int nents;
	int num_urbs = 1;
	int pipe = get_pipe(sdev, pdu);
	int use_sg = pdu->u.cmd_submit.transfer_flags & URB_DMA_MAP_SG;
	int use_sg = pdu->u.cmd_submit.transfer_flags & USBIP_URB_DMA_MAP_SG;
	int support_sg = 1;
	int np = 0;
	int ret, i;
@@ -514,7 +514,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
				num_urbs = nents;
				priv->completed_urbs = 0;
				pdu->u.cmd_submit.transfer_flags &=
								~URB_DMA_MAP_SG;
								~USBIP_URB_DMA_MAP_SG;
			}
		} else {
			buffer = kzalloc(buf_len, GFP_KERNEL);
+88 −3
Original line number Diff line number Diff line
@@ -344,6 +344,91 @@ static unsigned int tweak_transfer_flags(unsigned int flags)
	return flags;
}

/*
 * USBIP driver packs URB transfer flags in PDUs that are exchanged
 * between Server (usbip_host) and Client (vhci_hcd). URB_* flags
 * are internal to kernel and could change. Where as USBIP URB flags
 * exchanged in PDUs are USBIP user API must not change.
 *
 * USBIP_URB* flags are exported as explicit API and client and server
 * do mapping from kernel flags to USBIP_URB*. Details as follows:
 *
 * Client tx path (USBIP_CMD_SUBMIT):
 * - Maps URB_* to USBIP_URB_* when it sends USBIP_CMD_SUBMIT packet.
 *
 * Server rx path (USBIP_CMD_SUBMIT):
 * - Maps USBIP_URB_* to URB_* when it receives USBIP_CMD_SUBMIT packet.
 *
 * Flags aren't included in USBIP_CMD_UNLINK and USBIP_RET_SUBMIT packets
 * and no special handling is needed for them in the following cases:
 * - Server rx path (USBIP_CMD_UNLINK)
 * - Client rx path & Server tx path (USBIP_RET_SUBMIT)
 *
 * Code paths:
 * usbip_pack_pdu() is the common routine that handles packing pdu from
 * urb and unpack pdu to an urb.
 *
 * usbip_pack_cmd_submit() and usbip_pack_ret_submit() handle
 * USBIP_CMD_SUBMIT and USBIP_RET_SUBMIT respectively.
 *
 * usbip_map_urb_to_usbip() and usbip_map_usbip_to_urb() are used
 * by usbip_pack_cmd_submit() and usbip_pack_ret_submit() to map
 * flags.
 */

struct urb_to_usbip_flags {
	u32 urb_flag;
	u32 usbip_flag;
};

#define NUM_USBIP_FLAGS	17

static const struct urb_to_usbip_flags flag_map[NUM_USBIP_FLAGS] = {
	{URB_SHORT_NOT_OK, USBIP_URB_SHORT_NOT_OK},
	{URB_ISO_ASAP, USBIP_URB_ISO_ASAP},
	{URB_NO_TRANSFER_DMA_MAP, USBIP_URB_NO_TRANSFER_DMA_MAP},
	{URB_ZERO_PACKET, USBIP_URB_ZERO_PACKET},
	{URB_NO_INTERRUPT, USBIP_URB_NO_INTERRUPT},
	{URB_FREE_BUFFER, USBIP_URB_FREE_BUFFER},
	{URB_DIR_IN, USBIP_URB_DIR_IN},
	{URB_DIR_OUT, USBIP_URB_DIR_OUT},
	{URB_DIR_MASK, USBIP_URB_DIR_MASK},
	{URB_DMA_MAP_SINGLE, USBIP_URB_DMA_MAP_SINGLE},
	{URB_DMA_MAP_PAGE, USBIP_URB_DMA_MAP_PAGE},
	{URB_DMA_MAP_SG, USBIP_URB_DMA_MAP_SG},
	{URB_MAP_LOCAL, USBIP_URB_MAP_LOCAL},
	{URB_SETUP_MAP_SINGLE, USBIP_URB_SETUP_MAP_SINGLE},
	{URB_SETUP_MAP_LOCAL, USBIP_URB_SETUP_MAP_LOCAL},
	{URB_DMA_SG_COMBINED, USBIP_URB_DMA_SG_COMBINED},
	{URB_ALIGNED_TEMP_BUFFER, USBIP_URB_ALIGNED_TEMP_BUFFER},
};

static unsigned int urb_to_usbip(unsigned int flags)
{
	unsigned int map_flags = 0;
	int loop;

	for (loop = 0; loop < NUM_USBIP_FLAGS; loop++) {
		if (flags & flag_map[loop].urb_flag)
			map_flags |= flag_map[loop].usbip_flag;
	}

	return map_flags;
}

static unsigned int usbip_to_urb(unsigned int flags)
{
	unsigned int map_flags = 0;
	int loop;

	for (loop = 0; loop < NUM_USBIP_FLAGS; loop++) {
		if (flags & flag_map[loop].usbip_flag)
			map_flags |= flag_map[loop].urb_flag;
	}

	return map_flags;
}

static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
				  int pack)
{
@@ -354,14 +439,14 @@ static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
	 * will be discussed when usbip is ported to other operating systems.
	 */
	if (pack) {
		spdu->transfer_flags =
			tweak_transfer_flags(urb->transfer_flags);
		/* map after tweaking the urb flags */
		spdu->transfer_flags = urb_to_usbip(tweak_transfer_flags(urb->transfer_flags));
		spdu->transfer_buffer_length	= urb->transfer_buffer_length;
		spdu->start_frame		= urb->start_frame;
		spdu->number_of_packets		= urb->number_of_packets;
		spdu->interval			= urb->interval;
	} else  {
		urb->transfer_flags         = spdu->transfer_flags;
		urb->transfer_flags         = usbip_to_urb(spdu->transfer_flags);
		urb->transfer_buffer_length = spdu->transfer_buffer_length;
		urb->start_frame            = spdu->start_frame;
		urb->number_of_packets      = spdu->number_of_packets;
+26 −0
Original line number Diff line number Diff line
@@ -24,4 +24,30 @@ enum usbip_device_status {
	VDEV_ST_USED,
	VDEV_ST_ERROR
};

/* USB URB Transfer flags:
 *
 * USBIP server and client (vchi) pack URBs in TCP packets. The following
 * are the transfer type defines used in USBIP protocol.
 */

#define USBIP_URB_SHORT_NOT_OK		0x0001
#define USBIP_URB_ISO_ASAP		0x0002
#define USBIP_URB_NO_TRANSFER_DMA_MAP	0x0004
#define USBIP_URB_ZERO_PACKET		0x0040
#define USBIP_URB_NO_INTERRUPT		0x0080
#define USBIP_URB_FREE_BUFFER		0x0100
#define USBIP_URB_DIR_IN		0x0200
#define USBIP_URB_DIR_OUT		0
#define USBIP_URB_DIR_MASK		USBIP_URB_DIR_IN

#define USBIP_URB_DMA_MAP_SINGLE	0x00010000
#define USBIP_URB_DMA_MAP_PAGE		0x00020000
#define USBIP_URB_DMA_MAP_SG		0x00040000
#define USBIP_URB_MAP_LOCAL		0x00080000
#define USBIP_URB_SETUP_MAP_SINGLE	0x00100000
#define USBIP_URB_SETUP_MAP_LOCAL	0x00200000
#define USBIP_URB_DMA_SG_COMBINED	0x00400000
#define USBIP_URB_ALIGNED_TEMP_BUFFER	0x00800000

#endif /* _UAPI_LINUX_USBIP_H */