unsigned long value)
 {
        struct ffs_epfile *epfile = file->private_data;
+       struct ffs_ep *ep;
        int ret;
 
        ENTER();
        if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
                return -ENODEV;
 
+       /* Wait for endpoint to be enabled */
+       ep = epfile->ep;
+       if (!ep) {
+               if (file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+
+               ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
+               if (ret)
+                       return -EINTR;
+       }
+
        spin_lock_irq(&epfile->ffs->eps_lock);
-       if (likely(epfile->ep)) {
-               switch (code) {
-               case FUNCTIONFS_FIFO_STATUS:
-                       ret = usb_ep_fifo_status(epfile->ep->ep);
-                       break;
-               case FUNCTIONFS_FIFO_FLUSH:
-                       usb_ep_fifo_flush(epfile->ep->ep);
-                       ret = 0;
-                       break;
-               case FUNCTIONFS_CLEAR_HALT:
-                       ret = usb_ep_clear_halt(epfile->ep->ep);
-                       break;
-               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];
+       /* In the meantime, endpoint got disabled or changed. */
+       if (epfile->ep != ep) {
+               spin_unlock_irq(&epfile->ffs->eps_lock);
+               return -ESHUTDOWN;
+       }
 
-                       spin_unlock_irq(&epfile->ffs->eps_lock);
-                       ret = copy_to_user((void *)value, desc, desc->bLength);
-                       if (ret)
-                               ret = -EFAULT;
-                       return ret;
-               }
+       switch (code) {
+       case FUNCTIONFS_FIFO_STATUS:
+               ret = usb_ep_fifo_status(epfile->ep->ep);
+               break;
+       case FUNCTIONFS_FIFO_FLUSH:
+               usb_ep_fifo_flush(epfile->ep->ep);
+               ret = 0;
+               break;
+       case FUNCTIONFS_CLEAR_HALT:
+               ret = usb_ep_clear_halt(epfile->ep->ep);
+               break;
+       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:
-                       ret = -ENOTTY;
+                       desc_idx = 0;
                }
-       } else {
-               ret = -ENODEV;
+               desc = epfile->ep->descs[desc_idx];
+
+               spin_unlock_irq(&epfile->ffs->eps_lock);
+               ret = copy_to_user((void *)value, desc, desc->bLength);
+               if (ret)
+                       ret = -EFAULT;
+               return ret;
+       }
+       default:
+               ret = -ENOTTY;
        }
        spin_unlock_irq(&epfile->ffs->eps_lock);
 
 
 #define        FUNCTIONFS_INTERFACE_REVMAP     _IO('g', 128)
 
 /*
- * Returns real bEndpointAddress of an endpoint.  If function is not
- * active returns -ENODEV.
+ * Returns real bEndpointAddress of an endpoint. If endpoint shuts down
+ * during the call, returns -ESHUTDOWN.
  */
 #define        FUNCTIONFS_ENDPOINT_REVMAP      _IO('g', 129)
 
 /*
- * Returns endpoint descriptor. If function is not active returns -ENODEV.
+ * Returns endpoint descriptor. If endpoint shuts down during the call,
+ * returns -ESHUTDOWN.
  */
 #define        FUNCTIONFS_ENDPOINT_DESC        _IOR('g', 130, \
                                             struct usb_endpoint_descriptor)