linux-omap 2.6.27: add patch for musb RX TX bug
authorKoen Kooi <koen@openembedded.org>
Sun, 11 Jan 2009 10:25:32 +0000 (11:25 +0100)
committerKoen Kooi <koen@openembedded.org>
Sun, 11 Jan 2009 10:26:07 +0000 (11:26 +0100)
packages/linux/linux-omap-2.6.27/beagleboard/defconfig
packages/linux/linux-omap-2.6.27/musb-rxtx.patch [new file with mode: 0644]
packages/linux/linux-omap_2.6.27.bb

index afcd728..7b22946 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.27-omap1
-# Tue Jan  6 10:27:42 2009
+# Sun Jan 11 11:22:58 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -1261,38 +1261,6 @@ CONFIG_DVB_ISL6421=m
 #
 # Graphics support
 #
-CONFIG_PVR=m
-CONFIG_PVR_TRANSFER_QUEUE=y
-CONFIG_PVR_SUPPORT_SRVINIT=y
-CONFIG_PVR_SUPPORT_SECURE_HANDLES=y
-CONFIG_PVR_SERVICES4=y
-CONFIG_PVR_SGXCORE_530=y
-CONFIG_PVR_SGX_CORE_REV_103=y
-CONFIG_PVR_PVR2D_ALT_2DHW=y
-CONFIG_PVR_SYSTEM_OMAP3430=y
-# CONFIG_PVR_SYSTEM_NO_HARDWARE is not set
-CONFIG_PVR_BUFFERCLASS_EXAMPLE=y
-CONFIG_PVR_USE_PTHREADS=y
-CONFIG_PVR_SUPPORT_SGX_EVENT_OBJECT=y
-CONFIG_PVR_SYS_USING_INTERRUPTS=y
-CONFIG_PVR_SUPPORT_HW_RECOVERY=y
-CONFIG_PVR_SUPPORT_ACTIVE_POWER_MANAGEMENT=y
-# CONFIG_PVR_BUILD_RELEASE is not set
-CONFIG_PVR_BUILD_DEBUG=y
-# CONFIG_PVR_BUILD_TIMING is not set
-CONFIG_PVR_DEBUG_LINUX_MEMORY_ALLOCATIONS=y
-CONFIG_PVR_DEBUG_LINUX_MEM_AREAS=y
-CONFIG_PVR_DEBUG_LINUX_MMAP_AREAS=y
-# CONFIG_PVR_DEBUG_LINUX_XML_PROC_FILES is not set
-# CONFIG_PVR_DEBUG_LINUX_SLAB_ALLOCATIONS is not set
-CONFIG_PVR_DEBUG_BRIDGE_KM=y
-# CONFIG_PVR_DEBUG_TRACE_BRIDGE_KM is not set
-CONFIG_PVR_DEBUG_BEIDGE_KM_DISPATCH_TABLE=y
-CONFIG_PVR_SUPPORT_SGX1=y
-# CONFIG_DRM_VER_ORIG is not set
-CONFIG_DRM_VER_TUNGSTEN=y
-CONFIG_DRM_TUNGSTEN=y
-CONFIG_DRM_TUNGSTEN_PVR2D=m
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
@@ -1445,6 +1413,7 @@ CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_HDRC_HCD=y
 # CONFIG_MUSB_PIO_ONLY is not set
 CONFIG_USB_INVENTRA_DMA=y
+CONFIG_MUSB_USE_SYSTEM_DMA_RX=y
 # CONFIG_USB_TI_CPPI_DMA is not set
 # CONFIG_USB_MUSB_DEBUG is not set
 
