Let the host backend supply a name prefix for a port's UDC parent
platform_device via the bind event, instead of always using the
generic GADGET_NAME. When present, the prefix is used verbatim as
the parent device's name and the gadget name becomes
"<prefix>_p<port>"; when empty, behavior is unchanged.

Signed-off-by: Igor Skalkin <[email protected]>
---
 drivers/usb/virtio_usb/device.c |   47 +++++++++++++++++++++++++++++++++-------
 include/uapi/linux/virtio_usb.h |    4 ++-
 2 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/virtio_usb/device.c b/drivers/usb/virtio_usb/device.c
index ee41ea9..fedce74 100644
--- a/drivers/usb/virtio_usb/device.c
+++ b/drivers/usb/virtio_usb/device.c
@@ -1369,11 +1369,26 @@ on_error:
        return rc;
 }
 
-static int virtio_usb_dc_parent_create(struct virtio_usb_dc *vudc)
+static int virtio_usb_dc_parent_create(struct virtio_usb_dc *vudc,
+                                      const unsigned char *udc_prefix)
 {
+       size_t prefix_len;
+       char *parent_name;
        int rc;
 
-       vudc->pdev = platform_device_alloc(GADGET_NAME, vudc->port);
+       prefix_len = strnlen((const char *)udc_prefix,
+                            VIRTIO_USB_UDC_NAME_PREFIX_MAX);
+       if (prefix_len) {
+               parent_name = kasprintf(GFP_KERNEL, "%.*s", (int)prefix_len,
+                                       (const char *)udc_prefix);
+       } else {
+               parent_name = kstrdup(GADGET_NAME, GFP_KERNEL);
+       }
+       if (!parent_name)
+               return -ENOMEM;
+
+       vudc->pdev = platform_device_alloc(parent_name, vudc->port);
+       kfree(parent_name);
        if (!vudc->pdev)
                return -ENOMEM;
 
@@ -1421,6 +1436,7 @@ static void virtio_usb_dc_event_process(struct 
virtio_usb_event *event)
        switch (le32_to_cpu(evt->code)) {
        case VIRTIO_USB_EVT_DEV_BIND: {
                u8 max_speed;
+               size_t udc_prefix_len;
 
                if (vudc->registered) {
                        dev_err(&vusb->vdev->dev,
@@ -1447,7 +1463,8 @@ static void virtio_usb_dc_event_process(struct 
virtio_usb_event *event)
                        break;
                }
                if (!vudc->pdev) {
-                       rc = virtio_usb_dc_parent_create(vudc);
+                       rc = virtio_usb_dc_parent_create(
+                               vudc, bind_evt->udc_name_prefix);
                        if (rc) {
                                dev_err(&vusb->vdev->dev,
                                        "Failed to create UDC parent device\n");
@@ -1456,8 +1473,18 @@ static void virtio_usb_dc_event_process(struct 
virtio_usb_event *event)
                                break;
                        }
                }
-               vudc->gadget.name =
-                       kasprintf(GFP_KERNEL, "%s_%d", GADGET_NAME, port_id);
+               udc_prefix_len =
+                       strnlen((const char *)bind_evt->udc_name_prefix,
+                               VIRTIO_USB_UDC_NAME_PREFIX_MAX);
+               if (udc_prefix_len) {
+                       vudc->gadget.name = kasprintf(
+                               GFP_KERNEL, "%.*s_p%d", (int)udc_prefix_len,
+                               (const char *)bind_evt->udc_name_prefix,
+                               port_id);
+               } else {
+                       vudc->gadget.name = kasprintf(GFP_KERNEL, "%s_%d",
+                                                     GADGET_NAME, port_id);
+               }
                if (!vudc->gadget.name) {
                        rc = -ENOMEM;
                        kfree(vudc->veps);
@@ -1480,7 +1507,6 @@ static void virtio_usb_dc_event_process(struct 
virtio_usb_event *event)
                        break;
                }
 
-               //vudc->gadget.dev.init_name = gadget_name;
                vudc->gadget.dev.parent = &vudc->pdev->dev;
                rc = usb_add_gadget_udc(&vudc->pdev->dev, &vudc->gadget);
                if (rc) {
@@ -1612,11 +1638,16 @@ int virtio_usb_dc_event_populate(struct virtio_usb 
*vusb)
 {
        struct virtio_usb_queue *evt_queue =
                &vusb->vqueues[vusb->dev_vq_base + VIRTIO_USB_VQ_EVENT_IDX];
+       size_t evt_size;
        struct virtio_usb_event *events;
        int rc;
 
-       events = virtio_usb_events_alloc(vusb, evt_queue,
-                                        sizeof(struct virtio_usb_dev_event));
+       evt_size = max_t(size_t, sizeof(struct virtio_usb_dev_event),
+                        sizeof(struct virtio_usb_dev_setup_event));
+       evt_size = max_t(size_t, evt_size,
+                        sizeof(struct virtio_usb_dev_bind_event));
+
+       events = virtio_usb_events_alloc(vusb, evt_queue, evt_size);
 
        if (!events)
                return -ENOMEM;
diff --git a/include/uapi/linux/virtio_usb.h b/include/uapi/linux/virtio_usb.h
index d89223d..5fff248 100644
--- a/include/uapi/linux/virtio_usb.h
+++ b/include/uapi/linux/virtio_usb.h
@@ -216,6 +216,8 @@ enum {
        VIRTIO_USB_EVT_DEV_UNBIND,
 };
 
+#define VIRTIO_USB_UDC_NAME_PREFIX_MAX 64
+
 struct virtio_usb_dev_event {
        __le32 code; /* VIRTIO_USB_EVT_DEV_XXX */
        __le16 port; /* Device ID */
@@ -227,7 +229,7 @@ struct virtio_usb_dev_bind_event {
        __le32 code; /* VIRTIO_USB_EVT_DEV_BIND */
        __le16 port; /* Device ID */
        __u8 max_speed; /* enum usb_device_speed */
-       __u8 padding[9];
+       __u8 udc_name_prefix[VIRTIO_USB_UDC_NAME_PREFIX_MAX];
 };
 
 /* VIRTIO_USB_EVT_DEV_SETUP */

Reply via email to