mirror of
https://github.com/torvalds/linux.git
synced 2024-12-20 10:01:56 +00:00
usb: fixes for v3.10-rc4
Fix for a long standing bug where we would try to free resources which we never allocated for DWC3's physical endpoints 0 and 1. DWC3 also learned that when calling glue layer's ->remove() method, ordering of the teardown logic matters. This fixes a bug where we would try to act on bogus PHY resources. Lastly, MUSB learns about proper URB handling when the URB's buffer sits in highmen. In order to fix the bug, use_sg flag is moved down to the URB. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJRpQNDAAoJEIaOsuA1yqREfuMQAKm1NMFhbj//6+MrPinNuC7k WtWknx1gPGBZTts1OG7P86Tc+wPRYNk9eqIJbwV7SW9dUTtDn6b0AuyyWEN5GoFJ vc9N1uuzHyvLSpFGHIgLvV6cvwgnvnPmc5KTHQXh86xO2503QbgJU5ld1fndJDj6 dgfnf+s+i+fao1mR0kNSKI88ELDRZSIOxxugE8o05Mub6NQ8tMerwNCmqXMJDef9 2Q+4KVeX2SErzVZ9aE8aKHCii07Eiw8+1juOp3jS5ZCURAYTh16/ooamyyzLSHWZ yWv0ZBfu5UXDms03rwnYQU0gGuxP8tPc2/FkZfkw8DuH0MoS4XKYaHBGLhoIIDE8 y+wb/X80kyoNWx3jdZB/+eg81KAfOsvWs8k2pp9o7RvWivjeIyR2cs/EcBqd8kOS DzMDqNrCcF8hGZJl70TFDd2LP6bfEDGVzpsUI9u74gSFsCgaXwbFtppGh6oUOdT+ eonQp4PUtZBr56AR7rVtbOGrNDrpfU43n/ISULPHLDgdsRpEMk8CKv5/SISrERG8 Bjv9IhUyS4+yWYYjEx7zTA695JaGdpMcgL3RmxoYj0HcaSfXKJvIBwJEUMIGckbZ 3ByYksLGKJa255oLUGGQUa/7wwiiXuV+OvL5Ck22VPR385ayGDvCJ4z0kE9xdenq NIbjoxBz2jEIDZzkDqJC =oR45 -----END PGP SIGNATURE----- Merge tag 'fixes-for-v3.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus Felipe writes: usb: fixes for v3.10-rc4 Fix for a long standing bug where we would try to free resources which we never allocated for DWC3's physical endpoints 0 and 1. DWC3 also learned that when calling glue layer's ->remove() method, ordering of the teardown logic matters. This fixes a bug where we would try to act on bogus PHY resources. Lastly, MUSB learns about proper URB handling when the URB's buffer sits in highmen. In order to fix the bug, use_sg flag is moved down to the URB.
This commit is contained in:
commit
61d5b3d65c
@ -164,9 +164,9 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
|
||||
|
||||
device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
|
||||
platform_device_unregister(exynos->usb2_phy);
|
||||
platform_device_unregister(exynos->usb3_phy);
|
||||
device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
|
||||
|
||||
clk_disable_unprepare(exynos->clk);
|
||||
|
||||
|
@ -196,9 +196,9 @@ static void dwc3_pci_remove(struct pci_dev *pci)
|
||||
{
|
||||
struct dwc3_pci *glue = pci_get_drvdata(pci);
|
||||
|
||||
platform_device_unregister(glue->dwc3);
|
||||
platform_device_unregister(glue->usb2_phy);
|
||||
platform_device_unregister(glue->usb3_phy);
|
||||
platform_device_unregister(glue->dwc3);
|
||||
pci_set_drvdata(pci, NULL);
|
||||
pci_disable_device(pci);
|
||||
}
|
||||
|
@ -1706,11 +1706,19 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
|
||||
dep = dwc->eps[epnum];
|
||||
if (!dep)
|
||||
continue;
|
||||
|
||||
dwc3_free_trb_pool(dep);
|
||||
|
||||
if (epnum != 0 && epnum != 1)
|
||||
/*
|
||||
* Physical endpoints 0 and 1 are special; they form the
|
||||
* bi-directional USB endpoint 0.
|
||||
*
|
||||
* For those two physical endpoints, we don't allocate a TRB
|
||||
* pool nor do we add them the endpoints list. Due to that, we
|
||||
* shouldn't do these two operations otherwise we would end up
|
||||
* with all sorts of bugs when removing dwc3.ko.
|
||||
*/
|
||||
if (epnum != 0 && epnum != 1) {
|
||||
dwc3_free_trb_pool(dep);
|
||||
list_del(&dep->endpoint.ep_list);
|
||||
}
|
||||
|
||||
kfree(dep);
|
||||
}
|
||||
|
@ -1232,7 +1232,6 @@ void musb_host_tx(struct musb *musb, u8 epnum)
|
||||
void __iomem *mbase = musb->mregs;
|
||||
struct dma_channel *dma;
|
||||
bool transfer_pending = false;
|
||||
static bool use_sg;
|
||||
|
||||
musb_ep_select(mbase, epnum);
|
||||
tx_csr = musb_readw(epio, MUSB_TXCSR);
|
||||
@ -1463,9 +1462,9 @@ done:
|
||||
* NULL.
|
||||
*/
|
||||
if (!urb->transfer_buffer)
|
||||
use_sg = true;
|
||||
qh->use_sg = true;
|
||||
|
||||
if (use_sg) {
|
||||
if (qh->use_sg) {
|
||||
/* sg_miter_start is already done in musb_ep_program */
|
||||
if (!sg_miter_next(&qh->sg_miter)) {
|
||||
dev_err(musb->controller, "error: sg list empty\n");
|
||||
@ -1484,9 +1483,9 @@ done:
|
||||
|
||||
qh->segsize = length;
|
||||
|
||||
if (use_sg) {
|
||||
if (qh->use_sg) {
|
||||
if (offset + length >= urb->transfer_buffer_length)
|
||||
use_sg = false;
|
||||
qh->use_sg = false;
|
||||
}
|
||||
|
||||
musb_ep_select(mbase, epnum);
|
||||
@ -1552,7 +1551,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
||||
bool done = false;
|
||||
u32 status;
|
||||
struct dma_channel *dma;
|
||||
static bool use_sg;
|
||||
unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG;
|
||||
|
||||
musb_ep_select(mbase, epnum);
|
||||
@ -1878,12 +1876,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
||||
* NULL.
|
||||
*/
|
||||
if (!urb->transfer_buffer) {
|
||||
use_sg = true;
|
||||
qh->use_sg = true;
|
||||
sg_miter_start(&qh->sg_miter, urb->sg, 1,
|
||||
sg_flags);
|
||||
}
|
||||
|
||||
if (use_sg) {
|
||||
if (qh->use_sg) {
|
||||
if (!sg_miter_next(&qh->sg_miter)) {
|
||||
dev_err(musb->controller, "error: sg list empty\n");
|
||||
sg_miter_stop(&qh->sg_miter);
|
||||
@ -1913,8 +1911,8 @@ finish:
|
||||
urb->actual_length += xfer_len;
|
||||
qh->offset += xfer_len;
|
||||
if (done) {
|
||||
if (use_sg)
|
||||
use_sg = false;
|
||||
if (qh->use_sg)
|
||||
qh->use_sg = false;
|
||||
|
||||
if (urb->status == -EINPROGRESS)
|
||||
urb->status = status;
|
||||
|
@ -74,6 +74,7 @@ struct musb_qh {
|
||||
u16 frame; /* for periodic schedule */
|
||||
unsigned iso_idx; /* in urb->iso_frame_desc[] */
|
||||
struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */
|
||||
bool use_sg; /* to track urb using sglist */
|
||||
};
|
||||
|
||||
/* map from control or bulk queue head to the first qh on that ring */
|
||||
|
Loading…
Reference in New Issue
Block a user