forked from Minki/linux
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
8a00946e1a
@ -281,6 +281,8 @@ static int enetc_poll(struct napi_struct *napi, int budget)
|
||||
int work_done;
|
||||
int i;
|
||||
|
||||
enetc_lock_mdio();
|
||||
|
||||
for (i = 0; i < v->count_tx_rings; i++)
|
||||
if (!enetc_clean_tx_ring(&v->tx_ring[i], budget))
|
||||
complete = false;
|
||||
@ -291,8 +293,10 @@ static int enetc_poll(struct napi_struct *napi, int budget)
|
||||
if (work_done)
|
||||
v->rx_napi_work = true;
|
||||
|
||||
if (!complete)
|
||||
if (!complete) {
|
||||
enetc_unlock_mdio();
|
||||
return budget;
|
||||
}
|
||||
|
||||
napi_complete_done(napi, work_done);
|
||||
|
||||
@ -301,8 +305,6 @@ static int enetc_poll(struct napi_struct *napi, int budget)
|
||||
|
||||
v->rx_napi_work = false;
|
||||
|
||||
enetc_lock_mdio();
|
||||
|
||||
/* enable interrupts */
|
||||
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,
|
||||
{
|
||||
u32 lo, hi, tstamp_lo;
|
||||
|
||||
lo = enetc_rd(hw, ENETC_SICTR0);
|
||||
hi = enetc_rd(hw, ENETC_SICTR1);
|
||||
lo = enetc_rd_hot(hw, ENETC_SICTR0);
|
||||
hi = enetc_rd_hot(hw, ENETC_SICTR1);
|
||||
tstamp_lo = le32_to_cpu(txbd->wb.tstamp);
|
||||
if (lo <= tstamp_lo)
|
||||
hi -= 1;
|
||||
@ -358,9 +360,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
|
||||
i = tx_ring->next_to_clean;
|
||||
tx_swbd = &tx_ring->tx_swbd[i];
|
||||
|
||||
enetc_lock_mdio();
|
||||
bds_to_clean = enetc_bd_ready_count(tx_ring, i);
|
||||
enetc_unlock_mdio();
|
||||
|
||||
do_tstamp = false;
|
||||
|
||||
@ -403,8 +403,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
|
||||
tx_swbd = tx_ring->tx_swbd;
|
||||
}
|
||||
|
||||
enetc_lock_mdio();
|
||||
|
||||
/* BD iteration loop end */
|
||||
if (is_eof) {
|
||||
tx_frm_cnt++;
|
||||
@ -415,8 +413,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
|
||||
|
||||
if (unlikely(!bds_to_clean))
|
||||
bds_to_clean = enetc_bd_ready_count(tx_ring, i);
|
||||
|
||||
enetc_unlock_mdio();
|
||||
}
|
||||
|
||||
tx_ring->next_to_clean = i;
|
||||
@ -527,9 +523,8 @@ static void enetc_get_rx_tstamp(struct net_device *ndev,
|
||||
static void enetc_get_offloads(struct enetc_bdr *rx_ring,
|
||||
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);
|
||||
#endif
|
||||
|
||||
/* TODO: hashing */
|
||||
if (rx_ring->ndev->features & NETIF_F_RXCSUM) {
|
||||
u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum);
|
||||
@ -538,12 +533,31 @@ static void enetc_get_offloads(struct enetc_bdr *rx_ring,
|
||||
skb->ip_summed = CHECKSUM_COMPLETE;
|
||||
}
|
||||
|
||||
/* copy VLAN to skb, if one is extracted, for now we assume it's a
|
||||
* standard TPID, but HW also supports custom values
|
||||
*/
|
||||
if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN)
|
||||
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
|
||||
le16_to_cpu(rxbd->r.vlan_opt));
|
||||
if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN) {
|
||||
__be16 tpid = 0;
|
||||
|
||||
switch (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_TPID) {
|
||||
case 0:
|
||||
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
|
||||
if (priv->active_offloads & ENETC_F_RX_TSTAMP)
|
||||
enetc_get_rx_tstamp(rx_ring->ndev, rxbd, skb);
|
||||
@ -660,8 +674,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
|
||||
u32 bd_status;
|
||||
u16 size;
|
||||
|
||||
enetc_lock_mdio();
|
||||
|
||||
if (cleaned_cnt >= ENETC_RXBD_BUNDLE) {
|
||||
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,
|
||||
|
||||
rxbd = enetc_rxbd(rx_ring, i);
|
||||
bd_status = le32_to_cpu(rxbd->r.lstatus);
|
||||
if (!bd_status) {
|
||||
enetc_unlock_mdio();
|
||||
if (!bd_status)
|
||||
break;
|
||||
}
|
||||
|
||||
enetc_wr_reg_hot(rx_ring->idr, BIT(rx_ring->index));
|
||||
dma_rmb(); /* for reading other rxbd fields */
|
||||
size = le16_to_cpu(rxbd->r.buf_len);
|
||||
skb = enetc_map_rx_buff_to_skb(rx_ring, i, size);
|
||||
if (!skb) {
|
||||
enetc_unlock_mdio();
|
||||
if (!skb)
|
||||
break;
|
||||
}
|
||||
|
||||
enetc_get_offloads(rx_ring, rxbd, skb);
|
||||
|
||||
@ -696,7 +704,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
|
||||
|
||||
if (unlikely(bd_status &
|
||||
ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK))) {
|
||||
enetc_unlock_mdio();
|
||||
dev_kfree_skb(skb);
|
||||
while (!(bd_status & ENETC_RXBD_LSTATUS_F)) {
|
||||
dma_rmb();
|
||||
@ -736,8 +743,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
|
||||
|
||||
enetc_process_skb(rx_ring, skb);
|
||||
|
||||
enetc_unlock_mdio();
|
||||
|
||||
napi_gro_receive(napi, skb);
|
||||
|
||||
rx_frm_cnt++;
|
||||
@ -984,7 +989,7 @@ static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv)
|
||||
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);
|
||||
|
||||
@ -1005,7 +1010,7 @@ static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
|
||||
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);
|
||||
|
||||
@ -1013,7 +1018,7 @@ static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
|
||||
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 */
|
||||
enetc_wr(hw, ENETC_SICAR2,
|
||||
@ -1033,7 +1038,7 @@ static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
|
||||
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);
|
||||
}
|
||||
@ -1058,13 +1063,12 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
|
||||
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_hw *hw = &si->hw;
|
||||
int err;
|
||||
|
||||
enetc_setup_cbdr(hw, &si->cbd_ring);
|
||||
/* set SI cache attributes */
|
||||
enetc_wr(hw, ENETC_SICAR0,
|
||||
ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
|
||||
@ -1112,6 +1116,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
enetc_setup_cbdr(&si->hw, &si->cbd_ring);
|
||||
|
||||
priv->cls_rules = kcalloc(si->num_fs_entries, sizeof(*priv->cls_rules),
|
||||
GFP_KERNEL);
|
||||
if (!priv->cls_rules) {
|
||||
@ -1119,14 +1125,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
|
||||
goto err_alloc_cls;
|
||||
}
|
||||
|
||||
err = enetc_configure_si(priv);
|
||||
if (err)
|
||||
goto err_config_si;
|
||||
|
||||
return 0;
|
||||
|
||||
err_config_si:
|
||||
kfree(priv->cls_rules);
|
||||
err_alloc_cls:
|
||||
enetc_clear_cbdr(&si->hw);
|
||||
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)
|
||||
rx_ring->idr = hw->reg + ENETC_SIRXIDR;
|
||||
|
||||
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 */
|
||||
enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
|
||||
|
@ -292,6 +292,7 @@ void enetc_get_si_caps(struct enetc_si *si);
|
||||
void enetc_init_si_rings_params(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);
|
||||
int enetc_configure_si(struct enetc_ndev_priv *priv);
|
||||
|
||||
int enetc_open(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,
|
||||
void enetc_set_ethtool_ops(struct net_device *ndev);
|
||||
|
||||
/* 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,
|
||||
char *mac_addr, int si_map);
|
||||
int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
|
||||
|
@ -172,6 +172,8 @@ enum enetc_bdr_type {TX, RX};
|
||||
#define ENETC_PSIPMAR0(n) (0x0100 + (n) * 0x8) /* n = SI index */
|
||||
#define ENETC_PSIPMAR1(n) (0x0104 + (n) * 0x8)
|
||||
#define ENETC_PVCLCTR 0x0208
|
||||
#define ENETC_PCVLANR1 0x0210
|
||||
#define ENETC_PCVLANR2 0x0214
|
||||
#define ENETC_VLAN_TYPE_C BIT(0)
|
||||
#define ENETC_VLAN_TYPE_S BIT(1)
|
||||
#define ENETC_PVCLCTR_OVTPIDL(bmp) ((bmp) & 0xff) /* VLAN_TYPE */
|
||||
@ -236,10 +238,17 @@ enum enetc_bdr_type {TX, RX};
|
||||
#define ENETC_PM_IMDIO_BASE 0x8030
|
||||
|
||||
#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_RGAUTO (BIT(15) | ENETC_PMO_IFM_RG | BIT(1))
|
||||
#define ENETC_PM0_IFM_XGMII BIT(12)
|
||||
#define ENETC_PM0_IFM_EN_AUTO BIT(15)
|
||||
#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_MSK GENMASK(15, 0)
|
||||
#define ENETC_PSFCAPR 0x1b18
|
||||
@ -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_rd(hw, off) enetc_rd_reg((hw)->reg + (off))
|
||||
#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))
|
||||
/* port register accessors - PF only */
|
||||
#define enetc_port_rd(hw, off) enetc_rd_reg((hw)->port + (off))
|
||||
@ -568,6 +579,7 @@ union enetc_rx_bd {
|
||||
#define ENETC_RXBD_LSTATUS(flags) ((flags) << 16)
|
||||
#define ENETC_RXBD_FLAG_VLAN BIT(9)
|
||||
#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 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)
|
||||
{
|
||||
struct enetc_ndev_priv *priv = netdev_priv(ndev);
|
||||
struct enetc_pf *pf = enetc_si_priv(priv->si);
|
||||
char vlan_promisc_simap = pf->vlan_promisc_simap;
|
||||
struct enetc_hw *hw = &priv->si->hw;
|
||||
bool uprom = false, mprom = false;
|
||||
struct enetc_mac_filter *filter;
|
||||
@ -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);
|
||||
uprom = true;
|
||||
mprom = true;
|
||||
/* Enable VLAN promiscuous mode for SI0 (PF) */
|
||||
vlan_promisc_simap |= BIT(0);
|
||||
} else if (ndev->flags & IFF_ALLMULTI) {
|
||||
/* enable multi cast promisc mode for SI0 (PF) */
|
||||
psipmr = ENETC_PSIPMR_SET_MP(0);
|
||||
mprom = true;
|
||||
}
|
||||
|
||||
enetc_set_vlan_promisc(&pf->si->hw, vlan_promisc_simap);
|
||||
|
||||
/* first 2 filter entries belong to PF */
|
||||
if (!uprom) {
|
||||
/* Update unicast filters */
|
||||
@ -320,7 +315,7 @@ static void enetc_set_loopback(struct net_device *ndev, bool en)
|
||||
u32 reg;
|
||||
|
||||
reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
|
||||
if (reg & ENETC_PMO_IFM_RG) {
|
||||
if (reg & ENETC_PM0_IFM_RG) {
|
||||
/* RGMII mode */
|
||||
reg = (reg & ~ENETC_PM0_IFM_RLP) |
|
||||
(en ? ENETC_PM0_IFM_RLP : 0);
|
||||
@ -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)
|
||||
{
|
||||
/* set auto-speed for RGMII */
|
||||
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);
|
||||
u32 val;
|
||||
|
||||
if (phy_mode == PHY_INTERFACE_MODE_USXGMII)
|
||||
enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_XGMII);
|
||||
if (phy_interface_mode_is_rgmii(phy_mode)) {
|
||||
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)
|
||||
@ -937,6 +939,34 @@ static void enetc_pl_mac_config(struct phylink_config *config,
|
||||
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,
|
||||
struct phy_device *phy, unsigned int mode,
|
||||
phy_interface_t interface, int speed,
|
||||
@ -949,6 +979,10 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
|
||||
if (priv->active_offloads & ENETC_F_QBV)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1041,6 +1075,26 @@ static int enetc_init_port_rss_memory(struct enetc_si *si)
|
||||
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,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
@ -1051,11 +1105,6 @@ static int enetc_pf_probe(struct pci_dev *pdev,
|
||||
struct enetc_pf *pf;
|
||||
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));
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "PCI probing failed\n");
|
||||
@ -1069,6 +1118,13 @@ static int enetc_pf_probe(struct pci_dev *pdev,
|
||||
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->si = si;
|
||||
pf->total_vfs = pci_sriov_get_totalvfs(pdev);
|
||||
@ -1108,6 +1164,12 @@ static int enetc_pf_probe(struct pci_dev *pdev,
|
||||
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);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "MSIX alloc failed\n");
|
||||
@ -1136,6 +1198,7 @@ err_phylink_create:
|
||||
enetc_mdiobus_destroy(pf);
|
||||
err_mdiobus_create:
|
||||
enetc_free_msix(priv);
|
||||
err_config_si:
|
||||
err_init_port_rss:
|
||||
err_init_port_rfs:
|
||||
err_alloc_msix:
|
||||
@ -1144,6 +1207,7 @@ err_alloc_si_res:
|
||||
si->ndev = NULL;
|
||||
free_netdev(ndev);
|
||||
err_alloc_netdev:
|
||||
err_device_disabled:
|
||||
err_map_pf_space:
|
||||
enetc_pci_remove(pdev);
|
||||
|
||||
|
@ -171,6 +171,12 @@ static int enetc_vf_probe(struct pci_dev *pdev,
|
||||
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);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "MSIX alloc failed\n");
|
||||
@ -187,6 +193,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
|
||||
|
||||
err_reg_netdev:
|
||||
enetc_free_msix(priv);
|
||||
err_config_si:
|
||||
err_alloc_msix:
|
||||
enetc_free_si_resources(priv);
|
||||
err_alloc_si_res:
|
||||
|
Loading…
Reference in New Issue
Block a user