arch/arm/src/sama5/sam_gmac: Prevent txtimeout from always firing and fix txbuffer leak during high-volume sends

This commit is contained in:
Adam Feuer 2020-02-25 14:10:04 -08:00 committed by GitHub
parent 8ee6be0780
commit cdc61a08e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 140 additions and 79 deletions

View File

@ -1,4 +1,4 @@
/************************************************************************************ /****************************************************************************
* arch/arm/src/sama5/hardware/sam_gmac.h * arch/arm/src/sama5/hardware/sam_gmac.h
* *
* Copyright (C) 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2013 Gregory Nutt. All rights reserved.
@ -31,22 +31,23 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
************************************************************************************/ ****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H #ifndef __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H
#define __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H #define __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H
/************************************************************************************ /****************************************************************************
* Included Files * Included Files
************************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include "hardware/sam_memorymap.h" #include "hardware/sam_memorymap.h"
/************************************************************************************ /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
************************************************************************************/ ****************************************************************************/
/* GMAC Register Offsets ************************************************************/
/* GMAC Register Offsets ****************************************************/
#define SAM_GMAC_NCR_OFFSET 0x0000 /* Network Control Register */ #define SAM_GMAC_NCR_OFFSET 0x0000 /* Network Control Register */
#define SAM_GMAC_NCFGR_OFFSET 0x0004 /* Network Configuration Register */ #define SAM_GMAC_NCFGR_OFFSET 0x0004 /* Network Configuration Register */
@ -243,7 +244,7 @@
#define SAM_GMAC_IMRPQ5_OFFSET 0x654 /* Interrupt Mask Register Priority Queue 5 */ #define SAM_GMAC_IMRPQ5_OFFSET 0x654 /* Interrupt Mask Register Priority Queue 5 */
#define SAM_GMAC_IMRPQ6_OFFSET 0x658 /* Interrupt Mask Register Priority Queue 6 */ #define SAM_GMAC_IMRPQ6_OFFSET 0x658 /* Interrupt Mask Register Priority Queue 6 */
/* GMAC Register Addresses *********************************************************/ /* GMAC Register Addresses **************************************************/
#define SAM_GMAC_NCR (SAM_GMAC_VBASE+SAM_GMAC_NCR_OFFSET) #define SAM_GMAC_NCR (SAM_GMAC_VBASE+SAM_GMAC_NCR_OFFSET)
#define SAM_GMAC_NCFGR (SAM_GMAC_VBASE+SAM_GMAC_NCFGR_OFFSET) #define SAM_GMAC_NCFGR (SAM_GMAC_VBASE+SAM_GMAC_NCFGR_OFFSET)
@ -436,7 +437,7 @@
#define SAM_GMAC_IMRPQ5 (SAM_GMAC_VBASE+SAM_GMAC_IMRPQ5_OFFSET) #define SAM_GMAC_IMRPQ5 (SAM_GMAC_VBASE+SAM_GMAC_IMRPQ5_OFFSET)
#define SAM_GMAC_IMRPQ6 (SAM_GMAC_VBASE+SAM_GMAC_IMRPQ6_OFFSET) #define SAM_GMAC_IMRPQ6 (SAM_GMAC_VBASE+SAM_GMAC_IMRPQ6_OFFSET)
/* GMAC Register Bit Definitions ***************************************************/ /* GMAC Register Bit Definitions ********************************************/
/* Network Control Register */ /* Network Control Register */
@ -871,13 +872,13 @@
* *
* Use these definitions: * Use these definitions:
* *
* GMAC_INT_RCOMP Bit 1: Receive Complete * GMAC_INT_RCOMP Bit 1: Receive Complete
* GMAC_INT_RXUBR Bit 2: Receive Used Bit Read * GMAC_INT_RXUBR Bit 2: Receive Used Bit Read
* GMAC_INT_RLEX Bit 5: Retry Limit Exceeded or Late Collision * GMAC_INT_RLEX Bit 5: Retry Limit Exceeded or Late Collision
* GMAC_INT_TFC Bit 6: Transmit Frame Corruption due to AHB error * GMAC_INT_TFC Bit 6: Transmit Frame Corruption due to AHB error
* GMAC_INT_TCOMP Bit 7: Transmit Complete * GMAC_INT_TCOMP Bit 7: Transmit Complete
* GMAC_INT_ROVR Bit 10: Receive Overrun * GMAC_INT_ROVR Bit 10: Receive Overrun
* GMAC_INT_HRESP Bit 11: HRESP not OK * GMAC_INT_HRESP Bit 11: HRESP not OK
*/ */
/* Transmit Buffer Queue Base Address Priority Queue 0-6 */ /* Transmit Buffer Queue Base Address Priority Queue 0-6 */
@ -916,7 +917,7 @@
# define GMAC_ST2RPQ0_VLANP(n) ((uint32_t)(n) << GMAC_ST2RPQ0_VLANP_SHIFT) # define GMAC_ST2RPQ0_VLANP(n) ((uint32_t)(n) << GMAC_ST2RPQ0_VLANP_SHIFT)
#define GMAC_ST2RPQ0_VLANE (1 << 8) /* Bit 8: VLAN Enable */ #define GMAC_ST2RPQ0_VLANE (1 << 8) /* Bit 8: VLAN Enable */
/* Descriptors **********************************************************************/ /* Descriptors **************************************************************/
/* Receive buffer descriptor: Address word */ /* Receive buffer descriptor: Address word */
@ -992,9 +993,12 @@
#define GMACTXD_STA_WRAP (1 << 30) /* Bit 30: Last descriptor in descriptor list */ #define GMACTXD_STA_WRAP (1 << 30) /* Bit 30: Last descriptor in descriptor list */
#define GMACTXD_STA_USED (1 << 31) /* Bit 31: Zero for the GMAC to read from buffer */ #define GMACTXD_STA_USED (1 << 31) /* Bit 31: Zero for the GMAC to read from buffer */
/************************************************************************************ #define GMAC_STATUS_LENGTH_MASK 0x3fffu
/****************************************************************************
* Public Types * Public Types
************************************************************************************/ ****************************************************************************/
/* Receive buffer descriptor */ /* Receive buffer descriptor */
struct gmac_rxdesc_s struct gmac_rxdesc_s

