USB host: Need to include the port structure when disconnecting, otherwise may destroy a root hub port

This commit is contained in:
Gregory Nutt 2015-05-02 10:44:18 -06:00
parent 973f572829
commit c2a3f936aa
14 changed files with 93 additions and 51 deletions

View File

@ -467,7 +467,8 @@ static int efm32_connect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport,
bool connected);
#endif
static void efm32_disconnect(FAR struct usbhost_driver_s *drvr);
static void efm32_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport);
/* Initialization **************************************************************/
@ -4761,12 +4762,13 @@ static int efm32_connect(FAR struct usbhost_driver_s *drvr,
*
*******************************************************************************/
static void efm32_disconnect(FAR struct usbhost_driver_s *drvr)
static void efm32_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport)
{
FAR struct efm32_usbhost_s *priv = (FAR struct efm32_usbhost_s *)drvr;
DEBUGASSERT(priv);
DEBUGASSERT(priv != NULL && hport != NULL);
priv->rhport.hport.devclass = NULL;
hport->devclass = NULL;
}
/*******************************************************************************

View File

@ -390,7 +390,8 @@ static int lpc17_connect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport,
bool connected);
#endif
static void lpc17_disconnect(struct usbhost_driver_s *drvr);
static void lpc17_disconnect(struct usbhost_driver_s *drvr,
struct usbhost_hubport_s *hport);
/* Initialization **************************************************************/
@ -3213,6 +3214,8 @@ static int lpc17_connect(FAR struct usbhost_driver_s *drvr,
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* hport - The port from which the device is being disconnected. Might be a port
* on a hub.
*
* Returned Values:
* None
@ -3223,12 +3226,13 @@ static int lpc17_connect(FAR struct usbhost_driver_s *drvr,
*
*******************************************************************************/
static void lpc17_disconnect(struct usbhost_driver_s *drvr)
static void lpc17_disconnect(struct usbhost_driver_s *drvr,
struct usbhost_hubport_s *hport)
{
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
DEBUGASSERT(priv);
DEBUGASSERT(priv != NULL && hport != NULL);
priv->rhport.hport.devclass = NULL;
hport->devclass = NULL;
}
/*******************************************************************************

View File

@ -549,7 +549,8 @@ static int lpc31_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
static int lpc31_connect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport, bool connected);
#endif
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr);
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport);
/* Initialization **************************************************************/
@ -4638,6 +4639,8 @@ static int lpc31_connect(FAR struct usbhost_driver_s *drvr,
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* hport - The port from which the device is being disconnected. Might be a port
* on a hub.
*
* Returned Values:
* None
@ -4648,15 +4651,16 @@ static int lpc31_connect(FAR struct usbhost_driver_s *drvr,
*
*******************************************************************************/
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr)
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport)
{
struct lpc31_rhport_s *rhport = (struct lpc31_rhport_s *)drvr;
DEBUGASSERT(rhport);
DEBUGASSERT(rhport != NULL && hport != NULL);
/* Unbind the class */
/* REVISIT: Is there more that needs to be done? */
rhport->hport.hport.devclass = NULL;
hport->devclass = NULL;
}
/*******************************************************************************

View File

@ -425,7 +425,8 @@ static int sam_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
static int sam_connect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport, bool connected);
#endif
static void sam_disconnect(FAR struct usbhost_driver_s *drvr);
static void sam_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport);
/* Initialization **************************************************************/
@ -4464,6 +4465,8 @@ static int sam_connect(FAR struct usbhost_driver_s *drvr,
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* hport - The port from which the device is being disconnected. Might be a port
* on a hub.
*
* Returned Values:
* None
@ -4474,10 +4477,11 @@ static int sam_connect(FAR struct usbhost_driver_s *drvr,
*
*******************************************************************************/
static void sam_disconnect(FAR struct usbhost_driver_s *drvr)
static void sam_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport)
{
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
DEBUGASSERT(rhport);
DEBUGASSERT(rhport != NULL && hport != NULL);
/* Unbind the class */
/* REVISIT: Is there more that needs to be done? */

View File

@ -388,7 +388,7 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplis
struct sam_ed_s *ed, uint32_t dirpid, uint32_t toggle,
volatile uint8_t *buffer, size_t buflen);
static int sam_ep0enqueue(struct sam_rhport_s *rhport);
static void sam_ep0dequeue(struct sam_rhport_s *rhport);
static void sam_ep0dequeue(struct sam_eplist_s *ep0);
static int sam_wdhwait(struct sam_rhport_s *rhport, struct sam_ed_s *ed);
#ifdef CONFIG_USBHOST_ASYNCH
static int sam_wdhasynch(struct sam_rhport_s *rhport, struct sam_ed_s *ed,
@ -448,7 +448,8 @@ static int sam_connect(struct usbhost_driver_s *drvr,
struct usbhost_hubport_s *hport,
bool connected);
#endif
static void sam_disconnect(struct usbhost_driver_s *drvr);
static void sam_disconnect(struct usbhost_driver_s *drvr,
struct usbhost_hubport_s *hport);
/*******************************************************************************
* Private Data
@ -1520,8 +1521,8 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplis
* Name: sam_ep0enqueue
*
* Description:
* Initialize ED for EP0, add it to the control ED list, and enable control
* transfers.
* Initialize ED for a root hub EP0, add it to the control ED list, and
* enable control transfers.
*
* Input Parameters:
* rhpndx - Root hub port index.
@ -1609,14 +1610,15 @@ static int sam_ep0enqueue(struct sam_rhport_s *rhport)
* list processing.
*
* Input Parameters:
* rhpndx - Root hub port index.
* ep0 - The control endpoint to be released. May be the control endpoint for
* an attached hub.
*
* Returned Values:
* None
*
*******************************************************************************/
static void sam_ep0dequeue(struct sam_rhport_s *rhport)
static void sam_ep0dequeue(struct sam_eplist_s *ep0)
{
struct sam_ed_s *edctrl;
struct sam_ed_s *curred;
@ -1627,8 +1629,7 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
uintptr_t physcurr;
uint32_t regval;
DEBUGASSERT(rhport && rhport->ep0init && rhport->ep0.ed != NULL &&
rhport->ep0.tail != NULL);
DEBUGASSERT(ep0->ed != NULL && ep0->tail != NULL);
/* ControlListEnable. This bit is cleared to disable the processing of the
* Control list. We should never modify the control list while CLE is set.
@ -1643,7 +1644,7 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
* precedessor).
*/
edctrl = rhport->ep0.ed;
edctrl = ep0->ed;
physcurr = sam_getreg(SAM_USBHOST_CTRLHEADED);
for (curred = (struct sam_ed_s *)sam_virtramaddr(physcurr),
@ -1692,7 +1693,7 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
/* Release any TDs that may still be attached to the ED. */
tdtail = rhport->ep0.tail;
tdtail = ep0->tail;
physcurr = edctrl->hw.headp;
for (currtd = (struct sam_gtd_s *)sam_virtramaddr(physcurr);
@ -1708,8 +1709,8 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
sam_tdfree(tdtail);
sam_edfree(edctrl);
rhport->ep0.ed = NULL;
rhport->ep0.tail = NULL;
ep0->ed = NULL;
ep0->tail = NULL;
}
/*******************************************************************************
@ -2408,7 +2409,7 @@ static int sam_rh_enumerate(struct usbhost_connection_s *conn,
return -ENODEV;
}
/* Add EP0 to the control list */
/* Add root hub EP0 to the control list */
if (!rhport->ep0init)
{
@ -3659,6 +3660,8 @@ static int sam_connect(struct usbhost_driver_s *drvr,
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* hport - The port from which the device is being disconnected. Might be a port
* on a hub.
*
* Returned Values:
* None
@ -3669,19 +3672,29 @@ static int sam_connect(struct usbhost_driver_s *drvr,
*
*******************************************************************************/
static void sam_disconnect(struct usbhost_driver_s *drvr)
static void sam_disconnect(struct usbhost_driver_s *drvr,
struct usbhost_hubport_s *hport)
{
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
DEBUGASSERT(rhport);
struct sam_eplist_s *ep0;
DEBUGASSERT(rhport != NULL && hport != NULL && hport->ep0);
ep0 = (struct sam_eplist_s *)hport->ep0;
/* Remove the disconnected port from the control list */
sam_ep0dequeue(rhport);
rhport->ep0init = false;
sam_ep0dequeue(ep0);
/* Unbind the class */
/* Did we just dequeue EP0 from a hoot hub port? */
rhport->hport.hport.devclass = NULL;
if (ROOTHUB(hport))
{
rhport->ep0init = false;
}
/* Unbind the class from the port */
hport->devclass = NULL;
}
/*******************************************************************************

View File

@ -454,7 +454,8 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport,
bool connected);
#endif
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr);
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport);
/* Initialization **************************************************************/
@ -4684,6 +4685,8 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* hport - The port from which the device is being disconnected. Might be a port
* on a hub.
*
* Returned Values:
* None
@ -4694,12 +4697,13 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
*
*******************************************************************************/
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr)
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport)
{
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
DEBUGASSERT(priv);
DEBUGASSERT(priv != NULL && hport != NULL);
priv->rhport.hport.devclass = NULL;
hport->devclass = NULL;
}
/*******************************************************************************

View File

@ -454,7 +454,8 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport,
bool connected);
#endif
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr);
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport);
/* Initialization **************************************************************/
@ -4684,6 +4685,8 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* hport - The port from which the device is being disconnected. Might be a port
* on a hub.
*
* Returned Values:
* None
@ -4694,12 +4697,13 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
*
*******************************************************************************/
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr)
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport)
{
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
DEBUGASSERT(priv);
DEBUGASSERT(priv != NULL && hport != NULL);
priv->rhport.hport.devclass = NULL;
hport->devclass = NULL;
}
/*******************************************************************************

View File

@ -184,7 +184,7 @@ static int ehci_waiter(int argc, char *argv[])
* Name: sam_usbinitialize
*
* Description:
* Called from sam_usbinitialize very early in inialization to setup USB-related
* Called from sam_usbinitialize very early in initialization to setup USB-related
* GPIO pins for the SAMA5D4-EK board.
*
* USB Ports

View File

@ -798,7 +798,7 @@ static void usbhost_destroy(FAR void *arg)
/* Disconnect the USB host device */
DRVR_DISCONNECT(hport->drvr);
DRVR_DISCONNECT(hport->drvr, hport);
/* Free the function address assigned to this device */

View File

@ -654,7 +654,7 @@ static void usbhost_destroy(FAR void *arg)
/* Disconnect the USB host device */
DRVR_DISCONNECT(hport->drvr);
DRVR_DISCONNECT(hport->drvr, hport);
/* Free the function address assigned to this device */

View File

@ -1074,13 +1074,17 @@ static void usbhost_disconnect_event(FAR void *arg)
usbhost_hport_deactivate(child);
}
/* Deactivate the parent hub port (unless it is the root hub port) */
usbhost_hport_deactivate(hport);
/* Destroy the semaphores */
sem_destroy(&priv->exclsem);
/* Deactivate the parent hub port (unless it is the root hub port) */
/* Disconnect the USB host device */
usbhost_hport_deactivate(hport);
DRVR_DISCONNECT(hport->drvr, hport);
/* Free the class instance */

View File

@ -377,7 +377,7 @@ static void usbhost_destroy(FAR void *arg)
/* Disconnect the USB host device */
DRVR_DISCONNECT(drvr);
DRVR_DISCONNECT(drvr, hport);
/* And free the class instance. Hmmm.. this may execute on the worker
* thread and the work structure is part of what is getting freed. That

View File

@ -952,7 +952,7 @@ static void usbhost_destroy(FAR void *arg)
/* Disconnect the USB host device */
DRVR_DISCONNECT(hport->drvr);
DRVR_DISCONNECT(hport->drvr, hport);
/* Free the function address assigned to this device */

View File

@ -579,6 +579,8 @@
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* hport - The port from which the device is being disconnected. Might be a port
* on a hub.
*
* Returned Values:
* None
@ -588,7 +590,7 @@
*
************************************************************************************/
#define DRVR_DISCONNECT(drvr) ((drvr)->disconnect(drvr))
#define DRVR_DISCONNECT(drvr, hport) ((drvr)->disconnect(drvr, hport))
/************************************************************************************
* Public Types
@ -873,7 +875,8 @@ struct usbhost_driver_s
* (until a new instance is received from the create() method).
*/
void (*disconnect)(FAR struct usbhost_driver_s *drvr);
void (*disconnect)(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport);
};
/************************************************************************************