Felipe: Can you check the reasoning here? I don't understand how an OTG event could cause dwc3 to remove the shared (SuperSpeed) hcd and then re-instantiate it before removing the primary (HS-FS-LS) hcd, which is what this diagram seems to show. On Wed, 8 Jun 2016, Chung-Geol Kim wrote: > Thank you for clear understanding the problem that I faced. > When I tested with your below patch, it also works well. > The description has been modified as follows as you suggested. > > ================================================= > At *remove USB(3.0) Storage > sequence <1> --> <5> ((Problem Case)) > ================================================= > VOLD > ------------------------------------|------------ > (uevent) > ________|_________ > |<1> | > |dwc3_otg_sm_work | > |usb_put_hcd | > |peer_hcd(kref=2)| > |__________________| > ________|_________ > |<2> | > |New USB BUS #2 | > | | > |peer_hcd(kref=1)| > | | > --(Link)-bandXX_mutex| > | |__________________| > | > ___________________ | > |<3> | | > |dwc3_otg_sm_work | | > |usb_put_hcd | | > |primary_hcd(kref=1)| | > |___________________| | > _________|_________ | > |<4> | | > |New USB BUS #1 | | > |hcd_release | | > |primary_hcd(kref=0)| | > | | | > |bandXX_mutex(free) |<- > |___________________| > (( VOLD )) > ______|___________ > |<5> | > | SCSI | > |usb_put_hcd | > |peer_hcd(kref=0)| > |*hcd_release | > |bandXX_mutex(free*)|<- double free > |__________________| > > ================================================= As far as I can tell, the real problem occurs when the HS/FS/LS primary hcd is released before the SS shared hcd. The bandwidth_mutex gets deallocated when the primary hcd is released, even though the shared hcd still exists. Then when the shared hcd is released, it tries the deallocate the bandwidth_mutex a second time, because the code is written in such a way that it now thinks the shared hcd _is_ the primary. Is the patch below a good way to fix the problem? There doesn't _seem_ to be any harm in making this change. At least, I don't think it will confuse drivers any more than they are already. Thanks, Alan Stern Index: usb-4.x/drivers/usb/core/hcd.c =================================================================== --- usb-4.x.orig/drivers/usb/core/hcd.c +++ usb-4.x/drivers/usb/core/hcd.c @@ -2588,24 +2588,22 @@ EXPORT_SYMBOL_GPL(usb_create_hcd); * Don't deallocate the bandwidth_mutex until the last shared usb_hcd is * deallocated. * - * Make sure to only deallocate the bandwidth_mutex when the primary HCD is - * freed. When hcd_release() is called for either hcd in a peer set - * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to - * block new peering attempts + * Make sure to deallocate the bandwidth_mutex only when the last HCD is + * freed. When hcd_release() is called for either hcd in a peer set, + * invalidate the peer's ->shared_hcd and ->primary_hcd pointers. */ static void hcd_release(struct kref *kref) { struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); mutex_lock(&usb_port_peer_mutex); - if (usb_hcd_is_primary_hcd(hcd)) - kfree(hcd->bandwidth_mutex); if (hcd->shared_hcd) { struct usb_hcd *peer = hcd->shared_hcd; peer->shared_hcd = NULL; - if (peer->primary_hcd == hcd) - peer->primary_hcd = NULL; + peer->primary_hcd = NULL; + } else { + kfree(hcd->bandwidth_mutex); } mutex_unlock(&usb_port_peer_mutex); kfree(hcd); -- 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