forked from raspberrypi/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dwc_otg: Fix unsafe access of QTD during URB enqueue
In dwc_otg_hcd_urb_enqueue during qtd creation, it was possible that the transaction could complete almost immediately after the qtd was assigned to a host channel during URB enqueue, which meant the qtd pointer was no longer valid having been completed and removed. Usually, this resulted in an OOPS during URB submission. By predetermining whether transactions need to be queued or not, this unsafe pointer access is avoided. This bug was only evident on the Pi model A where a device was attached that had no periodic endpoints (e.g. USB pendrive or some wlan devices).
- Loading branch information
P33M
authored and
P33M
committed
Feb 15, 2013
1 parent
871eef1
commit 3e964c4
Showing
2 changed files
with
13 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -462,6 +462,8 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, | |
{ | ||
dwc_irqflags_t flags; | ||
int retval = 0; | ||
uint8_t needs_scheduling = 0; | ||
dwc_otg_transaction_type_e tr_type; | ||
dwc_otg_qtd_t *qtd; | ||
gintmsk_data_t intr_mask = {.d32 = 0 }; | ||
|
||
|
@@ -493,30 +495,29 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, | |
return -DWC_E_NO_MEMORY; | ||
} | ||
#endif | ||
retval = | ||
dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc); | ||
intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); | ||
if(!intr_mask.b.sofintr) needs_scheduling = 1; | ||
if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
P33M
Owner
|
||
/* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ | ||
needs_scheduling = 0; | ||
|
||
retval = dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc); | ||
// creates a new queue in ep_handle if it doesn't exist already | ||
if (retval < 0) { | ||
DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " | ||
"Error status %d\n", retval); | ||
dwc_otg_hcd_qtd_free(qtd); | ||
return retval; | ||
} | ||
intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); | ||
if (!intr_mask.b.sofintr && retval == 0) { | ||
dwc_otg_transaction_type_e tr_type; | ||
if ((qtd->qh->ep_type == UE_BULK) | ||
&& !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { | ||
/* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ | ||
return 0; | ||
} | ||
|
||
if(needs_scheduling) { | ||
DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); | ||
tr_type = dwc_otg_hcd_select_transactions(hcd); | ||
if (tr_type != DWC_OTG_TRANSACTION_NONE) { | ||
dwc_otg_hcd_queue_transactions(hcd, tr_type); | ||
} | ||
DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); | ||
} | ||
|
||
return retval; | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Why is the first half of expression using ((dwc_otg_qh_t *)ep_handle)->ep_type rather than qtd->qh->ep_type ?