usbip: add USBIP_URB_* URB transfer flags
authorShuah Khan <skhan@linuxfoundation.org>
Wed, 24 Aug 2022 00:24:56 +0000 (18:24 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Aug 2022 07:07:53 +0000 (09:07 +0200)
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: Hongren Zenithal Zheng <i@zenithal.me>
Suggested-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
Link: https://lore.kernel.org/r/20220824002456.94605-1-skhan@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/usb/usbip_protocol.rst
drivers/usb/usbip/stub_rx.c
drivers/usb/usbip/usbip_common.c
include/uapi/linux/usbip.h

index 0b8541fda4d8476e7686b6f569e3345ef5d64a76..adc158967cc6113188d751c96b21f90393cefe88 100644 (file)
@@ -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                    |
index 5dd41e8215e0febd22ede7bb8cd35296bf04d214..fc01b31bbb875d1b200c68ba32f219168035a532 100644 (file)
@@ -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);
index 2ab99244bc314dd42c0921105181fbbecdc3047e..053a2bca4c475a54ba7081b979b331652124edea 100644 (file)
@@ -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;
index fd393d908d8a3170c6ff57a431c924fdfd229b18..e4421ad55b2eedb02df062860818ee1c52f1dd8d 100644 (file)
@@ -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 */