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
*
* 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
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H
#define __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H
/************************************************************************************
/****************************************************************************
* Included Files
************************************************************************************/
****************************************************************************/
#include <nuttx/config.h>
#include "hardware/sam_memorymap.h"
/************************************************************************************
/****************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* GMAC Register Offsets ************************************************************/
****************************************************************************/
/* GMAC Register Offsets ****************************************************/
#define SAM_GMAC_NCR_OFFSET 0x0000 /* Network Control 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_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_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_IMRPQ6 (SAM_GMAC_VBASE+SAM_GMAC_IMRPQ6_OFFSET)
/* GMAC Register Bit Definitions ***************************************************/
/* GMAC Register Bit Definitions ********************************************/
/* Network Control Register */
@ -871,13 +872,13 @@
*
* Use these definitions:
*
* GMAC_INT_RCOMP Bit 1: Receive Complete
* GMAC_INT_RXUBR Bit 2: Receive Used Bit Read
* 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_TCOMP Bit 7: Transmit Complete
* GMAC_INT_ROVR Bit 10: Receive Overrun
* GMAC_INT_HRESP Bit 11: HRESP not OK
* GMAC_INT_RCOMP Bit 1: Receive Complete
* GMAC_INT_RXUBR Bit 2: Receive Used Bit Read
* 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_TCOMP Bit 7: Transmit Complete
* GMAC_INT_ROVR Bit 10: Receive Overrun
* GMAC_INT_HRESP Bit 11: HRESP not OK
*/
/* 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_VLANE (1 << 8) /* Bit 8: VLAN Enable */
/* Descriptors **********************************************************************/
/* Descriptors **************************************************************/
/* 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_USED (1 << 31) /* Bit 31: Zero for the GMAC to read from buffer */
/************************************************************************************
#define GMAC_STATUS_LENGTH_MASK 0x3fffu
/****************************************************************************
* Public Types
************************************************************************************/
****************************************************************************/
/* Receive buffer descriptor */
struct gmac_rxdesc_s

View File

