On 6/5/2015 7:23 AM, Mian Yousaf Kaukab wrote: > To avoid sleep while atomic bugs, allocate qh before calling > dwc2_hcd_urb_enqueue. qh pointer can be used directly now instead of > passing ep->hcpriv as double pointer. > > Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@xxxxxxxxx> > --- > drivers/usb/dwc2/hcd.c | 31 ++++++++++++++++++++++++++---- > drivers/usb/dwc2/hcd.h | 5 ++++- > drivers/usb/dwc2/hcd_queue.c | 45 ++++++++++++-------------------------------- > 3 files changed, 43 insertions(+), 38 deletions(-) > > diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c > index b10377c..80bce71 100644 > --- a/drivers/usb/dwc2/hcd.c > +++ b/drivers/usb/dwc2/hcd.c > @@ -359,7 +359,7 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hsotg) > > /* Caller must hold driver lock */ > static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, > - struct dwc2_hcd_urb *urb, void **ep_handle, > + struct dwc2_hcd_urb *urb, struct dwc2_qh *qh, > gfp_t mem_flags) > { > struct dwc2_qtd *qtd; > @@ -391,8 +391,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, > return -ENOMEM; > > dwc2_hcd_qtd_init(qtd, urb); > - retval = dwc2_hcd_qtd_add(hsotg, qtd, (struct dwc2_qh **)ep_handle, > - mem_flags); > + retval = dwc2_hcd_qtd_add(hsotg, qtd, qh); > if (retval) { > dev_err(hsotg->dev, > "DWC OTG HCD URB Enqueue failed adding QTD. Error status %d\n", > @@ -2445,6 +2444,8 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, > u32 tflags = 0; > void *buf; > unsigned long flags; > + struct dwc2_qh *qh; > + bool qh_allocated = false; > > if (dbg_urb(urb)) { > dev_vdbg(hsotg->dev, "DWC OTG HCD URB Enqueue\n"); > @@ -2523,13 +2524,24 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, > urb->iso_frame_desc[i].length); > > urb->hcpriv = dwc2_urb; > + qh = (struct dwc2_qh *) ep->hcpriv; > + /* Create QH for the endpoint if it doesn't exist */ > + if (!qh) { > + qh = dwc2_hcd_qh_create(hsotg, dwc2_urb, mem_flags); > + if (!qh) { > + retval = -ENOMEM; > + goto fail0; > + } > + ep->hcpriv = qh; > + qh_allocated = true; > + } > > spin_lock_irqsave(&hsotg->lock, flags); > retval = usb_hcd_link_urb_to_ep(hcd, urb); > if (retval) > goto fail1; > > - retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv, mem_flags); > + retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, qh, mem_flags); > if (retval) > goto fail2; > > @@ -2549,6 +2561,17 @@ fail2: > fail1: > spin_unlock_irqrestore(&hsotg->lock, flags); > urb->hcpriv = NULL; > + if (qh_allocated) { > + struct dwc2_qtd *qtd2, *qtd2_tmp; > + > + ep->hcpriv = NULL; > + dwc2_hcd_qh_unlink(hsotg, qh); > + /* Free each QTD in the QH's QTD list */ > + list_for_each_entry_safe(qtd2, qtd2_tmp, &qh->qtd_list, > + qtd_list_entry) > + dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh); > + dwc2_hcd_qh_free(hsotg, qh); > + } > fail0: > kfree(dwc2_urb); > > diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h > index 7b5841c..fc10549 100644 > --- a/drivers/usb/dwc2/hcd.h > +++ b/drivers/usb/dwc2/hcd.h > @@ -463,6 +463,9 @@ extern void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg, > /* Schedule Queue Functions */ > /* Implemented in hcd_queue.c */ > extern void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg); > +extern struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, > + struct dwc2_hcd_urb *urb, > + gfp_t mem_flags); > extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); > extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); > extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); > @@ -471,7 +474,7 @@ extern void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, > > extern void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb); > extern int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, > - struct dwc2_qh **qh, gfp_t mem_flags); > + struct dwc2_qh *qh); > > /* Unlinks and frees a QTD */ > static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg, > diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c > index 9b5c362..e573a4f 100644 > --- a/drivers/usb/dwc2/hcd_queue.c > +++ b/drivers/usb/dwc2/hcd_queue.c > @@ -191,7 +191,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, > * > * Return: Pointer to the newly allocated QH, or NULL on error > */ > -static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, > +struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, > struct dwc2_hcd_urb *urb, > gfp_t mem_flags) > { > @@ -767,57 +767,36 @@ void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb) > * > * @hsotg: The DWC HCD structure > * @qtd: The QTD to add > - * @qh: Out parameter to return queue head > - * @atomic_alloc: Flag to do atomic alloc if needed > + * @qh: Queue head to add qtd to > * > * Return: 0 if successful, negative error code otherwise > * > - * Finds the correct QH to place the QTD into. If it does not find a QH, it > - * will create a new QH. If the QH to which the QTD is added is not currently > - * scheduled, it is placed into the proper schedule based on its EP type. > + * If the QH to which the QTD is added is not currently scheduled, it is placed > + * into the proper schedule based on its EP type. > */ > int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, > - struct dwc2_qh **qh, gfp_t mem_flags) > + struct dwc2_qh *qh) > { > - struct dwc2_hcd_urb *urb = qtd->urb; > - int allocated = 0; > int retval; > > /* > * Get the QH which holds the QTD-list to insert to. Create QH if it > * doesn't exist. > */ This comment doesn't apply anymore. Otherwise the series looks ok. Acked-by: John Youn <johnyoun@xxxxxxxxxxxx> John -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html