Merge pull request #1738 from zhuangwei123/master

[bsp/ls1cdev]修复以太网驱动发送字节丢失问题
This commit is contained in:
Bernard Xiong 2018-08-26 20:08:04 +08:00 committed by GitHub
commit 6bde1c520d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 658 additions and 619 deletions

View File

@ -109,7 +109,8 @@ s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32
gmacdev->TxDescCount = 0; gmacdev->TxDescCount = 0;
first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr); first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr);
if(first_desc == NULL){ if (first_desc == NULL)
{
rt_kprintf("Error in Tx Descriptors memory allocation\n"); rt_kprintf("Error in Tx Descriptors memory allocation\n");
return -ESYNOPGMACNOMEM; return -ESYNOPGMACNOMEM;
} }
@ -120,7 +121,8 @@ s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32
gmacdev->TxDesc = first_desc; gmacdev->TxDesc = first_desc;
gmacdev->TxDescDma = dma_addr; gmacdev->TxDescDma = dma_addr;
for(i =0; i < gmacdev->TxDescCount; i++){ for (i = 0; i < gmacdev->TxDescCount; i++)
{
synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount - 1); synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount - 1);
#if SYNOP_TOP_DEBUG #if SYNOP_TOP_DEBUG
rt_kprintf("\n%02d %08x \n", i, (unsigned int)(gmacdev->TxDesc + i)); rt_kprintf("\n%02d %08x \n", i, (unsigned int)(gmacdev->TxDesc + i));
@ -181,7 +183,8 @@ s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32
gmacdev->RxDescCount = 0; gmacdev->RxDescCount = 0;
first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr); first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr);
if(first_desc == NULL){ if (first_desc == NULL)
{
rt_kprintf("Error in Rx Descriptor Memory allocation in Ring mode\n"); rt_kprintf("Error in Rx Descriptor Memory allocation in Ring mode\n");
return -ESYNOPGMACNOMEM; return -ESYNOPGMACNOMEM;
} }
@ -192,7 +195,8 @@ s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32
gmacdev->RxDesc = (DmaDesc *)first_desc; gmacdev->RxDesc = (DmaDesc *)first_desc;
gmacdev->RxDescDma = dma_addr; gmacdev->RxDescDma = dma_addr;
for(i =0; i < gmacdev->RxDescCount; i++){ for (i = 0; i < gmacdev->RxDescCount; i++)
{
synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount - 1); synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount - 1);
} }
@ -215,7 +219,8 @@ void synopGMAC_linux_cable_unplug_function(void *adaptr)
struct ethtool_cmd cmd; struct ethtool_cmd cmd;
//rt_kprintf("%s\n",__FUNCTION__); //rt_kprintf("%s\n",__FUNCTION__);
if(!mii_link_ok(&adapter->mii)){ if (!mii_link_ok(&adapter->mii))
{
if (gmacdev->LinkState) if (gmacdev->LinkState)
rt_kprintf("\r\nNo Link\r\n"); rt_kprintf("\r\nNo Link\r\n");
gmacdev->DuplexMode = 0; gmacdev->DuplexMode = 0;
@ -223,10 +228,12 @@ void synopGMAC_linux_cable_unplug_function(void *adaptr)
gmacdev->LoopBackMode = 0; gmacdev->LoopBackMode = 0;
gmacdev->LinkState = 0; gmacdev->LinkState = 0;
} }
else{ else
{
data = synopGMAC_check_phy_init(adapter); data = synopGMAC_check_phy_init(adapter);
if(gmacdev->LinkState != data){ if (gmacdev->LinkState != data)
{
gmacdev->LinkState = data; gmacdev->LinkState = data;
synopGMAC_mac_init(gmacdev); synopGMAC_mac_init(gmacdev);
rt_kprintf("Link is up in %s mode\n", (gmacdev->DuplexMode == FULLDUPLEX) ? "FULL DUPLEX" : "HALF DUPLEX"); rt_kprintf("Link is up in %s mode\n", (gmacdev->DuplexMode == FULLDUPLEX) ? "FULL DUPLEX" : "HALF DUPLEX");
@ -272,7 +279,8 @@ s32 synopGMAC_check_phy_init (synopGMACPciNetworkAdapter *adapter)
static int Mac_change_check(u8 *macaddr0, u8 *macaddr1) static int Mac_change_check(u8 *macaddr0, u8 *macaddr1)
{ {
int i; int i;
for(i = 0; i < 6; i++){ for (i = 0; i < 6; i++)
{
if (macaddr0[i] != macaddr1[i]) if (macaddr0[i] != macaddr1[i])
return 1; return 1;
} }
@ -304,11 +312,11 @@ static rt_err_t eth_init(rt_device_t device )
init_phy(adapter->synopGMACdev); init_phy(adapter->synopGMACdev);
rt_kprintf("tx desc_queue\n"); DEBUG_MES("tx desc_queue\n");
synopGMAC_setup_tx_desc_queue(gmacdev, TRANSMIT_DESC_SIZE, RINGMODE); synopGMAC_setup_tx_desc_queue(gmacdev, TRANSMIT_DESC_SIZE, RINGMODE);
synopGMAC_init_tx_desc_base(gmacdev); synopGMAC_init_tx_desc_base(gmacdev);
rt_kprintf("rx desc_queue\n"); DEBUG_MES("rx desc_queue\n");
synopGMAC_setup_rx_desc_queue(gmacdev, RECEIVE_DESC_SIZE, RINGMODE); synopGMAC_setup_rx_desc_queue(gmacdev, RECEIVE_DESC_SIZE, RINGMODE);
synopGMAC_init_rx_desc_base(gmacdev); synopGMAC_init_rx_desc_base(gmacdev);
DEBUG_MES("DmaRxBaseAddr = %08x\n", synopGMACReadReg(gmacdev->DmaBase, DmaRxBaseAddr)); DEBUG_MES("DmaRxBaseAddr = %08x\n", synopGMACReadReg(gmacdev->DmaBase, DmaRxBaseAddr));
@ -335,9 +343,11 @@ static rt_err_t eth_init(rt_device_t device )
#endif #endif
u32 skb; u32 skb;
do{ do
{
skb = (u32)plat_alloc_memory(RX_BUF_SIZE); //should skb aligned here? skb = (u32)plat_alloc_memory(RX_BUF_SIZE); //should skb aligned here?
if(skb == RT_NULL){ if (skb == RT_NULL)
{
rt_kprintf("ERROR in skb buffer allocation\n"); rt_kprintf("ERROR in skb buffer allocation\n");
break; break;
} }
@ -350,7 +360,8 @@ static rt_err_t eth_init(rt_device_t device )
rt_kprintf("status < 0!!\n"); rt_kprintf("status < 0!!\n");
plat_free_memory((void *)skb); plat_free_memory((void *)skb);
} }
}while(status >= 0 && (status < (RECEIVE_DESC_SIZE - 1))); }
while (status >= 0 && (status < (RECEIVE_DESC_SIZE - 1)));
synopGMAC_clear_interrupt(gmacdev); synopGMAC_clear_interrupt(gmacdev);
@ -460,7 +471,7 @@ rt_err_t rt_eth_tx(rt_device_t device, struct pbuf* p)
if (!synopGMAC_is_desc_owned_by_dma(gmacdev->TxNextDesc)) if (!synopGMAC_is_desc_owned_by_dma(gmacdev->TxNextDesc))
{ {
pbuf = (u32)plat_alloc_memory(p->len); pbuf = (u32)plat_alloc_memory(p->tot_len);
//pbuf = (u32)pbuf_alloc(PBUF_LINK, p->len, PBUF_RAM); //pbuf = (u32)pbuf_alloc(PBUF_LINK, p->len, PBUF_RAM);
if (pbuf == 0) if (pbuf == 0)
{ {
@ -469,11 +480,12 @@ rt_err_t rt_eth_tx(rt_device_t device, struct pbuf* p)
} }
DEBUG_MES("p->len = %d\n", p->len); DEBUG_MES("p->len = %d\n", p->len);
memcpy((void *)pbuf, p->payload, p->len); pbuf_copy_partial(p, (void *)pbuf, p->tot_len, 0);
dma_addr = plat_dma_map_single(gmacdev,(void*)pbuf,p->len); dma_addr = plat_dma_map_single(gmacdev, (void *)pbuf, p->tot_len);
status = synopGMAC_set_tx_qptr(gmacdev,dma_addr,p->len,pbuf,0,0,0,offload_needed,&index,dpr); status = synopGMAC_set_tx_qptr(gmacdev, dma_addr, p->tot_len, pbuf, 0, 0, 0, offload_needed, &index, dpr);
if(status < 0){ if (status < 0)
{
rt_kprintf("%s No More Free Tx Descriptors\n", __FUNCTION__); rt_kprintf("%s No More Free Tx Descriptors\n", __FUNCTION__);
plat_free_memory((void *)pbuf); plat_free_memory((void *)pbuf);
@ -492,36 +504,44 @@ rt_err_t rt_eth_tx(rt_device_t device, struct pbuf* p)
u32 time_stamp_high; u32 time_stamp_high;
u32 time_stamp_low; u32 time_stamp_low;
#endif #endif
do { do
{
#ifdef ENH_DESC_8W #ifdef ENH_DESC_8W
desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2, &ext_status, &time_stamp_high, &time_stamp_low); desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2, &ext_status, &time_stamp_high, &time_stamp_low);
synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher); synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher);
#else #else
desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2); desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2);
#endif #endif
if(desc_index >= 0 && data1 != 0){ if (desc_index >= 0 && data1 != 0)
{
#ifdef IPC_OFFLOAD #ifdef IPC_OFFLOAD
if(synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status)){ if (synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status))
{
rt_kprintf("Harware Failed to Insert IPV4 Header Checksum\n"); rt_kprintf("Harware Failed to Insert IPV4 Header Checksum\n");
} }
if(synopGMAC_is_tx_payload_checksum_error(gmacdev, status)){ if (synopGMAC_is_tx_payload_checksum_error(gmacdev, status))
{
rt_kprintf("Harware Failed to Insert Payload Checksum\n"); rt_kprintf("Harware Failed to Insert Payload Checksum\n");
} }
#endif #endif
plat_free_memory((void *)(data1)); //sw: data1 = buffer1 plat_free_memory((void *)(data1)); //sw: data1 = buffer1
if(synopGMAC_is_desc_valid(status)){ if (synopGMAC_is_desc_valid(status))
{
adapter->synopGMACNetStats.tx_bytes += length1; adapter->synopGMACNetStats.tx_bytes += length1;
adapter->synopGMACNetStats.tx_packets++; adapter->synopGMACNetStats.tx_packets++;
} }
else { else
{
adapter->synopGMACNetStats.tx_errors++; adapter->synopGMACNetStats.tx_errors++;
adapter->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status); adapter->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status);
adapter->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status); adapter->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status);
} }
} adapter->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status); }
} while(desc_index >= 0); adapter->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status);
}
while (desc_index >= 0);
/* unlock eth device */ /* unlock eth device */
rt_sem_release(&sem_lock); rt_sem_release(&sem_lock);
@ -552,13 +572,15 @@ struct pbuf *rt_eth_rx(rt_device_t device)
rt_sem_take(&sem_lock, RT_WAITING_FOREVER); rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
adapter = (struct synopGMACNetworkAdapter *) dev->priv; adapter = (struct synopGMACNetworkAdapter *) dev->priv;
if(adapter == NULL){ if (adapter == NULL)
{
rt_kprintf("%S : Unknown Device !!\n", __FUNCTION__); rt_kprintf("%S : Unknown Device !!\n", __FUNCTION__);
return NULL; return NULL;
} }
gmacdev = (synopGMACdevice *) adapter->synopGMACdev; gmacdev = (synopGMACdevice *) adapter->synopGMACdev;
if(gmacdev == NULL){ if (gmacdev == NULL)
{
rt_kprintf("%s : GMAC device structure is missing\n", __FUNCTION__); rt_kprintf("%s : GMAC device structure is missing\n", __FUNCTION__);
return NULL; return NULL;
} }
@ -567,7 +589,8 @@ struct pbuf *rt_eth_rx(rt_device_t device)
// do{ // do{
desc_index = synopGMAC_get_rx_qptr(gmacdev, &status, &dma_addr1, NULL, &data1, &dma_addr2, NULL, &data2); desc_index = synopGMAC_get_rx_qptr(gmacdev, &status, &dma_addr1, NULL, &data1, &dma_addr2, NULL, &data2);
if(desc_index >= 0 && data1 != 0){ if (desc_index >= 0 && data1 != 0)
{
DEBUG_MES("Received Data at Rx Descriptor %d for skb 0x%08x whose status is %08x\n", desc_index, dma_addr1, status); DEBUG_MES("Received Data at Rx Descriptor %d for skb 0x%08x whose status is %08x\n", desc_index, dma_addr1, status);
if (synopGMAC_is_rx_desc_valid(status) || SYNOP_PHY_LOOPBACK) if (synopGMAC_is_rx_desc_valid(status) || SYNOP_PHY_LOOPBACK)
@ -593,7 +616,8 @@ struct pbuf *rt_eth_rx(rt_device_t device)
desc_index = synopGMAC_set_rx_qptr(gmacdev, dma_addr1, RX_BUF_SIZE, (u32)data1, 0, 0, 0); desc_index = synopGMAC_set_rx_qptr(gmacdev, dma_addr1, RX_BUF_SIZE, (u32)data1, 0, 0, 0);
if(desc_index < 0){ if (desc_index < 0)
{
#if SYNOP_RX_DEBUG #if SYNOP_RX_DEBUG
rt_kprintf("Cannot set Rx Descriptor for data1 %08x\n", (u32)data1); rt_kprintf("Cannot set Rx Descriptor for data1 %08x\n", (u32)data1);
#endif #endif
@ -675,7 +699,8 @@ int init_phy(synopGMACdevice *gmacdev)
return 0; return 0;
} }
u32 synopGMAC_wakeup_filter_config3[] = { u32 synopGMAC_wakeup_filter_config3[] =
{
0x00000000, 0x00000000,
0x000000FF, 0x000000FF,
0x00000000, 0x00000000,
@ -779,23 +804,27 @@ void eth_rx_irq(int irqno,void *param)
synopGMAC_disable_interrupt_all(gmacdev); synopGMAC_disable_interrupt_all(gmacdev);
gmacstatus = synopGMACReadReg(gmacdev->MacBase, GmacStatus); gmacstatus = synopGMACReadReg(gmacdev->MacBase, GmacStatus);
if(dma_status_reg & GmacPmtIntr){ if (dma_status_reg & GmacPmtIntr)
{
rt_kprintf("%s:: Interrupt due to PMT module\n", __FUNCTION__); rt_kprintf("%s:: Interrupt due to PMT module\n", __FUNCTION__);
//synopGMAC_linux_powerup_mac(gmacdev); //synopGMAC_linux_powerup_mac(gmacdev);
} }
if(dma_status_reg & GmacMmcIntr){ if (dma_status_reg & GmacMmcIntr)
{
rt_kprintf("%s:: Interrupt due to MMC module\n", __FUNCTION__); rt_kprintf("%s:: Interrupt due to MMC module\n", __FUNCTION__);
DEBUG_MES("%s:: synopGMAC_rx_int_status = %08x\n", __FUNCTION__, synopGMAC_read_mmc_rx_int_status(gmacdev)); DEBUG_MES("%s:: synopGMAC_rx_int_status = %08x\n", __FUNCTION__, synopGMAC_read_mmc_rx_int_status(gmacdev));
DEBUG_MES("%s:: synopGMAC_tx_int_status = %08x\n", __FUNCTION__, synopGMAC_read_mmc_tx_int_status(gmacdev)); DEBUG_MES("%s:: synopGMAC_tx_int_status = %08x\n", __FUNCTION__, synopGMAC_read_mmc_tx_int_status(gmacdev));
} }
if(dma_status_reg & GmacLineIntfIntr){ if (dma_status_reg & GmacLineIntfIntr)
{
rt_kprintf("%s:: Interrupt due to GMAC LINE module\n", __FUNCTION__); rt_kprintf("%s:: Interrupt due to GMAC LINE module\n", __FUNCTION__);
} }
interrupt = synopGMAC_get_interrupt_type(gmacdev); interrupt = synopGMAC_get_interrupt_type(gmacdev);
//rt_kprintf("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt); //rt_kprintf("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt);
if(interrupt & synopGMACDmaError){ if (interrupt & synopGMACDmaError)
{
u8 mac_addr0[6]; u8 mac_addr0[6];
rt_kprintf("%s::Fatal Bus Error Inetrrupt Seen\n", __FUNCTION__); rt_kprintf("%s::Fatal Bus Error Inetrrupt Seen\n", __FUNCTION__);
@ -820,34 +849,42 @@ void eth_rx_irq(int irqno,void *param)
synopGMAC_enable_dma_tx(gmacdev); synopGMAC_enable_dma_tx(gmacdev);
} }
if(interrupt & synopGMACDmaRxNormal){ if (interrupt & synopGMACDmaRxNormal)
{
//DEBUG_MES("%s:: Rx Normal \n", __FUNCTION__); //DEBUG_MES("%s:: Rx Normal \n", __FUNCTION__);
//synop_handle_received_data(netdev); //synop_handle_received_data(netdev);
eth_device_ready(&eth_dev.parent); eth_device_ready(&eth_dev.parent);
} }
if(interrupt & synopGMACDmaRxAbnormal){ if (interrupt & synopGMACDmaRxAbnormal)
{
//rt_kprintf("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__); //rt_kprintf("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__);
if(GMAC_Power_down == 0){ if (GMAC_Power_down == 0)
{
adapter->synopGMACNetStats.rx_over_errors++; adapter->synopGMACNetStats.rx_over_errors++;
synopGMACWriteReg(gmacdev->DmaBase, DmaStatus, 0x80); synopGMACWriteReg(gmacdev->DmaBase, DmaStatus, 0x80);
synopGMAC_resume_dma_rx(gmacdev); synopGMAC_resume_dma_rx(gmacdev);
} }
} }
if(interrupt & synopGMACDmaRxStopped){ if (interrupt & synopGMACDmaRxStopped)
{
rt_kprintf("%s::Receiver stopped seeing Rx interrupts\n", __FUNCTION__); //Receiver gone in to stopped state rt_kprintf("%s::Receiver stopped seeing Rx interrupts\n", __FUNCTION__); //Receiver gone in to stopped state
} }
if(interrupt & synopGMACDmaTxNormal){ if (interrupt & synopGMACDmaTxNormal)
{
DEBUG_MES("%s::Finished Normal Transmission \n", __FUNCTION__); DEBUG_MES("%s::Finished Normal Transmission \n", __FUNCTION__);
// synop_handle_transmit_over(netdev); // synop_handle_transmit_over(netdev);
} }
if(interrupt & synopGMACDmaTxAbnormal){ if (interrupt & synopGMACDmaTxAbnormal)
{
rt_kprintf("%s::Abnormal Tx Interrupt Seen\n", __FUNCTION__); rt_kprintf("%s::Abnormal Tx Interrupt Seen\n", __FUNCTION__);
} }
if(interrupt & synopGMACDmaTxStopped){ if (interrupt & synopGMACDmaTxStopped)
{
TR("%s::Transmitter stopped sending the packets\n", __FUNCTION__); TR("%s::Transmitter stopped sending the packets\n", __FUNCTION__);
if(GMAC_Power_down == 0){ // If Mac is not in powerdown if (GMAC_Power_down == 0) // If Mac is not in powerdown
{
synopGMAC_disable_dma_tx(gmacdev); synopGMAC_disable_dma_tx(gmacdev);
synopGMAC_take_desc_ownership_tx(gmacdev); synopGMAC_take_desc_ownership_tx(gmacdev);
@ -886,7 +923,8 @@ int rt_hw_eth_init(void)
memset(&eth_dev, 0, sizeof(eth_dev)); memset(&eth_dev, 0, sizeof(eth_dev));
synopGMACadapter = (struct synopGMACNetworkAdapter *)plat_alloc_memory(sizeof(struct synopGMACNetworkAdapter)); synopGMACadapter = (struct synopGMACNetworkAdapter *)plat_alloc_memory(sizeof(struct synopGMACNetworkAdapter));
if(!synopGMACadapter){ if (!synopGMACadapter)
{
rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__); rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__);
} }
memset((char *)synopGMACadapter, 0, sizeof(struct synopGMACNetworkAdapter)); memset((char *)synopGMACadapter, 0, sizeof(struct synopGMACNetworkAdapter));
@ -894,7 +932,8 @@ int rt_hw_eth_init(void)
synopGMACadapter->synopGMACdev = NULL; synopGMACadapter->synopGMACdev = NULL;
synopGMACadapter->synopGMACdev = (synopGMACdevice *) plat_alloc_memory(sizeof(synopGMACdevice)); synopGMACadapter->synopGMACdev = (synopGMACdevice *) plat_alloc_memory(sizeof(synopGMACdevice));
if(!synopGMACadapter->synopGMACdev){ if (!synopGMACadapter->synopGMACdev)
{
rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__); rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__);
} }
memset((char *)synopGMACadapter->synopGMACdev, 0, sizeof(synopGMACdevice)); memset((char *)synopGMACadapter->synopGMACdev, 0, sizeof(synopGMACdevice));