@ -89,6 +89,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* If processing is not done at the interrupt level, then work queue support
@ -168,6 +169,7 @@
#endif
/* Timing *******************************************************************/
/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per
* second
*/
@ -183,6 +185,7 @@
#define PHY_RETRY_MAX 300000
/* Helpers ******************************************************************/
/* This is a helper pointer for accessing the contents of the GMAC
* header
*/
@ -250,6 +253,7 @@ static uint8_t g_pktbuf[MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE];
#ifdef CONFIG_SAMA5_GMAC_PREALLOCATE
/* Preallocated data */
/* TX descriptors list */
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
*
* Section 3.6 of AMBA 2.0 spec states that burst should not cross 1K Boundaries.
* Receive buffer manager writes are burst of 2 words => 3 lsb bits of the address
* shall be set to 0
* Section 3.6 of AMBA 2.0 spec states that burst should not cross 1K
* Boundaries. Receive buffer manager writes are burst of
* 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]
@ -279,13 +283,15 @@ static uint8_t g_rxbuffer[CONFIG_SAMA5_GMAC_NRXBUFFERS * GMAC_RX_UNITSIZE]
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Register operations ******************************************************/
#if defined(CONFIG_SAMA5_GMAC_REGDEBUG) && defined(CONFIG_DEBUG_FEATURES)
static bool sam_checkreg(struct sam_gmac_s *priv, bool wr,
uint32_t regval, uintptr_t address);
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
# define sam_getreg(priv,addr) getreg32(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
****************************************************************************/
/****************************************************************************
* Name: sam_checkreg
*
@ -526,7 +533,7 @@ static uint16_t sam_txfree(struct sam_gmac_s *priv)
* 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;
}
/* 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)
{
@ -721,8 +735,10 @@ static int sam_transmit(struct sam_gmac_s *priv)
/* Update TX descriptor status. */
status = dev->d_len & GMAC_STATUS_LENGTH_MASK;
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;
}
@ -777,8 +793,9 @@ static int sam_transmit(struct sam_gmac_s *priv)
* Function: sam_txpoll
*
* Description:
* The transmitter is available, check if the network has any outgoing packets ready
* to send. This is a callback from devif_poll(). devif_poll() may be called:
* The transmitter is available, check if the network has any outgoing
* 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,
* 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
* been examined.
/* If zero is returned, the polling will continue until all connections
* have been examined.
*/
return 0;
@ -866,7 +883,8 @@ static int sam_txpoll(struct net_driver_s *dev)
*
* 1. After completion of a transmission (sam_txdone),
* 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:
* 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)
{
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;
}
@ -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
{
@ -1181,8 +1202,8 @@ static void sam_receive(struct sam_gmac_s *priv)
{
sam_dumppacket("Received packet", dev->d_buf, dev->d_len);
/* Check if the packet is a valid size for the network buffer configuration
* (this should not happen)
/* Check if the packet is a valid size for the network buffer
* configuration (this should not happen)
*/
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
/* 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);
#endif
@ -1212,7 +1235,8 @@ static void sam_receive(struct sam_gmac_s *priv)
ipv4_input(&priv->dev);
/* 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)
@ -1249,7 +1273,8 @@ static void sam_receive(struct sam_gmac_s *priv)
ipv6_input(&priv->dev);
/* 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)
@ -1286,7 +1311,8 @@ static void sam_receive(struct sam_gmac_s *priv)
arp_arpin(&priv->dev);
/* 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)
@ -1323,6 +1349,7 @@ static void sam_receive(struct sam_gmac_s *priv)
static void sam_txdone(struct sam_gmac_s *priv)
{
struct gmac_txdesc_s *txdesc;
struct net_driver_s *dev = &priv->dev;
/* Are there any outstanding transmissions? Loop until either (1) all of
* 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,
(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)
{
/* Yes.. the descriptor is still in use. However, I have seen a
* case (only repeatable on start-up) where the USED bit is never
* set. Yikes! If we have encountered the first still busy
* descriptor, then we should also have TQBD equal to the descriptor
* address. If it is not, then treat is as used anyway.
* descriptor, then we should also have TQBD equal to the
* descriptor address. If it is not, then treat is as used anyway.
*/
#warning REVISIT
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,
(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
{
@ -1428,8 +1470,8 @@ static void sam_interrupt_work(FAR void *arg)
ninfo("isr: %08x pending: %08x\n", isr, pending);
/* Check for the completion of a transmission. This should be done before
* checking for received data (because receiving can cause another transmission
* before we had a chance to handle the last one).
* checking for received data (because receiving can cause another
* transmission before we had a chance to handle the last one).
*
* 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
@ -1579,7 +1621,8 @@ static void sam_interrupt_work(FAR void *arg)
#ifdef CONFIG_DEBUG_NET
/* 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)
@ -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
* we cannot read it here).
* TSR:TXCOMP is set when a frame has been transmitted. Cleared by writing a
* one to this bit.
* TSR:TXCOMP is set when a frame has been transmitted. Cleared by writing
* 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 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.
*/
@ -2032,7 +2075,8 @@ static unsigned int sam_hashindx(const uint8_t *mac)
unsigned int ndx;
/* Isolate: mac[0]
* ... 05 04 03 02 01 00] */
* ... 05 04 03 02 01 00]
*/
ndx = mac[0];
@ -2203,8 +2247,8 @@ static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac)
* Function: sam_rmmac
*
* Description:
* NuttX Callback: Remove the specified MAC address from the hardware multicast
* address filtering
* NuttX Callback: Remove the specified MAC address from the hardware
* multicast address filtering
*
* Input Parameters:
* 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
* to the req->val_out field.
*
* When called with SIOCSMIIREG it will write to a register of the PHY that
* is specified using the req->reg_no struct field and use req->val_in as
* its input.
* When called with SIOCSMIIREG it will write to a register of the PHY
* that is specified using the req->reg_no struct field and use
* req->val_in as its input.
*
* Input Parameters:
* 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
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);
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 */
{
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;
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 */
{
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 */
@ -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 */
{
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 */
@ -3119,6 +3167,7 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
sam_putreg(priv, SAM_GMAC_UR, regval);
errout:
/* Disable the management port */
sam_disablemdio(priv);
@ -3367,13 +3416,14 @@ static void sam_txreset(struct sam_gmac_s *priv)
/* 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 */
up_clean_dcache((uintptr_t)txdesc,
(uintptr_t)txdesc +
CONFIG_SAMA5_GMAC_NTXBUFFERS * sizeof(struct gmac_txdesc_s));
(uintptr_t)txdesc + CONFIG_SAMA5_GMAC_NTXBUFFERS *
sizeof(struct gmac_txdesc_s));
/* 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 */
up_clean_dcache((uintptr_t)rxdesc,
(uintptr_t)rxdesc +
CONFIG_SAMA5_GMAC_NRXBUFFERS * sizeof(struct gmac_rxdesc_s));
(uintptr_t)rxdesc + CONFIG_SAMA5_GMAC_NRXBUFFERS *
sizeof(struct gmac_rxdesc_s));
/* 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",
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[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]);
dev->d_mac.ether.ether_addr_octet[0],
dev->d_mac.ether.ether_addr_octet[1],
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 */
@ -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 */
regval = GMAC_INT_MFS | GMAC_INT_RCOMP | GMAC_INT_RXUBR | GMAC_INT_TXUBR |
GMAC_INT_TUR | GMAC_INT_RLEX | GMAC_INT_TFC | GMAC_INT_TCOMP |
GMAC_INT_ROVR | GMAC_INT_HRESP | GMAC_INT_PFNZ | GMAC_INT_PTZ |
GMAC_INT_PFTR | GMAC_INT_EXINT | GMAC_INT_DRQFR | GMAC_INT_SFR |
GMAC_INT_DRQFT | GMAC_INT_SFT | GMAC_INT_PDRQFR | GMAC_INT_PDRSFR |
GMAC_INT_PDRQFT | GMAC_INT_PDRSFT;
regval = GMAC_INT_MFS | GMAC_INT_RCOMP | GMAC_INT_RXUBR |
GMAC_INT_TXUBR | GMAC_INT_TUR | GMAC_INT_RLEX |
GMAC_INT_TFC | GMAC_INT_TCOMP | GMAC_INT_ROVR |
GMAC_INT_HRESP | GMAC_INT_PFNZ | GMAC_INT_PTZ |
GMAC_INT_PFTR | GMAC_INT_EXINT | GMAC_INT_DRQFR |
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);
return OK;
}
@ -3807,7 +3862,8 @@ int sam_gmac_initialize(void)
ret = irq_attach(SAM_IRQ_GMAC, sam_gmac_interrupt, NULL);
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;
}
@ -3820,7 +3876,8 @@ int sam_gmac_initialize(void)
ret = sam_ifdown(&priv->dev);
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;
}