USB ECHI: Fix a bug when trying to traverse an empty asynchronous queue
This commit is contained in:
parent
5c76c53909
commit
5b80b257ce
@ -2995,13 +2995,18 @@ static inline void lpc31_ioc_bottomhalf(void)
|
|||||||
cp15_invalidate_dcache((uintptr_t)&g_asynchead.hw,
|
cp15_invalidate_dcache((uintptr_t)&g_asynchead.hw,
|
||||||
(uintptr_t)&g_asynchead.hw + sizeof(struct ehci_qh_s));
|
(uintptr_t)&g_asynchead.hw + sizeof(struct ehci_qh_s));
|
||||||
|
|
||||||
/* Set the back pointer to the forward qTD pointer of the asynchronous
|
/* Set the back pointer to the forward QH pointer of the asynchronous
|
||||||
* queue head.
|
* queue head.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bp = (uint32_t *)&g_asynchead.hw.hlp;
|
bp = (uint32_t *)&g_asynchead.hw.hlp;
|
||||||
qh = (struct lpc31_qh_s *)lpc31_virtramaddr(lpc31_swap32(*bp) & QH_HLP_MASK);
|
qh = (struct lpc31_qh_s *)lpc31_virtramaddr(lpc31_swap32(*bp) & QH_HLP_MASK);
|
||||||
if (qh)
|
|
||||||
|
/* If the asynchronous queue is empty, then the forward point in the
|
||||||
|
* asynchronous queue head will point back to the the queue head.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (qh && qh != &g_asynchead)
|
||||||
{
|
{
|
||||||
/* Then traverse and operate on every QH and qTD in the asynchronous
|
/* Then traverse and operate on every QH and qTD in the asynchronous
|
||||||
* queue
|
* queue
|
||||||
@ -4491,12 +4496,46 @@ static int lpc31_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
|
|||||||
{
|
{
|
||||||
case USB_EP_ATTR_XFER_CONTROL:
|
case USB_EP_ATTR_XFER_CONTROL:
|
||||||
case USB_EP_ATTR_XFER_BULK:
|
case USB_EP_ATTR_XFER_BULK:
|
||||||
qh = &g_asynchead;
|
{
|
||||||
|
/* Get the horizontal pointer from the head of the asynchronous
|
||||||
|
* queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bp = (uint32_t *)&g_asynchead.hw.hlp;
|
||||||
|
qh = (struct lpc31_qh_s *)lpc31_virtramaddr(lpc31_swap32(*bp) & QH_HLP_MASK);
|
||||||
|
|
||||||
|
/* If the asynchronous queue is empty, then the forward point in
|
||||||
|
* the asynchronous queue head will point back to the the queue
|
||||||
|
* head.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (qh && qh != &g_asynchead)
|
||||||
|
{
|
||||||
|
/* Claim that we successfully cancelled the transfer */
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef CONFIG_USBHOST_INT_DISABLE
|
#ifndef CONFIG_USBHOST_INT_DISABLE
|
||||||
case USB_EP_ATTR_XFER_INT:
|
case USB_EP_ATTR_XFER_INT:
|
||||||
qh = &g_intrhead;
|
{
|
||||||
|
/* Get the horizontal pointer from the head of the interrupt
|
||||||
|
* queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bp = (uint32_t *)&g_intrhead.hw.hlp;
|
||||||
|
qh = (struct lpc31_qh_s *)lpc31_virtramaddr(lpc31_swap32(*bp) & QH_HLP_MASK);
|
||||||
|
if (qh)
|
||||||
|
{
|
||||||
|
/* if the queue is empty, then just claim that we successfully
|
||||||
|
* cancelled the transfer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2814,13 +2814,18 @@ static inline void sam_ioc_bottomhalf(void)
|
|||||||
arch_invalidate_dcache((uintptr_t)&g_asynchead.hw,
|
arch_invalidate_dcache((uintptr_t)&g_asynchead.hw,
|
||||||
(uintptr_t)&g_asynchead.hw + sizeof(struct ehci_qh_s));
|
(uintptr_t)&g_asynchead.hw + sizeof(struct ehci_qh_s));
|
||||||
|
|
||||||
/* Set the back pointer to the forward qTD pointer of the asynchronous
|
/* Set the back pointer to the forward QH pointer of the asynchronous
|
||||||
* queue head.
|
* queue head.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bp = (uint32_t *)&g_asynchead.hw.hlp;
|
bp = (uint32_t *)&g_asynchead.hw.hlp;
|
||||||
qh = (struct sam_qh_s *)sam_virtramaddr(sam_swap32(*bp) & QH_HLP_MASK);
|
qh = (struct sam_qh_s *)sam_virtramaddr(sam_swap32(*bp) & QH_HLP_MASK);
|
||||||
if (qh)
|
|
||||||
|
/* If the asynchronous queue is empty, then the forward point in the
|
||||||
|
* asynchronous queue head will point back to the the queue head.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (qh && qh != &g_asynchead)
|
||||||
{
|
{
|
||||||
/* Then traverse and operate on every QH and qTD in the asynchronous
|
/* Then traverse and operate on every QH and qTD in the asynchronous
|
||||||
* queue
|
* queue
|
||||||
@ -4317,12 +4322,46 @@ static int sam_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
|
|||||||
{
|
{
|
||||||
case USB_EP_ATTR_XFER_CONTROL:
|
case USB_EP_ATTR_XFER_CONTROL:
|
||||||
case USB_EP_ATTR_XFER_BULK:
|
case USB_EP_ATTR_XFER_BULK:
|
||||||
qh = &g_asynchead;
|
{
|
||||||
|
/* Get the horizontal pointer from the head of the asynchronous
|
||||||
|
* queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bp = (uint32_t *)&g_asynchead.hw.hlp;
|
||||||
|
qh = (struct sam_qh_s *)sam_virtramaddr(sam_swap32(*bp) & QH_HLP_MASK);
|
||||||
|
|
||||||
|
/* If the asynchronous queue is empty, then the forward point in
|
||||||
|
* the asynchronous queue head will point back to the the queue
|
||||||
|
* head.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (qh && qh != &g_asynchead)
|
||||||
|
{
|
||||||
|
/* Claim that we successfully cancelled the transfer */
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef CONFIG_USBHOST_INT_DISABLE
|
#ifndef CONFIG_USBHOST_INT_DISABLE
|
||||||
case USB_EP_ATTR_XFER_INT:
|
case USB_EP_ATTR_XFER_INT:
|
||||||
qh = &g_intrhead;
|
{
|
||||||
|
/* Get the horizontal pointer from the head of the interrupt
|
||||||
|
* queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bp = (uint32_t *)&g_intrhead.hw.hlp;
|
||||||
|
qh = (struct sam_qh_s *)sam_virtramaddr(sam_swap32(*bp) & QH_HLP_MASK);
|
||||||
|
if (qh)
|
||||||
|
{
|
||||||
|
/* if the queue is empty, then just claim that we successfully
|
||||||
|
* cancelled the transfer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user