Commit 8a00946e authored by David S. Miller's avatar David S. Miller

Merge branch 'enetc-fixes'

Vladimir Oltean says:

====================
Fixes for NXP ENETC driver

This contains an assorted set of fixes collected over the past 2 weeks
on the enetc driver. Some are related to VLAN processing, some to
physical link settings, some are fixups of previous hardware workarounds,
and some are simply zero-day data path bugs that for some reason were
never caught or at least identified.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8bd2a055 3a5d12c9
...@@ -281,6 +281,8 @@ static int enetc_poll(struct napi_struct *napi, int budget) ...@@ -281,6 +281,8 @@ static int enetc_poll(struct napi_struct *napi, int budget)
int work_done; int work_done;
int i; int i;
enetc_lock_mdio();
for (i = 0; i < v->count_tx_rings; i++) for (i = 0; i < v->count_tx_rings; i++)
if (!enetc_clean_tx_ring(&v->tx_ring[i], budget)) if (!enetc_clean_tx_ring(&v->tx_ring[i], budget))
complete = false; complete = false;
...@@ -291,8 +293,10 @@ static int enetc_poll(struct napi_struct *napi, int budget) ...@@ -291,8 +293,10 @@ static int enetc_poll(struct napi_struct *napi, int budget)
if (work_done) if (work_done)
v->rx_napi_work = true; v->rx_napi_work = true;
if (!complete) if (!complete) {
enetc_unlock_mdio();
return budget; return budget;
}
napi_complete_done(napi, work_done); napi_complete_done(napi, work_done);
...@@ -301,8 +305,6 @@ static int enetc_poll(struct napi_struct *napi, int budget) ...@@ -301,8 +305,6 @@ static int enetc_poll(struct napi_struct *napi, int budget)
v->rx_napi_work = false; v->rx_napi_work = false;
enetc_lock_mdio();
/* enable interrupts */ /* enable interrupts */
enetc_wr_reg_hot(v->rbier, ENETC_RBIER_RXTIE); enetc_wr_reg_hot(v->rbier, ENETC_RBIER_RXTIE);
...@@ -327,8 +329,8 @@ static void enetc_get_tx_tstamp(struct enetc_hw *hw, union enetc_tx_bd *txbd, ...@@ -327,8 +329,8 @@ static void enetc_get_tx_tstamp(struct enetc_hw *hw, union enetc_tx_bd *txbd,
{ {
u32 lo, hi, tstamp_lo; u32 lo, hi, tstamp_lo;
lo = enetc_rd(hw, ENETC_SICTR0); lo = enetc_rd_hot(hw, ENETC_SICTR0);
hi = enetc_rd(hw, ENETC_SICTR1); hi = enetc_rd_hot(hw, ENETC_SICTR1);
tstamp_lo = le32_to_cpu(txbd->wb.tstamp); tstamp_lo = le32_to_cpu(txbd->wb.tstamp);
if (lo <= tstamp_lo) if (lo <= tstamp_lo)
hi -= 1; hi -= 1;
...@@ -358,9 +360,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget) ...@@ -358,9 +360,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
i = tx_ring->next_to_clean; i = tx_ring->next_to_clean;
tx_swbd = &tx_ring->tx_swbd[i]; tx_swbd = &tx_ring->tx_swbd[i];
enetc_lock_mdio();
bds_to_clean = enetc_bd_ready_count(tx_ring, i); bds_to_clean = enetc_bd_ready_count(tx_ring, i);
enetc_unlock_mdio();
do_tstamp = false; do_tstamp = false;
...@@ -403,8 +403,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget) ...@@ -403,8 +403,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
tx_swbd = tx_ring->tx_swbd; tx_swbd = tx_ring->tx_swbd;
} }
enetc_lock_mdio();
/* BD iteration loop end */ /* BD iteration loop end */
if (is_eof) { if (is_eof) {
tx_frm_cnt++; tx_frm_cnt++;
...@@ -415,8 +413,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget) ...@@ -415,8 +413,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
if (unlikely(!bds_to_clean)) if (unlikely(!bds_to_clean))
bds_to_clean = enetc_bd_ready_count(tx_ring, i); bds_to_clean = enetc_bd_ready_count(tx_ring, i);
enetc_unlock_mdio();
} }
tx_ring->next_to_clean = i; tx_ring->next_to_clean = i;
...@@ -527,9 +523,8 @@ static void enetc_get_rx_tstamp(struct net_device *ndev, ...@@ -527,9 +523,8 @@ static void enetc_get_rx_tstamp(struct net_device *ndev,
static void enetc_get_offloads(struct enetc_bdr *rx_ring, static void enetc_get_offloads(struct enetc_bdr *rx_ring,
union enetc_rx_bd *rxbd, struct sk_buff *skb) union enetc_rx_bd *rxbd, struct sk_buff *skb)
{ {
#ifdef CONFIG_FSL_ENETC_PTP_CLOCK
struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev); struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev);
#endif
/* TODO: hashing */ /* TODO: hashing */
if (rx_ring->ndev->features & NETIF_F_RXCSUM) { if (rx_ring->ndev->features & NETIF_F_RXCSUM) {
u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum); u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum);
...@@ -538,12 +533,31 @@ static void enetc_get_offloads(struct enetc_bdr *rx_ring, ...@@ -538,12 +533,31 @@ static void enetc_get_offloads(struct enetc_bdr *rx_ring,
skb->ip_summed = CHECKSUM_COMPLETE; skb->ip_summed = CHECKSUM_COMPLETE;
} }
/* copy VLAN to skb, if one is extracted, for now we assume it's a if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN) {
* standard TPID, but HW also supports custom values __be16 tpid = 0;
*/
if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN) switch (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_TPID) {
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), case 0:
le16_to_cpu(rxbd->r.vlan_opt)); tpid = htons(ETH_P_8021Q);
break;
case 1:
tpid = htons(ETH_P_8021AD);
break;
case 2:
tpid = htons(enetc_port_rd(&priv->si->hw,
ENETC_PCVLANR1));
break;
case 3:
tpid = htons(enetc_port_rd(&priv->si->hw,
ENETC_PCVLANR2));
break;
default:
break;
}
__vlan_hwaccel_put_tag(skb, tpid, le16_to_cpu(rxbd->r.vlan_opt));
}
#ifdef CONFIG_FSL_ENETC_PTP_CLOCK #ifdef CONFIG_FSL_ENETC_PTP_CLOCK
if (priv->active_offloads & ENETC_F_RX_TSTAMP) if (priv->active_offloads & ENETC_F_RX_TSTAMP)
enetc_get_rx_tstamp(rx_ring->ndev, rxbd, skb); enetc_get_rx_tstamp(rx_ring->ndev, rxbd, skb);
...@@ -660,8 +674,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, ...@@ -660,8 +674,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
u32 bd_status; u32 bd_status;
u16 size; u16 size;
enetc_lock_mdio();
if (cleaned_cnt >= ENETC_RXBD_BUNDLE) { if (cleaned_cnt >= ENETC_RXBD_BUNDLE) {
int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt); int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt);
...@@ -672,19 +684,15 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, ...@@ -672,19 +684,15 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
rxbd = enetc_rxbd(rx_ring, i); rxbd = enetc_rxbd(rx_ring, i);
bd_status = le32_to_cpu(rxbd->r.lstatus); bd_status = le32_to_cpu(rxbd->r.lstatus);
if (!bd_status) { if (!bd_status)
enetc_unlock_mdio();
break; break;
}
enetc_wr_reg_hot(rx_ring->idr, BIT(rx_ring->index)); enetc_wr_reg_hot(rx_ring->idr, BIT(rx_ring->index));
dma_rmb(); /* for reading other rxbd fields */ dma_rmb(); /* for reading other rxbd fields */
size = le16_to_cpu(rxbd->r.buf_len); size = le16_to_cpu(rxbd->r.buf_len);
skb = enetc_map_rx_buff_to_skb(rx_ring, i, size); skb = enetc_map_rx_buff_to_skb(rx_ring, i, size);
if (!skb) { if (!skb)
enetc_unlock_mdio();
break; break;
}
enetc_get_offloads(rx_ring, rxbd, skb); enetc_get_offloads(rx_ring, rxbd, skb);
...@@ -696,7 +704,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, ...@@ -696,7 +704,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
if (unlikely(bd_status & if (unlikely(bd_status &
ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK))) { ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK))) {
enetc_unlock_mdio();
dev_kfree_skb(skb); dev_kfree_skb(skb);
while (!(bd_status & ENETC_RXBD_LSTATUS_F)) { while (!(bd_status & ENETC_RXBD_LSTATUS_F)) {
dma_rmb(); dma_rmb();
...@@ -736,8 +743,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, ...@@ -736,8 +743,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
enetc_process_skb(rx_ring, skb); enetc_process_skb(rx_ring, skb);
enetc_unlock_mdio();
napi_gro_receive(napi, skb); napi_gro_receive(napi, skb);
rx_frm_cnt++; rx_frm_cnt++;
...@@ -984,7 +989,7 @@ static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv) ...@@ -984,7 +989,7 @@ static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv)
enetc_free_tx_ring(priv->tx_ring[i]); enetc_free_tx_ring(priv->tx_ring[i]);
} }
static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr) int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
{ {
int size = cbdr->bd_count * sizeof(struct enetc_cbd); int size = cbdr->bd_count * sizeof(struct enetc_cbd);
...@@ -1005,7 +1010,7 @@ static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr) ...@@ -1005,7 +1010,7 @@ static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
return 0; return 0;
} }
static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr) void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
{ {
int size = cbdr->bd_count * sizeof(struct enetc_cbd); int size = cbdr->bd_count * sizeof(struct enetc_cbd);
...@@ -1013,7 +1018,7 @@ static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr) ...@@ -1013,7 +1018,7 @@ static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
cbdr->bd_base = NULL; cbdr->bd_base = NULL;
} }
static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr) void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
{ {
/* set CBDR cache attributes */ /* set CBDR cache attributes */
enetc_wr(hw, ENETC_SICAR2, enetc_wr(hw, ENETC_SICAR2,
...@@ -1033,7 +1038,7 @@ static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr) ...@@ -1033,7 +1038,7 @@ static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
cbdr->cir = hw->reg + ENETC_SICBDRCIR; cbdr->cir = hw->reg + ENETC_SICBDRCIR;
} }
static void enetc_clear_cbdr(struct enetc_hw *hw) void enetc_clear_cbdr(struct enetc_hw *hw)
{ {
enetc_wr(hw, ENETC_SICBDRMR, 0); enetc_wr(hw, ENETC_SICBDRMR, 0);
} }
...@@ -1058,13 +1063,12 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups) ...@@ -1058,13 +1063,12 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
return 0; return 0;
} }
static int enetc_configure_si(struct enetc_ndev_priv *priv) int enetc_configure_si(struct enetc_ndev_priv *priv)
{ {
struct enetc_si *si = priv->si; struct enetc_si *si = priv->si;
struct enetc_hw *hw = &si->hw; struct enetc_hw *hw = &si->hw;
int err; int err;
enetc_setup_cbdr(hw, &si->cbd_ring);
/* set SI cache attributes */ /* set SI cache attributes */
enetc_wr(hw, ENETC_SICAR0, enetc_wr(hw, ENETC_SICAR0,
ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT); ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
...@@ -1112,6 +1116,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv) ...@@ -1112,6 +1116,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
if (err) if (err)
return err; return err;
enetc_setup_cbdr(&si->hw, &si->cbd_ring);
priv->cls_rules = kcalloc(si->num_fs_entries, sizeof(*priv->cls_rules), priv->cls_rules = kcalloc(si->num_fs_entries, sizeof(*priv->cls_rules),
GFP_KERNEL); GFP_KERNEL);
if (!priv->cls_rules) { if (!priv->cls_rules) {
...@@ -1119,14 +1125,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv) ...@@ -1119,14 +1125,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
goto err_alloc_cls; goto err_alloc_cls;
} }
err = enetc_configure_si(priv);
if (err)
goto err_config_si;
return 0; return 0;
err_config_si:
kfree(priv->cls_rules);
err_alloc_cls: err_alloc_cls:
enetc_clear_cbdr(&si->hw); enetc_clear_cbdr(&si->hw);
enetc_free_cbdr(priv->dev, &si->cbd_ring); enetc_free_cbdr(priv->dev, &si->cbd_ring);
...@@ -1212,7 +1212,8 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) ...@@ -1212,7 +1212,8 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
rx_ring->idr = hw->reg + ENETC_SIRXIDR; rx_ring->idr = hw->reg + ENETC_SIRXIDR;
enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring)); enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
enetc_wr(hw, ENETC_SIRXIDR, rx_ring->next_to_use); /* update ENETC's consumer index */
enetc_rxbdr_wr(hw, idx, ENETC_RBCIR, rx_ring->next_to_use);
/* enable ring */ /* enable ring */
enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr); enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
......
...@@ -292,6 +292,7 @@ void enetc_get_si_caps(struct enetc_si *si); ...@@ -292,6 +292,7 @@ void enetc_get_si_caps(struct enetc_si *si);
void enetc_init_si_rings_params(struct enetc_ndev_priv *priv); void enetc_init_si_rings_params(struct enetc_ndev_priv *priv);
int enetc_alloc_si_resources(struct enetc_ndev_priv *priv); int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
void enetc_free_si_resources(struct enetc_ndev_priv *priv); void enetc_free_si_resources(struct enetc_ndev_priv *priv);
int enetc_configure_si(struct enetc_ndev_priv *priv);
int enetc_open(struct net_device *ndev); int enetc_open(struct net_device *ndev);
int enetc_close(struct net_device *ndev); int enetc_close(struct net_device *ndev);
...@@ -309,6 +310,10 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type, ...@@ -309,6 +310,10 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void enetc_set_ethtool_ops(struct net_device *ndev); void enetc_set_ethtool_ops(struct net_device *ndev);
/* control buffer descriptor ring (CBDR) */ /* control buffer descriptor ring (CBDR) */
int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr);
void enetc_clear_cbdr(struct enetc_hw *hw);
int enetc_set_mac_flt_entry(struct enetc_si *si, int index, int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map); char *mac_addr, int si_map);
int enetc_clear_mac_flt_entry(struct enetc_si *si, int index); int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
......
...@@ -172,6 +172,8 @@ enum enetc_bdr_type {TX, RX}; ...@@ -172,6 +172,8 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_PSIPMAR0(n) (0x0100 + (n) * 0x8) /* n = SI index */ #define ENETC_PSIPMAR0(n) (0x0100 + (n) * 0x8) /* n = SI index */
#define ENETC_PSIPMAR1(n) (0x0104 + (n) * 0x8) #define ENETC_PSIPMAR1(n) (0x0104 + (n) * 0x8)
#define ENETC_PVCLCTR 0x0208 #define ENETC_PVCLCTR 0x0208
#define ENETC_PCVLANR1 0x0210
#define ENETC_PCVLANR2 0x0214
#define ENETC_VLAN_TYPE_C BIT(0) #define ENETC_VLAN_TYPE_C BIT(0)
#define ENETC_VLAN_TYPE_S BIT(1) #define ENETC_VLAN_TYPE_S BIT(1)
#define ENETC_PVCLCTR_OVTPIDL(bmp) ((bmp) & 0xff) /* VLAN_TYPE */ #define ENETC_PVCLCTR_OVTPIDL(bmp) ((bmp) & 0xff) /* VLAN_TYPE */
...@@ -236,10 +238,17 @@ enum enetc_bdr_type {TX, RX}; ...@@ -236,10 +238,17 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_PM_IMDIO_BASE 0x8030 #define ENETC_PM_IMDIO_BASE 0x8030
#define ENETC_PM0_IF_MODE 0x8300 #define ENETC_PM0_IF_MODE 0x8300
#define ENETC_PMO_IFM_RG BIT(2) #define ENETC_PM0_IFM_RG BIT(2)
#define ENETC_PM0_IFM_RLP (BIT(5) | BIT(11)) #define ENETC_PM0_IFM_RLP (BIT(5) | BIT(11))
#define ENETC_PM0_IFM_RGAUTO (BIT(15) | ENETC_PMO_IFM_RG | BIT(1)) #define ENETC_PM0_IFM_EN_AUTO BIT(15)
#define ENETC_PM0_IFM_XGMII BIT(12) #define ENETC_PM0_IFM_SSP_MASK GENMASK(14, 13)
#define ENETC_PM0_IFM_SSP_1000 (2 << 13)
#define ENETC_PM0_IFM_SSP_100 (0 << 13)
#define ENETC_PM0_IFM_SSP_10 (1 << 13)
#define ENETC_PM0_IFM_FULL_DPX BIT(12)
#define ENETC_PM0_IFM_IFMODE_MASK GENMASK(1, 0)
#define ENETC_PM0_IFM_IFMODE_XGMII 0
#define ENETC_PM0_IFM_IFMODE_GMII 2
#define ENETC_PSIDCAPR 0x1b08 #define ENETC_PSIDCAPR 0x1b08
#define ENETC_PSIDCAPR_MSK GENMASK(15, 0) #define ENETC_PSIDCAPR_MSK GENMASK(15, 0)
#define ENETC_PSFCAPR 0x1b18 #define ENETC_PSFCAPR 0x1b18
...@@ -453,6 +462,8 @@ static inline u64 _enetc_rd_reg64_wa(void __iomem *reg) ...@@ -453,6 +462,8 @@ static inline u64 _enetc_rd_reg64_wa(void __iomem *reg)
#define enetc_wr_reg(reg, val) _enetc_wr_reg_wa((reg), (val)) #define enetc_wr_reg(reg, val) _enetc_wr_reg_wa((reg), (val))
#define enetc_rd(hw, off) enetc_rd_reg((hw)->reg + (off)) #define enetc_rd(hw, off) enetc_rd_reg((hw)->reg + (off))
#define enetc_wr(hw, off, val) enetc_wr_reg((hw)->reg + (off), val) #define enetc_wr(hw, off, val) enetc_wr_reg((hw)->reg + (off), val)
#define enetc_rd_hot(hw, off) enetc_rd_reg_hot((hw)->reg + (off))
#define enetc_wr_hot(hw, off, val) enetc_wr_reg_hot((hw)->reg + (off), val)
#define enetc_rd64(hw, off) _enetc_rd_reg64_wa((hw)->reg + (off)) #define enetc_rd64(hw, off) _enetc_rd_reg64_wa((hw)->reg + (off))
/* port register accessors - PF only */ /* port register accessors - PF only */
#define enetc_port_rd(hw, off) enetc_rd_reg((hw)->port + (off)) #define enetc_port_rd(hw, off) enetc_rd_reg((hw)->port + (off))
...@@ -568,6 +579,7 @@ union enetc_rx_bd { ...@@ -568,6 +579,7 @@ union enetc_rx_bd {
#define ENETC_RXBD_LSTATUS(flags) ((flags) << 16) #define ENETC_RXBD_LSTATUS(flags) ((flags) << 16)
#define ENETC_RXBD_FLAG_VLAN BIT(9) #define ENETC_RXBD_FLAG_VLAN BIT(9)
#define ENETC_RXBD_FLAG_TSTMP BIT(10) #define ENETC_RXBD_FLAG_TSTMP BIT(10)
#define ENETC_RXBD_FLAG_TPID GENMASK(1, 0)
#define ENETC_MAC_ADDR_FILT_CNT 8 /* # of supported entries per port */ #define ENETC_MAC_ADDR_FILT_CNT 8 /* # of supported entries per port */
#define EMETC_MAC_ADDR_FILT_RES 3 /* # of reserved entries at the beginning */ #define EMETC_MAC_ADDR_FILT_RES 3 /* # of reserved entries at the beginning */
......
...@@ -190,7 +190,6 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev) ...@@ -190,7 +190,6 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
{ {
struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_pf *pf = enetc_si_priv(priv->si); struct enetc_pf *pf = enetc_si_priv(priv->si);
char vlan_promisc_simap = pf->vlan_promisc_simap;
struct enetc_hw *hw = &priv->si->hw; struct enetc_hw *hw = &priv->si->hw;
bool uprom = false, mprom = false; bool uprom = false, mprom = false;
struct enetc_mac_filter *filter; struct enetc_mac_filter *filter;
...@@ -203,16 +202,12 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev) ...@@ -203,16 +202,12 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0); psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
uprom = true; uprom = true;
mprom = true; mprom = true;
/* Enable VLAN promiscuous mode for SI0 (PF) */
vlan_promisc_simap |= BIT(0);
} else if (ndev->flags & IFF_ALLMULTI) { } else if (ndev->flags & IFF_ALLMULTI) {
/* enable multi cast promisc mode for SI0 (PF) */ /* enable multi cast promisc mode for SI0 (PF) */
psipmr = ENETC_PSIPMR_SET_MP(0); psipmr = ENETC_PSIPMR_SET_MP(0);
mprom = true; mprom = true;
} }
enetc_set_vlan_promisc(&pf->si->hw, vlan_promisc_simap);
/* first 2 filter entries belong to PF */ /* first 2 filter entries belong to PF */
if (!uprom) { if (!uprom) {
/* Update unicast filters */ /* Update unicast filters */
...@@ -320,7 +315,7 @@ static void enetc_set_loopback(struct net_device *ndev, bool en) ...@@ -320,7 +315,7 @@ static void enetc_set_loopback(struct net_device *ndev, bool en)
u32 reg; u32 reg;
reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE); reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
if (reg & ENETC_PMO_IFM_RG) { if (reg & ENETC_PM0_IFM_RG) {
/* RGMII mode */ /* RGMII mode */
reg = (reg & ~ENETC_PM0_IFM_RLP) | reg = (reg & ~ENETC_PM0_IFM_RLP) |
(en ? ENETC_PM0_IFM_RLP : 0); (en ? ENETC_PM0_IFM_RLP : 0);
...@@ -499,13 +494,20 @@ static void enetc_configure_port_mac(struct enetc_hw *hw) ...@@ -499,13 +494,20 @@ static void enetc_configure_port_mac(struct enetc_hw *hw)
static void enetc_mac_config(struct enetc_hw *hw, phy_interface_t phy_mode) static void enetc_mac_config(struct enetc_hw *hw, phy_interface_t phy_mode)
{ {
/* set auto-speed for RGMII */ u32 val;
if (enetc_port_rd(hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG ||
phy_interface_mode_is_rgmii(phy_mode))
enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_RGAUTO);
if (phy_mode == PHY_INTERFACE_MODE_USXGMII) if (phy_interface_mode_is_rgmii(phy_mode)) {
enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_XGMII); val = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
val &= ~ENETC_PM0_IFM_EN_AUTO;
val &= ENETC_PM0_IFM_IFMODE_MASK;
val |= ENETC_PM0_IFM_IFMODE_GMII | ENETC_PM0_IFM_RG;
enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
}
if (phy_mode == PHY_INTERFACE_MODE_USXGMII) {
val = ENETC_PM0_IFM_FULL_DPX | ENETC_PM0_IFM_IFMODE_XGMII;
enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
}
} }
static void enetc_mac_enable(struct enetc_hw *hw, bool en) static void enetc_mac_enable(struct enetc_hw *hw, bool en)
...@@ -937,6 +939,34 @@ static void enetc_pl_mac_config(struct phylink_config *config, ...@@ -937,6 +939,34 @@ static void enetc_pl_mac_config(struct phylink_config *config,
phylink_set_pcs(priv->phylink, &pf->pcs->pcs); phylink_set_pcs(priv->phylink, &pf->pcs->pcs);
} }
static void enetc_force_rgmii_mac(struct enetc_hw *hw, int speed, int duplex)
{
u32 old_val, val;
old_val = val = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
if (speed == SPEED_1000) {
val &= ~ENETC_PM0_IFM_SSP_MASK;
val |= ENETC_PM0_IFM_SSP_1000;
} else if (speed == SPEED_100) {
val &= ~ENETC_PM0_IFM_SSP_MASK;
val |= ENETC_PM0_IFM_SSP_100;
} else if (speed == SPEED_10) {
val &= ~ENETC_PM0_IFM_SSP_MASK;
val |= ENETC_PM0_IFM_SSP_10;
}
if (duplex == DUPLEX_FULL)
val |= ENETC_PM0_IFM_FULL_DPX;
else
val &= ~ENETC_PM0_IFM_FULL_DPX;
if (val == old_val)
return;
enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
}
static void enetc_pl_mac_link_up(struct phylink_config *config, static void enetc_pl_mac_link_up(struct phylink_config *config,
struct phy_device *phy, unsigned int mode, struct phy_device *phy, unsigned int mode,
phy_interface_t interface, int speed, phy_interface_t interface, int speed,
...@@ -949,6 +979,10 @@ static void enetc_pl_mac_link_up(struct phylink_config *config, ...@@ -949,6 +979,10 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
if (priv->active_offloads & ENETC_F_QBV) if (priv->active_offloads & ENETC_F_QBV)
enetc_sched_speed_set(priv, speed); enetc_sched_speed_set(priv, speed);
if (!phylink_autoneg_inband(mode) &&
phy_interface_mode_is_rgmii(interface))
enetc_force_rgmii_mac(&pf->si->hw, speed, duplex);
enetc_mac_enable(&pf->si->hw, true); enetc_mac_enable(&pf->si->hw, true);
} }
...@@ -1041,6 +1075,26 @@ static int enetc_init_port_rss_memory(struct enetc_si *si) ...@@ -1041,6 +1075,26 @@ static int enetc_init_port_rss_memory(struct enetc_si *si)
return err; return err;
} }
static void enetc_init_unused_port(struct enetc_si *si)
{
struct device *dev = &si->pdev->dev;
struct enetc_hw *hw = &si->hw;
int err;
si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE;
err = enetc_alloc_cbdr(dev, &si->cbd_ring);
if (err)
return;
enetc_setup_cbdr(hw, &si->cbd_ring);
enetc_init_port_rfs_memory(si);
enetc_init_port_rss_memory(si);
enetc_clear_cbdr(hw);
enetc_free_cbdr(dev, &si->cbd_ring);
}
static int enetc_pf_probe(struct pci_dev *pdev, static int enetc_pf_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
...@@ -1051,11 +1105,6 @@ static int enetc_pf_probe(struct pci_dev *pdev, ...@@ -1051,11 +1105,6 @@ static int enetc_pf_probe(struct pci_dev *pdev,
struct enetc_pf *pf; struct enetc_pf *pf;
int err; int err;
if (node && !of_device_is_available(node)) {
dev_info(&pdev->dev, "device is disabled, skipping\n");
return -ENODEV;
}
err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf)); err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
if (err) { if (err) {
dev_err(&pdev->dev, "PCI probing failed\n"); dev_err(&pdev->dev, "PCI probing failed\n");
...@@ -1069,6 +1118,13 @@ static int enetc_pf_probe(struct pci_dev *pdev, ...@@ -1069,6 +1118,13 @@ static int enetc_pf_probe(struct pci_dev *pdev,
goto err_map_pf_space; goto err_map_pf_space;
} }
if (node && !of_device_is_available(node)) {
enetc_init_unused_port(si);
dev_info(&pdev->dev, "device is disabled, skipping\n");
err = -ENODEV;
goto err_device_disabled;
}
pf = enetc_si_priv(si); pf = enetc_si_priv(si);
pf->si = si; pf->si = si;
pf->total_vfs = pci_sriov_get_totalvfs(pdev); pf->total_vfs = pci_sriov_get_totalvfs(pdev);
...@@ -1108,6 +1164,12 @@ static int enetc_pf_probe(struct pci_dev *pdev, ...@@ -1108,6 +1164,12 @@ static int enetc_pf_probe(struct pci_dev *pdev,
goto err_init_port_rss; goto err_init_port_rss;
} }
err = enetc_configure_si(priv);
if (err) {
dev_err(&pdev->dev, "Failed to configure SI\n");
goto err_config_si;
}
err = enetc_alloc_msix(priv); err = enetc_alloc_msix(priv);
if (err) { if (err) {
dev_err(&pdev->dev, "MSIX alloc failed\n"); dev_err(&pdev->dev, "MSIX alloc failed\n");
...@@ -1136,6 +1198,7 @@ static int enetc_pf_probe(struct pci_dev *pdev, ...@@ -1136,6 +1198,7 @@ static int enetc_pf_probe(struct pci_dev *pdev,
enetc_mdiobus_destroy(pf); enetc_mdiobus_destroy(pf);
err_mdiobus_create: err_mdiobus_create:
enetc_free_msix(priv); enetc_free_msix(priv);
err_config_si:
err_init_port_rss: err_init_port_rss:
err_init_port_rfs: err_init_port_rfs:
err_alloc_msix: err_alloc_msix:
...@@ -1144,6 +1207,7 @@ static int enetc_pf_probe(struct pci_dev *pdev, ...@@ -1144,6 +1207,7 @@ static int enetc_pf_probe(struct pci_dev *pdev,
si->ndev = NULL; si->ndev = NULL;
free_netdev(ndev); free_netdev(ndev);
err_alloc_netdev: err_alloc_netdev:
err_device_disabled:
err_map_pf_space: err_map_pf_space:
enetc_pci_remove(pdev); enetc_pci_remove(pdev);
......
...@@ -171,6 +171,12 @@ static int enetc_vf_probe(struct pci_dev *pdev, ...@@ -171,6 +171,12 @@ static int enetc_vf_probe(struct pci_dev *pdev,
goto err_alloc_si_res; goto err_alloc_si_res;
} }
err = enetc_configure_si(priv);
if (err) {
dev_err(&pdev->dev, "Failed to configure SI\n");
goto err_config_si;
}
err = enetc_alloc_msix(priv); err = enetc_alloc_msix(priv);
if (err) { if (err) {
dev_err(&pdev->dev, "MSIX alloc failed\n"); dev_err(&pdev->dev, "MSIX alloc failed\n");
...@@ -187,6 +193,7 @@ static int enetc_vf_probe(struct pci_dev *pdev, ...@@ -187,6 +193,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
err_reg_netdev: err_reg_netdev:
enetc_free_msix(priv); enetc_free_msix(priv);
err_config_si:
err_alloc_msix: err_alloc_msix:
enetc_free_si_resources(priv); enetc_free_si_resources(priv);
err_alloc_si_res: err_alloc_si_res:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment