mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-20 18:19:42 +07:00
Merge branch 'stmmac-fixes'
Jose Abreu says: ==================== net: stmmac: Fixes for -net Misc fixes for stmmac. Patch 1/11 and 2/11, use the correct variable type for bitrev32() calls. Patch 3/11, fixes the random failures the we were seing when running selftests. Patch 4/11, prevents a crash that can occur when receiving AVB packets and with SPH feature enabled on XGMAC. Patch 5/11, fixes the correct settings for CBS on XGMAC. Patch 6/11, corrects the interpretation of AVB feature on XGMAC. Patch 7/11, disables Flow Control for AVB enabled queues on XGMAC. Patch 8/11, disables MMC interrupts on XGMAC, preventing a storm of interrupts. Patch 9/11, fixes the number of packets that were being taken into account in the RX path cleaning function. Patch 10/11, fixes an incorrect descriptor setting that could cause IP misbehavior. Patch 11/11, fixes the IOC generation mechanism when multiple descriptors are used. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
58b87d21fe
@ -432,7 +432,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
|
||||
* bits used depends on the hardware configuration
|
||||
* selected at core configuration time.
|
||||
*/
|
||||
int bit_nr = bitrev32(~crc32_le(~0, ha->addr,
|
||||
u32 bit_nr = bitrev32(~crc32_le(~0, ha->addr,
|
||||
ETH_ALEN)) >> (32 - mcbitslog2);
|
||||
/* The most significant bit determines the register to
|
||||
* use (H/L) while the other 5 bits determine the bit
|
||||
|
@ -224,6 +224,7 @@ static void dwxgmac2_config_cbs(struct mac_device_info *hw,
|
||||
writel(low_credit, ioaddr + XGMAC_MTL_TCx_LOCREDIT(queue));
|
||||
|
||||
value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue));
|
||||
value &= ~XGMAC_TSA;
|
||||
value |= XGMAC_CC | XGMAC_CBS;
|
||||
writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue));
|
||||
}
|
||||
@ -463,7 +464,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
|
||||
value |= XGMAC_FILTER_HMC;
|
||||
|
||||
netdev_for_each_mc_addr(ha, dev) {
|
||||
int nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >>
|
||||
u32 nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >>
|
||||
(32 - mcbitslog2));
|
||||
mc_filter[nr >> 5] |= (1 << (nr & 0x1F));
|
||||
}
|
||||
|
@ -288,7 +288,8 @@ static int dwxgmac2_get_rx_hash(struct dma_desc *p, u32 *hash,
|
||||
|
||||
static int dwxgmac2_get_rx_header_len(struct dma_desc *p, unsigned int *len)
|
||||
{
|
||||
*len = le32_to_cpu(p->des2) & XGMAC_RDES2_HL;
|
||||
if (le32_to_cpu(p->des3) & XGMAC_RDES3_L34T)
|
||||
*len = le32_to_cpu(p->des2) & XGMAC_RDES2_HL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
|
||||
dma_cap->eee = (hw_cap & XGMAC_HWFEAT_EEESEL) >> 13;
|
||||
dma_cap->atime_stamp = (hw_cap & XGMAC_HWFEAT_TSSEL) >> 12;
|
||||
dma_cap->av = (hw_cap & XGMAC_HWFEAT_AVSEL) >> 11;
|
||||
dma_cap->av &= !(hw_cap & XGMAC_HWFEAT_RAVSEL) >> 10;
|
||||
dma_cap->av &= !((hw_cap & XGMAC_HWFEAT_RAVSEL) >> 10);
|
||||
dma_cap->arpoffsel = (hw_cap & XGMAC_HWFEAT_ARPOFFSEL) >> 9;
|
||||
dma_cap->rmon = (hw_cap & XGMAC_HWFEAT_MMCSEL) >> 8;
|
||||
dma_cap->pmt_magic_frame = (hw_cap & XGMAC_HWFEAT_MGKSEL) >> 7;
|
||||
@ -470,6 +470,7 @@ static void dwxgmac2_enable_tso(void __iomem *ioaddr, bool en, u32 chan)
|
||||
static void dwxgmac2_qmode(void __iomem *ioaddr, u32 channel, u8 qmode)
|
||||
{
|
||||
u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel));
|
||||
u32 flow = readl(ioaddr + XGMAC_RX_FLOW_CTRL);
|
||||
|
||||
value &= ~XGMAC_TXQEN;
|
||||
if (qmode != MTL_QUEUE_AVB) {
|
||||
@ -477,6 +478,7 @@ static void dwxgmac2_qmode(void __iomem *ioaddr, u32 channel, u8 qmode)
|
||||
writel(0, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(channel));
|
||||
} else {
|
||||
value |= 0x1 << XGMAC_TXQEN_SHIFT;
|
||||
writel(flow & (~XGMAC_RFE), ioaddr + XGMAC_RX_FLOW_CTRL);
|
||||
}
|
||||
|
||||
writel(value, ioaddr + XGMAC_MTL_TXQ_OPMODE(channel));
|
||||
|
@ -176,6 +176,7 @@
|
||||
#define MMC_XGMAC_RX_PKT_SMD_ERR 0x22c
|
||||
#define MMC_XGMAC_RX_PKT_ASSEMBLY_OK 0x230
|
||||
#define MMC_XGMAC_RX_FPE_FRAG 0x234
|
||||
#define MMC_XGMAC_RX_IPC_INTR_MASK 0x25c
|
||||
|
||||
static void dwmac_mmc_ctrl(void __iomem *mmcaddr, unsigned int mode)
|
||||
{
|
||||
@ -333,8 +334,9 @@ static void dwxgmac_mmc_ctrl(void __iomem *mmcaddr, unsigned int mode)
|
||||
|
||||
static void dwxgmac_mmc_intr_all_mask(void __iomem *mmcaddr)
|
||||
{
|
||||
writel(MMC_DEFAULT_MASK, mmcaddr + MMC_RX_INTR_MASK);
|
||||
writel(MMC_DEFAULT_MASK, mmcaddr + MMC_TX_INTR_MASK);
|
||||
writel(0x0, mmcaddr + MMC_RX_INTR_MASK);
|
||||
writel(0x0, mmcaddr + MMC_TX_INTR_MASK);
|
||||
writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_IPC_INTR_MASK);
|
||||
}
|
||||
|
||||
static void dwxgmac_read_mmc_reg(void __iomem *addr, u32 reg, u32 *dest)
|
||||
|
@ -2996,6 +2996,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
stmmac_set_desc_addr(priv, first, des);
|
||||
tmp_pay_len = pay_len;
|
||||
des += proto_hdr_len;
|
||||
pay_len = 0;
|
||||
}
|
||||
|
||||
stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);
|
||||
@ -3023,6 +3024,19 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Only the last descriptor gets to point to the skb. */
|
||||
tx_q->tx_skbuff[tx_q->cur_tx] = skb;
|
||||
|
||||
/* Manage tx mitigation */
|
||||
tx_q->tx_count_frames += nfrags + 1;
|
||||
if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) &&
|
||||
!((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
|
||||
priv->hwts_tx_en)) {
|
||||
stmmac_tx_timer_arm(priv, queue);
|
||||
} else {
|
||||
desc = &tx_q->dma_tx[tx_q->cur_tx];
|
||||
tx_q->tx_count_frames = 0;
|
||||
stmmac_set_tx_ic(priv, desc);
|
||||
priv->xstats.tx_set_ic_bit++;
|
||||
}
|
||||
|
||||
/* We've used all descriptors we need for this skb, however,
|
||||
* advance cur_tx so that it references a fresh descriptor.
|
||||
* ndo_start_xmit will fill this descriptor the next time it's
|
||||
@ -3040,19 +3054,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
priv->xstats.tx_tso_frames++;
|
||||
priv->xstats.tx_tso_nfrags += nfrags;
|
||||
|
||||
/* Manage tx mitigation */
|
||||
tx_q->tx_count_frames += nfrags + 1;
|
||||
if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) &&
|
||||
!(priv->synopsys_id >= DWMAC_CORE_4_00 &&
|
||||
(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
|
||||
priv->hwts_tx_en)) {
|
||||
stmmac_tx_timer_arm(priv, queue);
|
||||
} else {
|
||||
tx_q->tx_count_frames = 0;
|
||||
stmmac_set_tx_ic(priv, desc);
|
||||
priv->xstats.tx_set_ic_bit++;
|
||||
}
|
||||
|
||||
if (priv->sarc_type)
|
||||
stmmac_set_desc_sarc(priv, first, priv->sarc_type);
|
||||
|
||||
@ -3224,6 +3225,27 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Only the last descriptor gets to point to the skb. */
|
||||
tx_q->tx_skbuff[entry] = skb;
|
||||
|
||||
/* According to the coalesce parameter the IC bit for the latest
|
||||
* segment is reset and the timer re-started to clean the tx status.
|
||||
* This approach takes care about the fragments: desc is the first
|
||||
* element in case of no SG.
|
||||
*/
|
||||
tx_q->tx_count_frames += nfrags + 1;
|
||||
if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) &&
|
||||
!((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
|
||||
priv->hwts_tx_en)) {
|
||||
stmmac_tx_timer_arm(priv, queue);
|
||||
} else {
|
||||
if (likely(priv->extend_desc))
|
||||
desc = &tx_q->dma_etx[entry].basic;
|
||||
else
|
||||
desc = &tx_q->dma_tx[entry];
|
||||
|
||||
tx_q->tx_count_frames = 0;
|
||||
stmmac_set_tx_ic(priv, desc);
|
||||
priv->xstats.tx_set_ic_bit++;
|
||||
}
|
||||
|
||||
/* We've used all descriptors we need for this skb, however,
|
||||
* advance cur_tx so that it references a fresh descriptor.
|
||||
* ndo_start_xmit will fill this descriptor the next time it's
|
||||
@ -3259,23 +3281,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
|
||||
/* According to the coalesce parameter the IC bit for the latest
|
||||
* segment is reset and the timer re-started to clean the tx status.
|
||||
* This approach takes care about the fragments: desc is the first
|
||||
* element in case of no SG.
|
||||
*/
|
||||
tx_q->tx_count_frames += nfrags + 1;
|
||||
if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) &&
|
||||
!(priv->synopsys_id >= DWMAC_CORE_4_00 &&
|
||||
(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
|
||||
priv->hwts_tx_en)) {
|
||||
stmmac_tx_timer_arm(priv, queue);
|
||||
} else {
|
||||
tx_q->tx_count_frames = 0;
|
||||
stmmac_set_tx_ic(priv, desc);
|
||||
priv->xstats.tx_set_ic_bit++;
|
||||
}
|
||||
|
||||
if (priv->sarc_type)
|
||||
stmmac_set_desc_sarc(priv, first, priv->sarc_type);
|
||||
|
||||
@ -3506,8 +3511,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
||||
if (unlikely(status & dma_own))
|
||||
break;
|
||||
|
||||
count++;
|
||||
|
||||
rx_q->cur_rx = STMMAC_GET_ENTRY(rx_q->cur_rx, DMA_RX_SIZE);
|
||||
next_entry = rx_q->cur_rx;
|
||||
|
||||
@ -3534,6 +3537,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
||||
goto read_again;
|
||||
if (unlikely(error)) {
|
||||
dev_kfree_skb(skb);
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3573,6 +3577,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
||||
skb = napi_alloc_skb(&ch->rx_napi, len);
|
||||
if (!skb) {
|
||||
priv->dev->stats.rx_dropped++;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3638,6 +3643,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
||||
|
||||
priv->dev->stats.rx_packets++;
|
||||
priv->dev->stats.rx_bytes += len;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (status & rx_not_ls) {
|
||||
|
@ -6,7 +6,9 @@
|
||||
* Author: Jose Abreu <joabreu@synopsys.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitrev.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/phy.h>
|
||||
@ -485,12 +487,48 @@ static int stmmac_filter_check(struct stmmac_priv *priv)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static bool stmmac_hash_check(struct stmmac_priv *priv, unsigned char *addr)
|
||||
{
|
||||
int mc_offset = 32 - priv->hw->mcast_bits_log2;
|
||||
struct netdev_hw_addr *ha;
|
||||
u32 hash, hash_nr;
|
||||
|
||||
/* First compute the hash for desired addr */
|
||||
hash = bitrev32(~crc32_le(~0, addr, 6)) >> mc_offset;
|
||||
hash_nr = hash >> 5;
|
||||
hash = 1 << (hash & 0x1f);
|
||||
|
||||
/* Now, check if it collides with any existing one */
|
||||
netdev_for_each_mc_addr(ha, priv->dev) {
|
||||
u32 nr = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN)) >> mc_offset;
|
||||
if (((nr >> 5) == hash_nr) && ((1 << (nr & 0x1f)) == hash))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* No collisions, address is good to go */
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stmmac_perfect_check(struct stmmac_priv *priv, unsigned char *addr)
|
||||
{
|
||||
struct netdev_hw_addr *ha;
|
||||
|
||||
/* Check if it collides with any existing one */
|
||||
netdev_for_each_uc_addr(ha, priv->dev) {
|
||||
if (!memcmp(ha->addr, addr, ETH_ALEN))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* No collisions, address is good to go */
|
||||
return true;
|
||||
}
|
||||
|
||||
static int stmmac_test_hfilt(struct stmmac_priv *priv)
|
||||
{
|
||||
unsigned char gd_addr[ETH_ALEN] = {0x01, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
|
||||
unsigned char bd_addr[ETH_ALEN] = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
unsigned char gd_addr[ETH_ALEN] = {0xf1, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
|
||||
unsigned char bd_addr[ETH_ALEN] = {0xf1, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
struct stmmac_packet_attrs attr = { };
|
||||
int ret;
|
||||
int ret, tries = 256;
|
||||
|
||||
ret = stmmac_filter_check(priv);
|
||||
if (ret)
|
||||
@ -499,6 +537,16 @@ static int stmmac_test_hfilt(struct stmmac_priv *priv)
|
||||
if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
while (--tries) {
|
||||
/* We only need to check the bd_addr for collisions */
|
||||
bd_addr[ETH_ALEN - 1] = tries;
|
||||
if (stmmac_hash_check(priv, bd_addr))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tries)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = dev_mc_add(priv->dev, gd_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -523,13 +571,25 @@ static int stmmac_test_hfilt(struct stmmac_priv *priv)
|
||||
|
||||
static int stmmac_test_pfilt(struct stmmac_priv *priv)
|
||||
{
|
||||
unsigned char gd_addr[ETH_ALEN] = {0x00, 0x01, 0x44, 0x55, 0x66, 0x77};
|
||||
unsigned char bd_addr[ETH_ALEN] = {0x08, 0x00, 0x22, 0x33, 0x44, 0x55};
|
||||
unsigned char gd_addr[ETH_ALEN] = {0xf0, 0x01, 0x44, 0x55, 0x66, 0x77};
|
||||
unsigned char bd_addr[ETH_ALEN] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
struct stmmac_packet_attrs attr = { };
|
||||
int ret;
|
||||
int ret, tries = 256;
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
while (--tries) {
|
||||
/* We only need to check the bd_addr for collisions */
|
||||
bd_addr[ETH_ALEN - 1] = tries;
|
||||
if (stmmac_perfect_check(priv, bd_addr))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tries)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = dev_uc_add(priv->dev, gd_addr);
|
||||
if (ret)
|
||||
@ -553,39 +613,31 @@ static int stmmac_test_pfilt(struct stmmac_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stmmac_dummy_sync(struct net_device *netdev, const u8 *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stmmac_test_set_rx_mode(struct net_device *netdev)
|
||||
{
|
||||
/* As we are in test mode of ethtool we already own the rtnl lock
|
||||
* so no address will change from user. We can just call the
|
||||
* ndo_set_rx_mode() callback directly */
|
||||
if (netdev->netdev_ops->ndo_set_rx_mode)
|
||||
netdev->netdev_ops->ndo_set_rx_mode(netdev);
|
||||
}
|
||||
|
||||
static int stmmac_test_mcfilt(struct stmmac_priv *priv)
|
||||
{
|
||||
unsigned char uc_addr[ETH_ALEN] = {0x00, 0x01, 0x44, 0x55, 0x66, 0x77};
|
||||
unsigned char mc_addr[ETH_ALEN] = {0x01, 0x01, 0x44, 0x55, 0x66, 0x77};
|
||||
unsigned char uc_addr[ETH_ALEN] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
unsigned char mc_addr[ETH_ALEN] = {0xf1, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
struct stmmac_packet_attrs attr = { };
|
||||
int ret;
|
||||
int ret, tries = 256;
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (!priv->hw->multicast_filter_bins)
|
||||
if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Remove all MC addresses */
|
||||
__dev_mc_unsync(priv->dev, NULL);
|
||||
stmmac_test_set_rx_mode(priv->dev);
|
||||
while (--tries) {
|
||||
/* We only need to check the mc_addr for collisions */
|
||||
mc_addr[ETH_ALEN - 1] = tries;
|
||||
if (stmmac_hash_check(priv, mc_addr))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tries)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = dev_uc_add(priv->dev, uc_addr);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
return ret;
|
||||
|
||||
attr.dst = uc_addr;
|
||||
|
||||
@ -602,30 +654,34 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv)
|
||||
|
||||
cleanup:
|
||||
dev_uc_del(priv->dev, uc_addr);
|
||||
__dev_mc_sync(priv->dev, stmmac_dummy_sync, NULL);
|
||||
stmmac_test_set_rx_mode(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stmmac_test_ucfilt(struct stmmac_priv *priv)
|
||||
{
|
||||
unsigned char uc_addr[ETH_ALEN] = {0x00, 0x01, 0x44, 0x55, 0x66, 0x77};
|
||||
unsigned char mc_addr[ETH_ALEN] = {0x01, 0x01, 0x44, 0x55, 0x66, 0x77};
|
||||
unsigned char uc_addr[ETH_ALEN] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
unsigned char mc_addr[ETH_ALEN] = {0xf1, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
struct stmmac_packet_attrs attr = { };
|
||||
int ret;
|
||||
int ret, tries = 256;
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (!priv->hw->multicast_filter_bins)
|
||||
if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Remove all UC addresses */
|
||||
__dev_uc_unsync(priv->dev, NULL);
|
||||
stmmac_test_set_rx_mode(priv->dev);
|
||||
while (--tries) {
|
||||
/* We only need to check the uc_addr for collisions */
|
||||
uc_addr[ETH_ALEN - 1] = tries;
|
||||
if (stmmac_perfect_check(priv, uc_addr))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tries)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = dev_mc_add(priv->dev, mc_addr);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
return ret;
|
||||
|
||||
attr.dst = mc_addr;
|
||||
|
||||
@ -642,8 +698,6 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv)
|
||||
|
||||
cleanup:
|
||||
dev_mc_del(priv->dev, mc_addr);
|
||||
__dev_uc_sync(priv->dev, stmmac_dummy_sync, NULL);
|
||||
stmmac_test_set_rx_mode(priv->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user