Skip to content

Commit

Permalink
Merge tag 'fixes-for-v3.10-rc4' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/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.
  • Loading branch information
Greg Kroah-Hartman committed May 29, 2013
2 parents e4aa937 + ed74df1 commit 61d5b3d
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 16 deletions.
2 changes: 1 addition & 1 deletion drivers/usb/dwc3/dwc3-exynos.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/dwc3/dwc3-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
16 changes: 12 additions & 4 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
18 changes: 8 additions & 10 deletions drivers/usb/musb/musb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -1463,9 +1462,9 @@ void musb_host_tx(struct musb *musb, u8 epnum)
* 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");
Expand All @@ -1484,9 +1483,9 @@ void musb_host_tx(struct musb *musb, u8 epnum)

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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1913,8 +1911,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
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;
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/musb/musb_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 61d5b3d

Please sign in to comment.