|
@@ -119,6 +119,11 @@ static void tx_descs_init(struct eth_device *dev)
|
|
|
/* Correcting the last pointer of the chain */
|
|
|
desc_p->dmamac_next = &desc_table_p[0];
|
|
|
|
|
|
+ /* Flush all Tx buffer descriptors at once */
|
|
|
+ flush_dcache_range((unsigned int)priv->tx_mac_descrtable,
|
|
|
+ (unsigned int)priv->tx_mac_descrtable +
|
|
|
+ sizeof(priv->tx_mac_descrtable));
|
|
|
+
|
|
|
writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
|
|
|
priv->tx_currdescnum = 0;
|
|
|
}
|
|
@@ -132,6 +137,15 @@ static void rx_descs_init(struct eth_device *dev)
|
|
|
struct dmamacdescr *desc_p;
|
|
|
u32 idx;
|
|
|
|
|
|
+ /* Before passing buffers to GMAC we need to make sure zeros
|
|
|
+ * written there right after "priv" structure allocation were
|
|
|
+ * flushed into RAM.
|
|
|
+ * Otherwise there's a chance to get some of them flushed in RAM when
|
|
|
+ * GMAC is already pushing data to RAM via DMA. This way incoming from
|
|
|
+ * GMAC data will be corrupted. */
|
|
|
+ flush_dcache_range((unsigned int)rxbuffs, (unsigned int)rxbuffs +
|
|
|
+ RX_TOTAL_BUFSIZE);
|
|
|
+
|
|
|
for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
|
|
|
desc_p = &desc_table_p[idx];
|
|
|
desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
|
|
@@ -147,6 +161,11 @@ static void rx_descs_init(struct eth_device *dev)
|
|
|
/* Correcting the last pointer of the chain */
|
|
|
desc_p->dmamac_next = &desc_table_p[0];
|
|
|
|
|
|
+ /* Flush all Rx buffer descriptors at once */
|
|
|
+ flush_dcache_range((unsigned int)priv->rx_mac_descrtable,
|
|
|
+ (unsigned int)priv->rx_mac_descrtable +
|
|
|
+ sizeof(priv->rx_mac_descrtable));
|
|
|
+
|
|
|
writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
|
|
|
priv->rx_currdescnum = 0;
|
|
|
}
|
|
@@ -261,6 +280,11 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
|
|
|
u32 desc_num = priv->tx_currdescnum;
|
|
|
struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
|
|
|
|
|
|
+ /* Invalidate only "status" field for the following check */
|
|
|
+ invalidate_dcache_range((unsigned long)&desc_p->txrx_status,
|
|
|
+ (unsigned long)&desc_p->txrx_status +
|
|
|
+ sizeof(desc_p->txrx_status));
|
|
|
+
|
|
|
/* Check if the descriptor is owned by CPU */
|
|
|
if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
|
|
|
printf("CPU not owner of tx frame\n");
|
|
@@ -269,6 +293,10 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
|
|
|
|
|
|
memcpy((void *)desc_p->dmamac_addr, packet, length);
|
|
|
|
|
|
+ /* Flush data to be sent */
|
|
|
+ flush_dcache_range((unsigned long)desc_p->dmamac_addr,
|
|
|
+ (unsigned long)desc_p->dmamac_addr + length);
|
|
|
+
|
|
|
#if defined(CONFIG_DW_ALTDESCRIPTOR)
|
|
|
desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
|
|
|
desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
|
|
@@ -284,6 +312,10 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
|
|
|
desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
|
|
|
#endif
|
|
|
|
|
|
+ /* Flush modified buffer descriptor */
|
|
|
+ flush_dcache_range((unsigned long)desc_p,
|
|
|
+ (unsigned long)desc_p + sizeof(struct dmamacdescr));
|
|
|
+
|
|
|
/* Test the wrap-around condition. */
|
|
|
if (++desc_num >= CONFIG_TX_DESCR_NUM)
|
|
|
desc_num = 0;
|
|
@@ -299,18 +331,28 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
|
|
|
static int dw_eth_recv(struct eth_device *dev)
|
|
|
{
|
|
|
struct dw_eth_dev *priv = dev->priv;
|
|
|
- u32 desc_num = priv->rx_currdescnum;
|
|
|
+ u32 status, desc_num = priv->rx_currdescnum;
|
|
|
struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
|
|
|
-
|
|
|
- u32 status = desc_p->txrx_status;
|
|
|
int length = 0;
|
|
|
|
|
|
+ /* Invalidate entire buffer descriptor */
|
|
|
+ invalidate_dcache_range((unsigned long)desc_p,
|
|
|
+ (unsigned long)desc_p +
|
|
|
+ sizeof(struct dmamacdescr));
|
|
|
+
|
|
|
+ status = desc_p->txrx_status;
|
|
|
+
|
|
|
/* Check if the owner is the CPU */
|
|
|
if (!(status & DESC_RXSTS_OWNBYDMA)) {
|
|
|
|
|
|
length = (status & DESC_RXSTS_FRMLENMSK) >> \
|
|
|
DESC_RXSTS_FRMLENSHFT;
|
|
|
|
|
|
+ /* Invalidate received data */
|
|
|
+ invalidate_dcache_range((unsigned long)desc_p->dmamac_addr,
|
|
|
+ (unsigned long)desc_p->dmamac_addr +
|
|
|
+ length);
|
|
|
+
|
|
|
NetReceive(desc_p->dmamac_addr, length);
|
|
|
|
|
|
/*
|
|
@@ -319,6 +361,11 @@ static int dw_eth_recv(struct eth_device *dev)
|
|
|
*/
|
|
|
desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
|
|
|
|
|
|
+ /* Flush only status field - others weren't changed */
|
|
|
+ flush_dcache_range((unsigned long)&desc_p->txrx_status,
|
|
|
+ (unsigned long)&desc_p->txrx_status +
|
|
|
+ sizeof(desc_p->txrx_status));
|
|
|
+
|
|
|
/* Test the wrap-around condition. */
|
|
|
if (++desc_num >= CONFIG_RX_DESCR_NUM)
|
|
|
desc_num = 0;
|