diff --git a/packages/linux/linux-omap-2.6.27/musb-rxtx.patch b/packages/linux/linux-omap-2.6.27/musb-rxtx.patch
new file mode 100644 (file)
index 0000000..7908909
--- /dev/null
@@ -0,0 +1,283 @@
+MUSB: Workaround for simultaneous TX and RX usage
+
+MUSB RTL V1.4 has a hardware issue which results in a DMA controller
+hang when TX and RX DMA channels are simultaneously enabled. This
+affects at least OMAP2430 and OMAP34XX.
+
+Since RX transfers are in Mode 0 and anyway result in one DMA interrupt
+per packet, we can use System DMA to unload the RX fifos. MUSB DMA can
+be used for all TX channels as before.
+
+Tested with full-duplex TX and RX transfers using g_ether. Runs for 24
+hours without a hang. Without this patch, the hang occurs within minutes.
+
+This issue was first reported by Jon Hunter on [1]
+
+[1] http://marc.info/?l=linux-omap&m=119634480534453&w=2
+
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+---
+Patch based on the linux-omap tree. I believe the tabs-to-spaces issue
+has been resolved now, but this is the first patch I'm sending out to the
+list after that.
+
+Suggestions welcome for removing the 2 #ifdefs below. One suggestion was to
+use a module parameter to decide whether to use system dma or mentor dma.
+
+Patch updated with a few ifdefs removed and one compilation break resolved.
+
+ drivers/usb/musb/Kconfig     |    8 ++
+ drivers/usb/musb/musbhsdma.c |  163 +++++++++++++++++++++++++++++++++++--------
+ 2 files changed, 142 insertions(+), 29 deletions(-)
+
+Index: linux-omap-2.6/drivers/usb/musb/musbhsdma.c
+===================================================================
+--- linux-omap-2.6.orig/drivers/usb/musb/musbhsdma.c   2008-07-28 10:54:37.000000000 +0530
++++ linux-omap-2.6/drivers/usb/musb/musbhsdma.c        2008-08-13 11:58:26.272902373 +0530
+@@ -34,6 +34,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
+ #include "musb_core.h"
++#include <mach/dma.h>
+ #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+ #include "omap2430.h"
+@@ -64,6 +65,9 @@
+ #define MUSB_HSDMA_CHANNELS           8
++#define MUSB_FIFO_ADDRESS(epnum)      \
++      ((unsigned long) (OMAP_HSOTG_BASE + MUSB_FIFO_OFFSET(epnum)))
++
+ struct musb_dma_controller;
+ struct musb_dma_channel {
+@@ -75,6 +79,8 @@ struct musb_dma_channel {
+       u8                              bIndex;
+       u8                              epnum;
+       u8                              transmit;
++
++      int                             sysdma_channel;
+ };
+ struct musb_dma_controller {
+@@ -93,6 +99,42 @@ static int dma_controller_start(struct d
+       return 0;
+ }
++#ifdef CONFIG_MUSB_USE_SYSTEM_DMA_RX
++static void musb_sysdma_completion(int lch, u16 ch_status, void *data)
++{
++      u32 dwAddress;
++      unsigned long flags;
++
++      struct dma_channel *pChannel;
++
++      struct musb_dma_channel *pImplChannel =
++                                      (struct musb_dma_channel *) data;
++      struct musb_dma_controller *controller = pImplChannel->controller;
++      struct musb *musb = controller->pDmaPrivate;
++      pChannel = &pImplChannel->Channel;
++
++      DBG(2, "lch = 0x%d, ch_status = 0x%x\n", lch, ch_status);
++      spin_lock_irqsave(&musb->lock, flags);
++
++      dwAddress = (u32) omap_get_dma_dst_pos(pImplChannel->sysdma_channel);
++      pChannel->actual_len = dwAddress - pImplChannel->dwStartAddress;
++
++      DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n",
++              pChannel, pImplChannel->dwStartAddress, dwAddress,
++              pChannel->actual_len, pImplChannel->len,
++              (pChannel->actual_len < pImplChannel->len) ?
++              "=> reconfig 0": "=> complete");
++
++      pChannel->status = MUSB_DMA_STATUS_FREE;
++      musb_dma_completion(musb, pImplChannel->epnum, pImplChannel->transmit);
++
++      spin_unlock_irqrestore(&musb->lock, flags);
++      return;
++}
++#else
++#define musb_sysdma_completion NULL
++#endif
++
+ static void dma_channel_release(struct dma_channel *pChannel);
+ static int dma_controller_stop(struct dma_controller *c)
+@@ -144,6 +186,29 @@ static struct dma_channel *dma_channel_a
+                       /* Tx => mode 1; Rx => mode 0 */
+                       pChannel->desired_mode = transmit;
+                       pChannel->actual_len = 0;
++                      pImplChannel->sysdma_channel = -1;
++
++#ifdef CONFIG_MUSB_USE_SYSTEM_DMA_RX
++                      if (!transmit) {
++                              int ret;
++                              ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE,
++                                      "MUSB SysDMA", musb_sysdma_completion,
++                                      (void *) pImplChannel,
++                                      &(pImplChannel->sysdma_channel));
++
++                              if (ret) {
++                                      printk(KERN_ERR "request_dma failed:"
++                                                      " %d\n", ret);
++                                      controller->bmUsedChannels &=
++                                                              ~(1 << bBit);
++                                      pChannel->status =
++                                                      MUSB_DMA_STATUS_UNKNOWN;
++                                      pImplChannel->sysdma_channel = -1;
++                                      pChannel = NULL;
++                              }
++                      }
++#endif
++
+                       break;
+               }
+       }
+@@ -163,6 +228,12 @@ static void dma_channel_release(struct d
+               ~(1 << pImplChannel->bIndex);
+       pChannel->status = MUSB_DMA_STATUS_UNKNOWN;
++
++      if (pImplChannel->sysdma_channel != -1) {
++              omap_stop_dma(pImplChannel->sysdma_channel);
++              omap_free_dma(pImplChannel->sysdma_channel);
++              pImplChannel->sysdma_channel = -1;
++      }
+ }
+ static void configure_channel(struct dma_channel *pChannel,
+@@ -179,41 +250,69 @@ static void configure_channel(struct dma
+       DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n",
+                       pChannel, packet_sz, dma_addr, len, mode);
+-      if (mode) {
+-              csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
+-              BUG_ON(len < packet_sz);
++      if (pImplChannel->sysdma_channel != -1) {
++      /* System DMA */
++      /* RX: set src = FIFO */
++
++              omap_set_dma_transfer_params(pImplChannel->sysdma_channel,
++                                      OMAP_DMA_DATA_TYPE_S8,
++                                      len, 1, /* One frame */
++                                      OMAP_DMA_SYNC_ELEMENT,
++                                      OMAP24XX_DMA_NO_DEVICE,
++                                      0); /* Src Sync */
++
++              omap_set_dma_src_params(pImplChannel->sysdma_channel, 0,
++                                      OMAP_DMA_AMODE_CONSTANT,
++                                      MUSB_FIFO_ADDRESS(pImplChannel->epnum),
++                                      0, 0);
++
++              omap_set_dma_dest_params(pImplChannel->sysdma_channel, 0,
++                                      OMAP_DMA_AMODE_POST_INC, dma_addr,
++                                      0, 0);
++
++              omap_set_dma_dest_data_pack(pImplChannel->sysdma_channel, 1);
++              omap_set_dma_dest_burst_mode(pImplChannel->sysdma_channel,
++                                      OMAP_DMA_DATA_BURST_16);
++
++              omap_start_dma(pImplChannel->sysdma_channel);
++
++      } else { /* Mentor DMA */
++              if (mode) {
++                      csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
++                      BUG_ON(len < packet_sz);
+-              if (packet_sz >= 64) {
+-                      csr |= MUSB_HSDMA_BURSTMODE_INCR16
++                      if (packet_sz >= 64) {
++                              csr |= MUSB_HSDMA_BURSTMODE_INCR16
+                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
+-              } else if (packet_sz >= 32) {
+-                      csr |= MUSB_HSDMA_BURSTMODE_INCR8
++                      } else if (packet_sz >= 32) {
++                              csr |= MUSB_HSDMA_BURSTMODE_INCR8
+                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
+-              } else if (packet_sz >= 16) {
+-                      csr |= MUSB_HSDMA_BURSTMODE_INCR4
++                      } else if (packet_sz >= 16) {
++                              csr |= MUSB_HSDMA_BURSTMODE_INCR4
+                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
++                      }
+               }
+-      }
+-      csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
+-              | (1 << MUSB_HSDMA_ENABLE_SHIFT)
+-              | (1 << MUSB_HSDMA_IRQENABLE_SHIFT)
+-              | (pImplChannel->transmit
+-                              ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT)
+-                              : 0);
+-
+-      /* address/count */
+-      musb_writel(mbase,
+-              MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS),
+-              dma_addr);
+-      musb_writel(mbase,
+-              MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT),
+-              len);
+-
+-      /* control (this should start things) */
+-      musb_writew(mbase,
+-              MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL),
+-              csr);
++              csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
++                      | (1 << MUSB_HSDMA_ENABLE_SHIFT)
++                      | (1 << MUSB_HSDMA_IRQENABLE_SHIFT)
++                      | (pImplChannel->transmit
++                                      ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT)
++                                      : 0);
++
++              /* address/count */
++              musb_writel(mbase,
++                      MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS),
++                      dma_addr);
++              musb_writel(mbase,
++                      MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT),
++                      len);
++
++              /* control (this should start things) */
++              musb_writew(mbase,
++                      MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL),
++                      csr);
++      } /* Mentor DMA */
+ }
+ static int dma_channel_program(struct dma_channel *pChannel,
+@@ -265,6 +364,12 @@ static int dma_channel_abort(struct dma_
+                               MUSB_EP_OFFSET(pImplChannel->epnum, MUSB_TXCSR),
+                               csr);
+               } else {
++                      if (pImplChannel->sysdma_channel != -1) {
++                              omap_stop_dma(pImplChannel->sysdma_channel);
++                              omap_free_dma(pImplChannel->sysdma_channel);
++                              pImplChannel->sysdma_channel = -1;
++                      }
++
+                       csr = musb_readw(mbase,
+                               MUSB_EP_OFFSET(pImplChannel->epnum, MUSB_RXCSR));
+                       csr &= ~(MUSB_RXCSR_AUTOCLEAR |
+Index: linux-omap-2.6/drivers/usb/musb/Kconfig
+===================================================================
+--- linux-omap-2.6.orig/drivers/usb/musb/Kconfig       2008-07-28 10:54:37.000000000 +0530
++++ linux-omap-2.6/drivers/usb/musb/Kconfig    2008-08-12 13:18:34.000000000 +0530
+@@ -150,6 +150,14 @@ config USB_INVENTRA_DMA
+       help
+         Enable DMA transfers using Mentor's engine.
++config MUSB_USE_SYSTEM_DMA_RX
++      bool 'Use System DMA for RX endpoints'
++      depends on USB_MUSB_HDRC && USB_INVENTRA_DMA
++      help
++        MUSB RTL version 1.4 has a hardware issue when TX and RX DMA
++        channels are simultaneously enabled. To work around this issue,
++        you can choose to use System DMA for RX channels.
++
+ config USB_TI_CPPI_DMA
+       bool
+       depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at  http://vger.kernel.org/majordomo-info.html
index 6aed140..a5f5cad 100644 (file)
@@ -6,7 +6,7 @@ KERNEL_IMAGETYPE = "uImage"
 COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm"
 
 SRCREV = "2a3408be17f287fdb5809c9b6c68e7ad96d25b74"
-PR = "r11"
+PR = "r12"
 
 SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git;protocol=git \
           file://defconfig"
@@ -39,6 +39,7 @@ SRC_URI_append = " \
 #           file://openvz/openvz-2.6.27.diff;patch=1 \
            file://sitecomwl168-support.diff;patch=1 \
            file://nand.patch;patch=1 \
+           file://musb-rxtx.patch;patch=1 \
 "