iwlwifi: pcie: fix polling in various places
[cascardo/linux.git] / drivers / usb / gadget / function / f_fs.c
index 0dc3552..4ad11e0 100644 (file)
@@ -1032,6 +1032,29 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
                case FUNCTIONFS_ENDPOINT_REVMAP:
                        ret = epfile->ep->num;
                        break;
+               case FUNCTIONFS_ENDPOINT_DESC:
+               {
+                       int desc_idx;
+                       struct usb_endpoint_descriptor *desc;
+
+                       switch (epfile->ffs->gadget->speed) {
+                       case USB_SPEED_SUPER:
+                               desc_idx = 2;
+                               break;
+                       case USB_SPEED_HIGH:
+                               desc_idx = 1;
+                               break;
+                       default:
+                               desc_idx = 0;
+                       }
+                       desc = epfile->ep->descs[desc_idx];
+
+                       spin_unlock_irq(&epfile->ffs->eps_lock);
+                       ret = copy_to_user((void *)value, desc, sizeof(*desc));
+                       if (ret)
+                               ret = -EFAULT;
+                       return ret;
+               }
                default:
                        ret = -ENOTTY;
                }
@@ -1534,7 +1557,10 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
                epfile->ffs = ffs;
                mutex_init(&epfile->mutex);
                init_waitqueue_head(&epfile->wait);
-               sprintf(epfiles->name, "ep%u",  i);
+               if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
+                       sprintf(epfiles->name, "ep%02x", ffs->eps_addrmap[i]);
+               else
+                       sprintf(epfiles->name, "ep%u", i);
                if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile,
                                                 &ffs_epfile_operations,
                                                 &epfile->dentry))) {
@@ -2083,10 +2109,12 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
                break;
        case FUNCTIONFS_DESCRIPTORS_MAGIC_V2:
                flags = get_unaligned_le32(data + 8);
+               ffs->user_flags = flags;
                if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
                              FUNCTIONFS_HAS_HS_DESC |
                              FUNCTIONFS_HAS_SS_DESC |
-                             FUNCTIONFS_HAS_MS_OS_DESC)) {
+                             FUNCTIONFS_HAS_MS_OS_DESC |
+                             FUNCTIONFS_VIRTUAL_ADDR)) {
                        ret = -ENOSYS;
                        goto error;
                }
@@ -2346,7 +2374,8 @@ static void __ffs_event_add(struct ffs_data *ffs,
                break;
 
        default:
-               BUG();
+               WARN(1, "%d: unknown event, this should not happen\n", type);
+               return;
        }
 
        {
@@ -2393,7 +2422,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
        struct usb_endpoint_descriptor *ds = (void *)desc;
        struct ffs_function *func = priv;
        struct ffs_ep *ffs_ep;
-       unsigned ep_desc_id, idx;
+       unsigned ep_desc_id;
+       int idx;
        static const char *speed_names[] = { "full", "high", "super" };
 
        if (type != FFS_DESCRIPTOR)
@@ -2441,7 +2471,13 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
        } else {
                struct usb_request *req;
                struct usb_ep *ep;
+               u8 bEndpointAddress;
 
+               /*
+                * We back up bEndpointAddress because autoconfig overwrites
+                * it with physical endpoint address.
+                */
+               bEndpointAddress = ds->bEndpointAddress;
                pr_vdebug("autoconfig\n");
                ep = usb_ep_autoconfig(func->gadget, ds);
                if (unlikely(!ep))
@@ -2456,6 +2492,12 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
                ffs_ep->req = req;
                func->eps_revmap[ds->bEndpointAddress &
                                 USB_ENDPOINT_NUMBER_MASK] = idx + 1;
+               /*
+                * If we use virtual address mapping, we restore
+                * original bEndpointAddress value.
+                */
+               if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
+                       ds->bEndpointAddress = bEndpointAddress;
        }
        ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
 
@@ -2900,6 +2942,8 @@ static int ffs_func_setup(struct usb_function *f,
                ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex));
                if (unlikely(ret < 0))
                        return ret;
+               if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
+                       ret = func->ffs->eps_addrmap[ret];
                break;
 
        default: