Commit c461db2ad66b153b0b54450e2241bfe086b5314f

Authored by Eric Lee
1 parent d6c21f4ebb

Fix MUSB DMA Bug

Showing 6 changed files with 40 additions and 68 deletions Side-by-side Diff

drivers/dma/cppi41.c
... ... @@ -86,6 +86,9 @@
86 86  
87 87 #define USBSS_IRQ_PD_COMP (1 << 2)
88 88  
  89 +/* Packet Descriptor */
  90 +#define PD2_ZERO_LENGTH (1 << 19)
  91 +
89 92 struct cppi41_channel {
90 93 struct dma_chan chan;
91 94 struct dma_async_tx_descriptor txd;
... ... @@ -307,8 +310,7 @@
307 310 __iormb();
308 311  
309 312 while (val) {
310   - u32 desc;
311   -
  313 + u32 desc, len;
312 314 q_num = __fls(val);
313 315 val &= ~(1 << q_num);
314 316 q_num += 32 * i;
... ... @@ -322,6 +324,12 @@
322 324 c->residue = pd_trans_len(c->desc->pd6) -
323 325 pd_trans_len(c->desc->pd0);
324 326  
  327 + if (c->desc->pd2 & PD2_ZERO_LENGTH)
  328 + len = 0;
  329 + else
  330 + len = pd_trans_len(c->desc->pd0);
  331 +
  332 + c->residue = pd_trans_len(c->desc->pd6) - len;
325 333 dma_cookie_complete(&c->txd);
326 334 c->txd.callback(c->txd.callback_param);
327 335 }
drivers/usb/musb/musb_core.c
... ... @@ -1541,7 +1541,7 @@
1541 1541 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
1542 1542  
1543 1543 dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",
1544   - (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
  1544 + is_host_active(musb) ? "host" : "peripheral",
1545 1545 musb->int_usb, musb->int_tx, musb->int_rx);
1546 1546  
1547 1547 /* the core can interrupt us for multiple reasons; docs have
... ... @@ -1555,7 +1555,7 @@
1555 1555  
1556 1556 /* handle endpoint 0 first */
1557 1557 if (musb->int_tx & 1) {
1558   - if (devctl & MUSB_DEVCTL_HM)
  1558 + if (is_host_active(musb))
1559 1559 retval |= musb_h_ep0_irq(musb);
1560 1560 else
1561 1561 retval |= musb_g_ep0_irq(musb);
... ... @@ -1569,7 +1569,7 @@
1569 1569 /* musb_ep_select(musb->mregs, ep_num); */
1570 1570 /* REVISIT just retval = ep->rx_irq(...) */
1571 1571 retval = IRQ_HANDLED;
1572   - if (devctl & MUSB_DEVCTL_HM)
  1572 + if (is_host_active(musb))
1573 1573 musb_host_rx(musb, ep_num);
1574 1574 else
1575 1575 musb_g_rx(musb, ep_num);
... ... @@ -1587,7 +1587,7 @@
1587 1587 /* musb_ep_select(musb->mregs, ep_num); */
1588 1588 /* REVISIT just retval |= ep->tx_irq(...) */
1589 1589 retval = IRQ_HANDLED;
1590   - if (devctl & MUSB_DEVCTL_HM)
  1590 + if (is_host_active(musb))
1591 1591 musb_host_tx(musb, ep_num);
1592 1592 else
1593 1593 musb_g_tx(musb, ep_num);
1594 1594  
... ... @@ -1618,15 +1618,13 @@
1618 1618  
1619 1619 void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
1620 1620 {
1621   - u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
1622   -
1623 1621 /* called with controller lock already held */
1624 1622  
1625 1623 if (!epnum) {
1626 1624 #ifndef CONFIG_USB_TUSB_OMAP_DMA
1627 1625 if (!is_cppi_enabled()) {
1628 1626 /* endpoint 0 */
1629   - if (devctl & MUSB_DEVCTL_HM)
  1627 + if (is_host_active(musb))
1630 1628 musb_h_ep0_irq(musb);
1631 1629 else
1632 1630 musb_g_ep0_irq(musb);
1633 1631  
... ... @@ -1635,13 +1633,13 @@
1635 1633 } else {
1636 1634 /* endpoints 1..15 */
1637 1635 if (transmit) {
1638   - if (devctl & MUSB_DEVCTL_HM)
  1636 + if (is_host_active(musb))
1639 1637 musb_host_tx(musb, epnum);
1640 1638 else
1641 1639 musb_g_tx(musb, epnum);
1642 1640 } else {
1643 1641 /* receive */
1644   - if (devctl & MUSB_DEVCTL_HM)
  1642 + if (is_host_active(musb))
1645 1643 musb_host_rx(musb, epnum);
1646 1644 else
1647 1645 musb_g_rx(musb, epnum);
drivers/usb/musb/musb_cppi41.c
... ... @@ -39,7 +39,6 @@
39 39 u32 transferred;
40 40 u32 packet_sz;
41 41 struct list_head tx_check;
42   - struct work_struct dma_completion;
43 42 };
44 43  
45 44 #define MUSB_DMA_NUM_CHANNELS 15
46 45  
47 46  
... ... @@ -74,15 +73,18 @@
74 73  
75 74 static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
76 75 {
  76 + struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
  77 + struct musb *musb = hw_ep->musb;
77 78 u16 csr;
78 79 u8 toggle;
79 80  
80 81 if (cppi41_channel->is_tx)
81 82 return;
82   - if (!is_host_active(cppi41_channel->controller->musb))
  83 + if (!is_host_active(musb))
83 84 return;
84 85  
85   - csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
  86 + musb_ep_select(musb->mregs, hw_ep->epnum);
  87 + csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
86 88 toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
87 89  
88 90 /*
89 91  
... ... @@ -107,24 +109,13 @@
107 109 void __iomem *epio = musb->endpoints[epnum].regs;
108 110 u16 csr;
109 111  
  112 + musb_ep_select(musb->mregs, hw_ep->epnum);
110 113 csr = musb_readw(epio, MUSB_TXCSR);
111 114 if (csr & MUSB_TXCSR_TXPKTRDY)
112 115 return false;
113 116 return true;
114 117 }
115 118  
116   -static bool is_isoc(struct musb_hw_ep *hw_ep, bool in)
117   -{
118   - if (in && hw_ep->in_qh) {
119   - if (hw_ep->in_qh->type == USB_ENDPOINT_XFER_ISOC)
120   - return true;
121   - } else if (hw_ep->out_qh) {
122   - if (hw_ep->out_qh->type == USB_ENDPOINT_XFER_ISOC)
123   - return true;
124   - }
125   - return false;
126   -}
127   -
128 119 static void cppi41_dma_callback(void *private_data);
129 120  
130 121 static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
... ... @@ -139,6 +130,7 @@
139 130 cppi41_channel->channel.actual_len =
140 131 cppi41_channel->transferred;
141 132 cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
  133 + cppi41_channel->channel.rx_packet_done = true;
142 134 musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
143 135 } else {
144 136 /* next iteration, reload */
... ... @@ -172,6 +164,7 @@
172 164 dma_async_issue_pending(dc);
173 165  
174 166 if (!cppi41_channel->is_tx) {
  167 + musb_ep_select(musb->mregs, hw_ep->epnum);
175 168 csr = musb_readw(epio, MUSB_RXCSR);
176 169 csr |= MUSB_RXCSR_H_REQPKT;
177 170 musb_writew(epio, MUSB_RXCSR, csr);
... ... @@ -179,32 +172,6 @@
179 172 }
180 173 }
181 174  
182   -static void cppi_trans_done_work(struct work_struct *work)
183   -{
184   - unsigned long flags;
185   - struct cppi41_dma_channel *cppi41_channel =
186   - container_of(work, struct cppi41_dma_channel, dma_completion);
187   - struct cppi41_dma_controller *controller = cppi41_channel->controller;
188   - struct musb *musb = controller->musb;
189   - struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
190   - bool empty;
191   -
192   - if (!cppi41_channel->is_tx && is_isoc(hw_ep, 1)) {
193   - spin_lock_irqsave(&musb->lock, flags);
194   - cppi41_trans_done(cppi41_channel);
195   - spin_unlock_irqrestore(&musb->lock, flags);
196   - } else {
197   - empty = musb_is_tx_fifo_empty(hw_ep);
198   - if (empty) {
199   - spin_lock_irqsave(&musb->lock, flags);
200   - cppi41_trans_done(cppi41_channel);
201   - spin_unlock_irqrestore(&musb->lock, flags);
202   - } else {
203   - schedule_work(&cppi41_channel->dma_completion);
204   - }
205   - }
206   -}
207   -
208 175 static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
209 176 {
210 177 struct cppi41_dma_controller *controller;
... ... @@ -268,14 +235,6 @@
268 235 transferred < cppi41_channel->packet_sz)
269 236 cppi41_channel->prog_len = 0;
270 237  
271   - if (!cppi41_channel->is_tx) {
272   - if (is_isoc(hw_ep, 1))
273   - schedule_work(&cppi41_channel->dma_completion);
274   - else
275   - cppi41_trans_done(cppi41_channel);
276   - goto out;
277   - }
278   -
279 238 empty = musb_is_tx_fifo_empty(hw_ep);
280 239 if (empty) {
281 240 cppi41_trans_done(cppi41_channel);
... ... @@ -312,10 +271,6 @@
312 271 goto out;
313 272 }
314 273 }
315   - if (is_isoc(hw_ep, 0)) {
316   - schedule_work(&cppi41_channel->dma_completion);
317   - goto out;
318   - }
319 274 list_add_tail(&cppi41_channel->tx_check,
320 275 &controller->early_tx_list);
321 276 if (!hrtimer_is_queued(&controller->early_tx)) {
... ... @@ -452,6 +407,7 @@
452 407 dma_desc->callback = cppi41_dma_callback;
453 408 dma_desc->callback_param = channel;
454 409 cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
  410 + cppi41_channel->channel.rx_packet_done = false;
455 411  
456 412 save_rx_toggle(cppi41_channel);
457 413 dma_async_issue_pending(dc);
... ... @@ -674,8 +630,7 @@
674 630 cppi41_channel->port_num = port;
675 631 cppi41_channel->is_tx = is_tx;
676 632 INIT_LIST_HEAD(&cppi41_channel->tx_check);
677   - INIT_WORK(&cppi41_channel->dma_completion,
678   - cppi_trans_done_work);
  633 +
679 634 musb_dma = &cppi41_channel->channel;
680 635 musb_dma->private_data = cppi41_channel;
681 636 musb_dma->status = MUSB_DMA_STATUS_FREE;
drivers/usb/musb/musb_dma.h
... ... @@ -129,6 +129,7 @@
129 129 size_t actual_len;
130 130 enum dma_channel_status status;
131 131 bool desired_mode;
  132 + bool rx_packet_done;
132 133 };
133 134  
134 135 /*
drivers/usb/musb/musb_host.c
... ... @@ -121,7 +121,7 @@
121 121 if (csr != lastcsr)
122 122 dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
123 123 lastcsr = csr;
124   - csr |= MUSB_TXCSR_FLUSHFIFO;
  124 + csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY;
125 125 musb_writew(epio, MUSB_TXCSR, csr);
126 126 csr = musb_readw(epio, MUSB_TXCSR);
127 127 if (WARN(retries-- < 1,
... ... @@ -1739,7 +1739,8 @@
1739 1739 /* done if urb buffer is full or short packet is recd */
1740 1740 done = (urb->actual_length + xfer_len >=
1741 1741 urb->transfer_buffer_length
1742   - || dma->actual_len < qh->maxpacket);
  1742 + || dma->actual_len < qh->maxpacket
  1743 + || dma->rx_packet_done);
1743 1744 }
1744 1745  
1745 1746 /* send IN token for next packet, without AUTOREQ */
drivers/usb/phy/phy-am335x-control.c
... ... @@ -3,6 +3,7 @@
3 3 #include <linux/err.h>
4 4 #include <linux/of.h>
5 5 #include <linux/io.h>
  6 +#include <linux/delay.h>
6 7  
7 8 struct phy_control {
8 9 void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
... ... @@ -90,6 +91,14 @@
90 91 }
91 92  
92 93 writel(val, usb_ctrl->phy_reg + reg);
  94 +
  95 + /*
  96 + * Give the PHY ~1ms to complete the power up operation.
  97 + * Tests have shown unstable behaviour if other USB PHY related
  98 + * registers are written too shortly after such a transition.
  99 + */
  100 + if (on)
  101 + mdelay(1);
93 102 }
94 103  
95 104 static const struct phy_control ctrl_am335x = {