View File

@ -89,6 +89,7 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
/* If processing is not done at the interrupt level, then work queue support /* If processing is not done at the interrupt level, then work queue support
@ -168,6 +169,7 @@
#endif #endif
/* Timing *******************************************************************/ /* Timing *******************************************************************/
/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per /* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per
* second * second
*/ */
@ -183,6 +185,7 @@
#define PHY_RETRY_MAX 300000 #define PHY_RETRY_MAX 300000
/* Helpers ******************************************************************/ /* Helpers ******************************************************************/
/* This is a helper pointer for accessing the contents of the GMAC /* This is a helper pointer for accessing the contents of the GMAC
* header * header
*/ */
@ -250,6 +253,7 @@ static uint8_t g_pktbuf[MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE];
#ifdef CONFIG_SAMA5_GMAC_PREALLOCATE #ifdef CONFIG_SAMA5_GMAC_PREALLOCATE
/* Preallocated data */ /* Preallocated data */
/* TX descriptors list */ /* TX descriptors list */
static struct gmac_txdesc_s g_txdesc[CONFIG_SAMA5_GMAC_NTXBUFFERS] static struct gmac_txdesc_s g_txdesc[CONFIG_SAMA5_GMAC_NTXBUFFERS]
@ -262,9 +266,9 @@ static struct gmac_rxdesc_s g_rxdesc[CONFIG_SAMA5_GMAC_NRXBUFFERS]
/* Transmit Buffers /* Transmit Buffers
* *
* Section 3.6 of AMBA 2.0 spec states that burst should not cross 1K Boundaries. * Section 3.6 of AMBA 2.0 spec states that burst should not cross 1K
* Receive buffer manager writes are burst of 2 words => 3 lsb bits of the address * Boundaries. Receive buffer manager writes are burst of
* shall be set to 0 * 2 words => 3 lsb bits of the address shall be set to 0
*/ */
static uint8_t g_txbuffer[CONFIG_SAMA5_GMAC_NTXBUFFERS * GMAC_TX_UNITSIZE] static uint8_t g_txbuffer[CONFIG_SAMA5_GMAC_NTXBUFFERS * GMAC_TX_UNITSIZE]
@ -279,13 +283,15 @@ static uint8_t g_rxbuffer[CONFIG_SAMA5_GMAC_NRXBUFFERS * GMAC_RX_UNITSIZE]
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
/* Register operations ******************************************************/ /* Register operations ******************************************************/
#if defined(CONFIG_SAMA5_GMAC_REGDEBUG) && defined(CONFIG_DEBUG_FEATURES) #if defined(CONFIG_SAMA5_GMAC_REGDEBUG) && defined(CONFIG_DEBUG_FEATURES)
static bool sam_checkreg(struct sam_gmac_s *priv, bool wr, static bool sam_checkreg(struct sam_gmac_s *priv, bool wr,
uint32_t regval, uintptr_t address); uint32_t regval, uintptr_t address);
static uint32_t sam_getreg(struct sam_gmac_s *priv, uintptr_t addr); static uint32_t sam_getreg(struct sam_gmac_s *priv, uintptr_t addr);
static void sam_putreg(struct sam_gmac_s *priv, uintptr_t addr, uint32_t val); static void sam_putreg(struct sam_gmac_s *priv, uintptr_t addr,
uint32_t val);
#else #else
# define sam_getreg(priv,addr) getreg32(addr) # define sam_getreg(priv,addr) getreg32(addr)
# define sam_putreg(priv,addr,val) putreg32(val,addr) # define sam_putreg(priv,addr,val) putreg32(val,addr)
@ -383,6 +389,7 @@ static int sam_gmac_configure(struct sam_gmac_s *priv);
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: sam_checkreg * Name: sam_checkreg
* *
@ -526,7 +533,7 @@ static uint16_t sam_txfree(struct sam_gmac_s *priv)
* the configured size minus 1. * the configured size minus 1.
*/ */
return (CONFIG_SAMA5_GMAC_NTXBUFFERS-1) - sam_txinuse(priv); return (CONFIG_SAMA5_GMAC_NTXBUFFERS - 1) - sam_txinuse(priv);
} }
/**************************************************************************** /****************************************************************************
@ -708,7 +715,14 @@ static int sam_transmit(struct sam_gmac_s *priv)
return -EBUSY; return -EBUSY;
} }
/* Setup/Copy data to transmission buffer */ /* Mark buffer as used temporarily so DMA doesn't operate on it */
status = GMACTXD_STA_USED | GMACTXD_STA_LAST;
txdesc->status = status;
up_clean_dcache((uint32_t)txdesc,
(uint32_t)txdesc + sizeof(struct gmac_txdesc_s));
/* Setup/Copy data to transmition buffer */
if (dev->d_len > 0) if (dev->d_len > 0)
{ {
@ -721,8 +735,10 @@ static int sam_transmit(struct sam_gmac_s *priv)
/* Update TX descriptor status. */ /* Update TX descriptor status. */
status = dev->d_len & GMAC_STATUS_LENGTH_MASK;
status = dev->d_len | GMACTXD_STA_LAST; status = dev->d_len | GMACTXD_STA_LAST;
if (priv->txhead == CONFIG_SAMA5_GMAC_NTXBUFFERS-1)
if (priv->txhead == CONFIG_SAMA5_GMAC_NTXBUFFERS - 1)
{ {
status |= GMACTXD_STA_WRAP; status |= GMACTXD_STA_WRAP;
} }
@ -777,8 +793,9 @@ static int sam_transmit(struct sam_gmac_s *priv)
* Function: sam_txpoll * Function: sam_txpoll
* *
* Description: * Description:
* The transmitter is available, check if the network has any outgoing packets ready * The transmitter is available, check if the network has any outgoing
* to send. This is a callback from devif_poll(). devif_poll() may be called: * packets ready to send. This is a callback from devif_poll().
* devif_poll() may be called:
* *
* 1. When the preceding TX packet send is complete, * 1. When the preceding TX packet send is complete,
* 2. When the preceding TX packet send timesout and the interface is reset * 2. When the preceding TX packet send timesout and the interface is reset
@ -850,8 +867,8 @@ static int sam_txpoll(struct net_driver_s *dev)
} }
} }
/* If zero is returned, the polling will continue until all connections have /* If zero is returned, the polling will continue until all connections
* been examined. * have been examined.
*/ */
return 0; return 0;
@ -866,7 +883,8 @@ static int sam_txpoll(struct net_driver_s *dev)
* *
* 1. After completion of a transmission (sam_txdone), * 1. After completion of a transmission (sam_txdone),
* 2. When new TX data is available (sam_txavail), and * 2. When new TX data is available (sam_txavail), and
* 3. After a TX timeout to restart the sending process (sam_txtimeout_expiry). * 3. After a TX timeout to restart the sending process
* (sam_txtimeout_expiry).
* *
* Input Parameters: * Input Parameters:
* priv - Reference to the driver state structure * priv - Reference to the driver state structure
@ -1095,7 +1113,8 @@ static int sam_recvframe(struct sam_gmac_s *priv)
if (pktlen < dev->d_len) if (pktlen < dev->d_len)
{ {
nerr("ERROR: Buffer size %d; frame size %d\n", dev->d_len, pktlen); nerr("ERROR: Buffer size %d; frame size %d\n",
dev->d_len, pktlen);
return -E2BIG; return -E2BIG;
} }
@ -1103,7 +1122,9 @@ static int sam_recvframe(struct sam_gmac_s *priv)
} }
} }
/* We have not encount the SOF yet... discard this fragment and keep looking */ /* We have not encount the SOF yet... discard this fragment and keep
* looking
*/
else else
{ {
@ -1181,8 +1202,8 @@ static void sam_receive(struct sam_gmac_s *priv)
{ {
sam_dumppacket("Received packet", dev->d_buf, dev->d_len); sam_dumppacket("Received packet", dev->d_buf, dev->d_len);
/* Check if the packet is a valid size for the network buffer configuration /* Check if the packet is a valid size for the network buffer
* (this should not happen) * configuration (this should not happen)
*/ */
if (dev->d_len > CONFIG_NET_ETH_PKTSIZE) if (dev->d_len > CONFIG_NET_ETH_PKTSIZE)
@ -1192,7 +1213,9 @@ static void sam_receive(struct sam_gmac_s *priv)
} }
#ifdef CONFIG_NET_PKT #ifdef CONFIG_NET_PKT
/* When packet sockets are enabled, feed the frame into the packet tap */ /* When packet sockets are enabled, feed the frame into the packet
* tap
*/
pkt_input(&priv->dev); pkt_input(&priv->dev);
#endif #endif
@ -1212,7 +1235,8 @@ static void sam_receive(struct sam_gmac_s *priv)
ipv4_input(&priv->dev); ipv4_input(&priv->dev);
/* If the above function invocation resulted in data that should be /* If the above function invocation resulted in data that should be
* sent out on the network, the field d_len will set to a value > 0. * sent out on the network, the field d_len will set to a
* value > 0.
*/ */
if (priv->dev.d_len > 0) if (priv->dev.d_len > 0)
@ -1249,7 +1273,8 @@ static void sam_receive(struct sam_gmac_s *priv)
ipv6_input(&priv->dev); ipv6_input(&priv->dev);
/* If the above function invocation resulted in data that should be /* If the above function invocation resulted in data that should be
* sent out on the network, the field d_len will set to a value > 0. * sent out on the network, the field d_len will set to a
* value > 0.
*/ */
if (priv->dev.d_len > 0) if (priv->dev.d_len > 0)
@ -1286,7 +1311,8 @@ static void sam_receive(struct sam_gmac_s *priv)
arp_arpin(&priv->dev); arp_arpin(&priv->dev);
/* If the above function invocation resulted in data that should be /* If the above function invocation resulted in data that should be
* sent out on the network, the field d_len will set to a value > 0. * sent out on the network, the field d_len will set to a
* value > 0.
*/ */
if (priv->dev.d_len > 0) if (priv->dev.d_len > 0)
@ -1323,6 +1349,7 @@ static void sam_receive(struct sam_gmac_s *priv)
static void sam_txdone(struct sam_gmac_s *priv) static void sam_txdone(struct sam_gmac_s *priv)
{ {
struct gmac_txdesc_s *txdesc; struct gmac_txdesc_s *txdesc;
struct net_driver_s *dev = &priv->dev;
/* Are there any outstanding transmissions? Loop until either (1) all of /* Are there any outstanding transmissions? Loop until either (1) all of
* the TX descriptors have been examined, or (2) until we encounter the * the TX descriptors have been examined, or (2) until we encounter the
@ -1337,24 +1364,39 @@ static void sam_txdone(struct sam_gmac_s *priv)
up_invalidate_dcache((uintptr_t)txdesc, up_invalidate_dcache((uintptr_t)txdesc,
(uintptr_t)txdesc + sizeof(struct gmac_txdesc_s)); (uintptr_t)txdesc + sizeof(struct gmac_txdesc_s));
/* Is this TX descriptor still in use? */ /* Is this TX descriptor done transmitting? (SAMA5D36 datasheet,
* p. 934)
* First TX descriptor in chain has GMACTXD_STA_USED = 1
*/
if ((txdesc->status & GMACTXD_STA_USED) == 0) if ((txdesc->status & GMACTXD_STA_USED) == 0)
{ {
/* Yes.. the descriptor is still in use. However, I have seen a /* Yes.. the descriptor is still in use. However, I have seen a
* case (only repeatable on start-up) where the USED bit is never * case (only repeatable on start-up) where the USED bit is never
* set. Yikes! If we have encountered the first still busy * set. Yikes! If we have encountered the first still busy
* descriptor, then we should also have TQBD equal to the descriptor * descriptor, then we should also have TQBD equal to the
* address. If it is not, then treat is as used anyway. * descriptor address. If it is not, then treat is as used anyway.
*/ */
#warning REVISIT
if (priv->txtail == 0 && if (priv->txtail == 0 &&
sam_physramaddr((uintptr_t)txdesc) != sam_getreg(priv, SAM_GMAC_TBQB)) sam_physramaddr((uintptr_t)txdesc) != sam_getreg(priv,
SAM_GMAC_TBQB))
{ {
txdesc->status = (uint32_t)GMACTXD_STA_USED; ninfo("TX buffer marked in-use: unusual startup case (%d)\n",
priv->txtail);
txdesc->status = (uint32_t) dev->d_len | GMACTXD_STA_USED;
up_clean_dcache((uintptr_t)txdesc, up_clean_dcache((uintptr_t)txdesc,
(uintptr_t)txdesc + sizeof(struct gmac_txdesc_s)); (uintptr_t)txdesc +
sizeof(struct gmac_txdesc_s));
}
else if (((txdesc->status & GMACTXD_STA_USED) == 0) &&
((txdesc->status & GMACTXD_STA_LAST) != 0))
{
txdesc->status = (uint32_t) dev->d_len | GMACTXD_STA_USED |
GMACTXD_STA_LAST;
up_clean_dcache((uintptr_t)txdesc,
(uintptr_t)txdesc +
sizeof(struct gmac_txdesc_s));
} }
else else
{ {
@ -1428,8 +1470,8 @@ static void sam_interrupt_work(FAR void *arg)
ninfo("isr: %08x pending: %08x\n", isr, pending); ninfo("isr: %08x pending: %08x\n", isr, pending);
/* Check for the completion of a transmission. This should be done before /* Check for the completion of a transmission. This should be done before
* checking for received data (because receiving can cause another transmission * checking for received data (because receiving can cause another
* before we had a chance to handle the last one). * transmission before we had a chance to handle the last one).
* *
* ISR:TCOMP is set when a frame has been transmitted. Cleared on read. * ISR:TCOMP is set when a frame has been transmitted. Cleared on read.
* TSR:COMP is set when a frame has been transmitted. Cleared by writing a * TSR:COMP is set when a frame has been transmitted. Cleared by writing a
@ -1579,7 +1621,8 @@ static void sam_interrupt_work(FAR void *arg)
#ifdef CONFIG_DEBUG_NET #ifdef CONFIG_DEBUG_NET
/* Check for PAUSE Frame received (PFRE). /* Check for PAUSE Frame received (PFRE).
* *
* ISR:PFRE indicates that a pause frame has been received. Cleared on a read. * ISR:PFRE indicates that a pause frame has been received. Cleared on a
* read.
*/ */
if ((pending & GMAC_INT_PFNZ) != 0) if ((pending & GMAC_INT_PFNZ) != 0)
@ -1638,15 +1681,15 @@ static int sam_gmac_interrupt(int irq, void *context, FAR void *arg)
* *
* ISR:TCOMP is set when a frame has been transmitted. Cleared on read (so * ISR:TCOMP is set when a frame has been transmitted. Cleared on read (so
* we cannot read it here). * we cannot read it here).
* TSR:TXCOMP is set when a frame has been transmitted. Cleared by writing a * TSR:TXCOMP is set when a frame has been transmitted. Cleared by writing
* one to this bit. * a one to this bit.
*/ */
tsr = sam_getreg(priv, SAM_GMAC_TSR_OFFSET); tsr = sam_getreg(priv, SAM_GMAC_TSR);
if ((tsr & GMAC_TSR_TXCOMP) != 0) if ((tsr & GMAC_TSR_TXCOMP) != 0)
{ {
/* If a TX transfer just completed, then cancel the TX timeout so /* If a TX transfer just completed, then cancel the TX timeout so
* there will be do race condition between any subsequent timeout * there will be no race condition between any subsequent timeout
* expiration and the deferred interrupt processing. * expiration and the deferred interrupt processing.
*/ */
@ -2032,7 +2075,8 @@ static unsigned int sam_hashindx(const uint8_t *mac)
unsigned int ndx; unsigned int ndx;
/* Isolate: mac[0] /* Isolate: mac[0]
* ... 05 04 03 02 01 00] */ * ... 05 04 03 02 01 00]
*/
ndx = mac[0]; ndx = mac[0];
@ -2203,8 +2247,8 @@ static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac)
* Function: sam_rmmac * Function: sam_rmmac
* *
* Description: * Description:
* NuttX Callback: Remove the specified MAC address from the hardware multicast * NuttX Callback: Remove the specified MAC address from the hardware
* address filtering * multicast address filtering
* *
* Input Parameters: * Input Parameters:
* dev - Reference to the NuttX driver state structure * dev - Reference to the NuttX driver state structure
@ -2301,9 +2345,9 @@ static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac)
* specified using the req->reg_no struct field and then write its output * specified using the req->reg_no struct field and then write its output
* to the req->val_out field. * to the req->val_out field.
* *
* When called with SIOCSMIIREG it will write to a register of the PHY that * When called with SIOCSMIIREG it will write to a register of the PHY
* is specified using the req->reg_no struct field and use req->val_in as * that is specified using the req->reg_no struct field and use
* its input. * req->val_in as its input.
* *
* Input Parameters: * Input Parameters:
* dev - Ethernet device structure * dev - Ethernet device structure
@ -2330,7 +2374,8 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
#ifdef CONFIG_ARCH_PHY_INTERRUPT #ifdef CONFIG_ARCH_PHY_INTERRUPT
case SIOCMIINOTIFY: /* Set up for PHY event notifications */ case SIOCMIINOTIFY: /* Set up for PHY event notifications */
{ {
struct mii_ioctl_notify_s *req = (struct mii_ioctl_notify_s *)((uintptr_t)arg); struct mii_ioctl_notify_s *req =
(struct mii_ioctl_notify_s *)((uintptr_t)arg);
ret = phy_notify_subscribe(dev->d_ifname, req->pid, &req->event); ret = phy_notify_subscribe(dev->d_ifname, req->pid, &req->event);
if (ret == OK) if (ret == OK)
@ -2345,7 +2390,8 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
case SIOCGMIIPHY: /* Get MII PHY address */ case SIOCGMIIPHY: /* Get MII PHY address */
{ {
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); struct mii_ioctl_data_s *req =
(struct mii_ioctl_data_s *)((uintptr_t)arg);
req->phy_id = priv->phyaddr; req->phy_id = priv->phyaddr;
ret = OK; ret = OK;
} }
@ -2353,7 +2399,8 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
case SIOCGMIIREG: /* Get register from MII PHY */ case SIOCGMIIREG: /* Get register from MII PHY */
{ {
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); struct mii_ioctl_data_s *req =
(struct mii_ioctl_data_s *)((uintptr_t)arg);
/* Enable the management port */ /* Enable the management port */
@ -2371,7 +2418,8 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
case SIOCSMIIREG: /* Set register in MII PHY */ case SIOCSMIIREG: /* Set register in MII PHY */
{ {
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); struct mii_ioctl_data_s *req =
(struct mii_ioctl_data_s *)((uintptr_t)arg);
/* Enable the management port */ /* Enable the management port */
@ -3119,6 +3167,7 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
sam_putreg(priv, SAM_GMAC_UR, regval); sam_putreg(priv, SAM_GMAC_UR, regval);
errout: errout:
/* Disable the management port */ /* Disable the management port */
sam_disablemdio(priv); sam_disablemdio(priv);
@ -3367,13 +3416,14 @@ static void sam_txreset(struct sam_gmac_s *priv)
/* Mark the final descriptor in the list */ /* Mark the final descriptor in the list */
txdesc[CONFIG_SAMA5_GMAC_NTXBUFFERS - 1].status = GMACTXD_STA_USED | GMACTXD_STA_WRAP; txdesc[CONFIG_SAMA5_GMAC_NTXBUFFERS - 1].status = GMACTXD_STA_USED |
GMACTXD_STA_WRAP;
/* Flush the entire TX descriptor table to RAM */ /* Flush the entire TX descriptor table to RAM */
up_clean_dcache((uintptr_t)txdesc, up_clean_dcache((uintptr_t)txdesc,
(uintptr_t)txdesc + (uintptr_t)txdesc + CONFIG_SAMA5_GMAC_NTXBUFFERS *
CONFIG_SAMA5_GMAC_NTXBUFFERS * sizeof(struct gmac_txdesc_s)); sizeof(struct gmac_txdesc_s));
/* Set the Transmit Buffer Queue Base Register */ /* Set the Transmit Buffer Queue Base Register */
@ -3436,8 +3486,8 @@ static void sam_rxreset(struct sam_gmac_s *priv)
/* Flush the entire RX descriptor table to RAM */ /* Flush the entire RX descriptor table to RAM */
up_clean_dcache((uintptr_t)rxdesc, up_clean_dcache((uintptr_t)rxdesc,
(uintptr_t)rxdesc + (uintptr_t)rxdesc + CONFIG_SAMA5_GMAC_NRXBUFFERS *
CONFIG_SAMA5_GMAC_NRXBUFFERS * sizeof(struct gmac_rxdesc_s)); sizeof(struct gmac_rxdesc_s));
/* Set the Receive Buffer Queue Base Register */ /* Set the Receive Buffer Queue Base Register */
@ -3526,9 +3576,12 @@ static void sam_macaddress(struct sam_gmac_s *priv)
ninfo("%s MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", ninfo("%s MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
dev->d_ifname, dev->d_ifname,
dev->d_mac.ether.ether_addr_octet[0], dev->d_mac.ether.ether_addr_octet[1], dev->d_mac.ether.ether_addr_octet[0],
dev->d_mac.ether.ether_addr_octet[2], dev->d_mac.ether.ether_addr_octet[3], dev->d_mac.ether.ether_addr_octet[1],
dev->d_mac.ether.ether_addr_octet[4], dev->d_mac.ether.ether_addr_octet[5]); dev->d_mac.ether.ether_addr_octet[2],
dev->d_mac.ether.ether_addr_octet[3],
dev->d_mac.ether.ether_addr_octet[4],
dev->d_mac.ether.ether_addr_octet[5]);
/* Set the MAC address */ /* Set the MAC address */
@ -3717,12 +3770,14 @@ static int sam_gmac_configure(struct sam_gmac_s *priv)
/* Setup the interrupts for TX events, RX events, and error events */ /* Setup the interrupts for TX events, RX events, and error events */
regval = GMAC_INT_MFS | GMAC_INT_RCOMP | GMAC_INT_RXUBR | GMAC_INT_TXUBR | regval = GMAC_INT_MFS | GMAC_INT_RCOMP | GMAC_INT_RXUBR |
GMAC_INT_TUR | GMAC_INT_RLEX | GMAC_INT_TFC | GMAC_INT_TCOMP | GMAC_INT_TXUBR | GMAC_INT_TUR | GMAC_INT_RLEX |
GMAC_INT_ROVR | GMAC_INT_HRESP | GMAC_INT_PFNZ | GMAC_INT_PTZ | GMAC_INT_TFC | GMAC_INT_TCOMP | GMAC_INT_ROVR |
GMAC_INT_PFTR | GMAC_INT_EXINT | GMAC_INT_DRQFR | GMAC_INT_SFR | GMAC_INT_HRESP | GMAC_INT_PFNZ | GMAC_INT_PTZ |
GMAC_INT_DRQFT | GMAC_INT_SFT | GMAC_INT_PDRQFR | GMAC_INT_PDRSFR | GMAC_INT_PFTR | GMAC_INT_EXINT | GMAC_INT_DRQFR |
GMAC_INT_PDRQFT | GMAC_INT_PDRSFT; GMAC_INT_SFR | GMAC_INT_DRQFT | GMAC_INT_SFT |
GMAC_INT_PDRQFR | GMAC_INT_PDRSFR | GMAC_INT_PDRQFT |
GMAC_INT_PDRSFT;
sam_putreg(priv, SAM_GMAC_IER, regval); sam_putreg(priv, SAM_GMAC_IER, regval);
return OK; return OK;
} }
@ -3807,7 +3862,8 @@ int sam_gmac_initialize(void)
ret = irq_attach(SAM_IRQ_GMAC, sam_gmac_interrupt, NULL); ret = irq_attach(SAM_IRQ_GMAC, sam_gmac_interrupt, NULL);
if (ret < 0) if (ret < 0)
{ {
nerr("ERROR: Failed to attach the handler to the IRQ%d\n", SAM_IRQ_GMAC); nerr("ERROR: Failed to attach the handler to the IRQ%d\n",
SAM_IRQ_GMAC);
goto errout_with_buffers; goto errout_with_buffers;
} }
@ -3820,7 +3876,8 @@ int sam_gmac_initialize(void)
ret = sam_ifdown(&priv->dev); ret = sam_ifdown(&priv->dev);
if (ret < 0) if (ret < 0)
{ {
nerr("ERROR: Failed to put the interface in the down state: %d\n", ret); nerr("ERROR: Failed to put the interface in the down state: %d\n",
ret);
goto errout_with_buffers; goto errout_with_buffers;
} }