Index: cx3110x-0.8.1/src/sm_drv_spi.c =================================================================== --- cx3110x-0.8.1.orig/src/sm_drv_spi.c 2008-04-28 18:30:22.000000000 -0300 +++ cx3110x-0.8.1/src/sm_drv_spi.c 2008-04-28 18:30:25.000000000 -0300 @@ -99,10 +99,10 @@ struct net_local *lp = dev->priv; uint32_t host_ints, host_ints_ack, target_ints; unsigned long timeout; - int result; + int result, pass = 1; DEBUG(DBG_BH, "w\n"); - +again: /* Here we wake the target up */ target_ints = SPI_TARGET_INT_WAKEUP; sm_spi_write(dev, SPI_ADRS_ARM_INTERRUPTS, @@ -117,6 +117,11 @@ if (time_after(jiffies, timeout)) { printk(KERN_WARNING "We haven't got a READY interrupt" " from WAKEUP. (firmware crashed?)\n"); + if (pass == 1) { + printk(KERN_WARNING "Try again...\n"); + pass = 2; + goto again; + } lp->device_state = DEVSTATE_DEAD; result = -1; goto exit; @@ -131,7 +136,10 @@ (unsigned char *)&host_ints_ack, sizeof(host_ints_ack)); result = 0; - + + if (pass == 2) { + printk(KERN_WARNING "succeeded!!!\n"); + } exit: DEBUG(DBG_BH, "W\n"); return result; @@ -150,49 +158,84 @@ return 0; } -static int sm_drv_spi_rx(struct net_device *dev) +static int sm_drv_spi_is_rx_frame_available(struct net_device *dev) +{ + uint32_t host_ints, host_ints_ack; + sm_spi_read(dev, SPI_ADRS_HOST_INTERRUPTS, (unsigned char *)&host_ints, sizeof(host_ints)); + if ((host_ints & SPI_HOST_INT_UPDATE) || (host_ints & SPI_HOST_INT_SW_UPDATE)) { + host_ints_ack = SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE; + sm_spi_write(dev, SPI_ADRS_HOST_INT_ACK, (unsigned char *)&host_ints_ack, sizeof(host_ints_ack)); + return 1; + } + return 0; +} + +static struct s_ic_msg * sm_drv_spi_alloc_frame_and_start_rx_transfer(struct net_device *dev) { struct net_local *lp = dev->priv; - struct spi_hif_local_data *hif_lp = HIF_LP(lp); struct s_sm_frame *frame; + unsigned short length; struct s_ic_msg *ic_msg; + + frame = frame_skb_alloc(dev, lp->sm_descr.mtu + lp->sm_descr.rxoffset, 0); + if (frame == NULL) return NULL; + + /* dummy read to flush SPI DMA controller bug */ + sm_spi_read(dev, SPI_ADRS_GEN_PURP_1, (unsigned char *)&length, sizeof(length)); + + sm_spi_read(dev, SPI_ADRS_DMA_DATA, (unsigned char *)&length, sizeof(length)); + DEBUG(DBG_BH, "%s: received frame len=%d\n", DRIVER_NAME, length); + + if (length > SPI_MAX_PACKET_SIZE) + length = SPI_MAX_PACKET_SIZE; + + sm_spi_dma_read_start(dev, SPI_ADRS_DMA_DATA, (unsigned char *) frame->data, length); + + ic_msg = FRAME_ICMSG(frame); + ic_msg->frame = frame; + ic_msg->channel = 0; + ic_msg->flags = 0; + ic_msg->length = length; + ic_msg->address = 0; + ic_msg->data = frame->data; + + return ic_msg; +} + +static int sm_drv_spi_rx(struct net_device *dev) +{ + struct net_local *lp = dev->priv; + struct spi_hif_local_data *hif_lp = HIF_LP(lp); + struct s_ic_msg *ic_msg, *ic_msg_next; int result, err; - unsigned short length; int32_t callb_mask = 0; - + err = sm_drv_spi_wakeup(dev); if (err < 0) { result = -1; goto exit; } - frame = frame_skb_alloc(dev, lp->sm_descr.mtu + lp->sm_descr.rxoffset, - 0); - if (frame != NULL) { - ic_msg = FRAME_ICMSG(frame); - ic_msg->frame = frame; - - /* dummy read to flush SPI DMA controller bug */ - sm_spi_read(dev, SPI_ADRS_GEN_PURP_1, (unsigned char *)&length, - sizeof(length)); - - sm_spi_read(dev, SPI_ADRS_DMA_DATA, (unsigned char *)&length, - sizeof(length)); - - DEBUG(DBG_BH, "%s: received frame len=%d\n", DRIVER_NAME, - length); - - if (length > SPI_MAX_PACKET_SIZE) - length = SPI_MAX_PACKET_SIZE; + ic_msg_next = sm_drv_spi_alloc_frame_and_start_rx_transfer(dev); + if (ic_msg_next == NULL) { + printk("Couldn't allocate RX frame\n"); + result = -1; + goto exit; + } - sm_spi_dma_read(dev, SPI_ADRS_DMA_DATA, - (unsigned char *) frame->data, length); - - ic_msg->channel = 0; - ic_msg->flags = 0; - ic_msg->length = length; - ic_msg->address = 0; - ic_msg->data = frame->data; + while (ic_msg_next) { + sm_spi_dma_read_wait_for_completion(); + ic_msg = ic_msg_next; + ic_msg_next = NULL; + + if (sm_drv_spi_is_rx_frame_available(dev)) { + ic_msg_next = sm_drv_spi_alloc_frame_and_start_rx_transfer(dev); + if (ic_msg_next == NULL) { + printk("Couldn't allocate RX frame\n"); + result = -1; + goto exit; + } + } hif_lp->spi_packets++; spin_lock_bh(&lp->sm_lock); @@ -207,13 +250,14 @@ DEBUG(DBG_IC,"Callback mask: %d\n", callb_mask); - if(callb_mask < 0) + if (callb_mask < 0) { printk(KERN_WARNING "prism_interconnect_message_handle" "returned error %d\n", callb_mask); - } else - printk("Couldn't allocate RX frame\n"); - - handle_sm_callback(dev, callb_mask); + result = -1; + goto exit; + } + handle_sm_callback(dev, callb_mask); + } result = 0; Index: cx3110x-0.8.1/src/sm_drv_spi_io.c =================================================================== --- cx3110x-0.8.1.orig/src/sm_drv_spi_io.c 2008-04-28 18:30:25.000000000 -0300 +++ cx3110x-0.8.1/src/sm_drv_spi_io.c 2008-04-28 18:35:59.000000000 -0300 @@ -120,7 +120,7 @@ } -int cx3110x_spi_dma_read(struct net_device *dev, unsigned long address, void * buffer, unsigned int length) +int cx3110x_spi_dma_read_start(struct net_device *dev, unsigned long address, void * buffer, unsigned int length) { SPI_CS_ON(); @@ -170,13 +170,22 @@ omap_start_dma(spi_dma.dma_rx_ch); omap_start_dma(spi_dma.dma_tx_ch); - /* Wait for reading to complete */ - while(!spi_dma.dma_rx_done) { - udelay(5); + return 0; +} + +int cx3110x_spi_dma_read_wait_for_completion() +{ + int wait_limit = 15000 * 5; + int wait_cycles = 0; + + /* Wait for DMA reading to complete */ + while ((!spi_dma.dma_rx_done || !spi_dma.dma_tx_done) && wait_cycles < wait_limit) { + wait_cycles++; + udelay(1); } - while(!spi_dma.dma_tx_done) { - udelay(5); + if (wait_cycles >= wait_limit) { + printk("McBSP read DMA timeout, spi_dma.dma_rx_done=%d, spi_dma.dma_tx_done=%d\n", spi_dma.dma_rx_done, spi_dma.dma_tx_done); } spi_dma.dma_rx_done = 0; @@ -184,11 +193,14 @@ SPI_CS_OFF(); - return 0; + return wait_cycles; } int cx3110x_spi_dma_write(struct net_device *dev, unsigned long address, void * buffer, unsigned int length) { + int wait_limit = 15000 * 5; + int wait_cycles = 0; + SPI_CS_ON(); omap_mcbsp_spi_master_xmit_word_poll(OMAP_MCBSP2, address << 8); @@ -239,16 +251,20 @@ omap_start_dma(spi_dma.dma_rx_ch); omap_start_dma(spi_dma.dma_tx_ch); - /* We don't want to turn CS off before transfer is done */ - - while(!spi_dma.dma_rx_done) { - udelay(5); + /* Wait for DMA writing to complete */ + while ((!spi_dma.dma_rx_done || !spi_dma.dma_tx_done) && wait_cycles < wait_limit) { + wait_cycles++; + udelay(1); } while(!spi_dma.dma_tx_done) { udelay(5); } + if (wait_cycles >= wait_limit) { + printk("McBSP write DMA timeout, spi_dma.dma_rx_done=%d, spi_dma.dma_tx_done=%d\n", spi_dma.dma_rx_done, spi_dma.dma_tx_done); + } + spi_dma.dma_rx_done = 0; spi_dma.dma_tx_done = 0; @@ -320,7 +336,7 @@ int cx3110x_spi_start(struct net_device *dev) { struct omap_mcbsp_spi_cfg spi_cfg; - int r, div = 1, rate_mhz, max_mhz = 14; + int r, div = 1, rate_mhz, max_mhz = 16; struct net_local * lp; struct spi_hif_local_data * spi_lp; @@ -368,11 +384,11 @@ cx3110x_hw_reset(); - while(rate_mhz/div >= max_mhz) + while(rate_mhz/(div+1) >= max_mhz) div++; - printk("McBSP2: freq_limit=%dMHz, base_freq=%dMHz, divisor=%d (%d.%dMHz)\n", - max_mhz, rate_mhz, div, rate_mhz / div, (rate_mhz * 10 / div) % 10); + printk("McBSP2: freq_limit=%dMHz, base_freq=%dMHz, div=%d (%d.%dMHz)\n", + max_mhz, rate_mhz, div, rate_mhz / (div+1), (rate_mhz * 10 / (div+1)) % 10); spi_dma.dma_tx_done = 0; spi_dma.dma_rx_done = 0; Index: cx3110x-0.8.1/src/sm_drv_spi_io.h =================================================================== --- cx3110x-0.8.1.orig/src/sm_drv_spi_io.h 2008-04-28 18:30:22.000000000 -0300 +++ cx3110x-0.8.1/src/sm_drv_spi_io.h 2008-04-28 18:30:25.000000000 -0300 @@ -27,15 +27,17 @@ int cx3110x_spi_read(struct net_device * dev, unsigned long address, unsigned char * buffer, unsigned int length); int cx3110x_spi_write(struct net_device * dev, unsigned long address, unsigned char * buffer, unsigned int length); -int cx3110x_spi_dma_read(struct net_device *dev, unsigned long address, void * buffer, unsigned int length); +int cx3110x_spi_dma_read_start(struct net_device *dev, unsigned long address, void * buffer, unsigned int length); +int cx3110x_spi_dma_read_wait_for_completion(void); int cx3110x_spi_dma_write(struct net_device *dev, unsigned long address, void * buffer, unsigned int length); void cx3110x_dump_register(struct net_device * dev); -#define sm_spi_read(dev, addr, data, len) cx3110x_spi_read(dev, (addr), (data), (len)) +#define sm_spi_read(dev, addr, data, len) cx3110x_spi_read(dev, (addr), (data), (len)) #define sm_spi_write(dev, addr, data, len) cx3110x_spi_write(dev, (addr), (data), (len)) -#define sm_spi_dma_read(dev, addr, data, len) cx3110x_spi_dma_read(dev, (addr), (data), (len)) +#define sm_spi_dma_read_start(dev, addr, data, len) cx3110x_spi_dma_read_start(dev, (addr), (data), (len)) +#define sm_spi_dma_read_wait_for_completion() cx3110x_spi_dma_read_wait_for_completion() #define sm_spi_dma_write(dev, addr, data, len) cx3110x_spi_dma_write(dev, (addr), (data), (len)) #endif