diff options
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/stmmac_main.c')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 95 |
1 files changed, 48 insertions, 47 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c87202cbd3d6..8d9d6ecf8c63 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -931,6 +931,11 @@ static void stmmac_validate(struct phylink_config *config, if ((max_speed > 0) && (max_speed < 1000)) { phylink_set(mask, 1000baseT_Full); phylink_set(mask, 1000baseX_Full); + } else if (priv->plat->has_gmac4) { + if (!max_speed || max_speed >= 2500) { + phylink_set(mac_supported, 2500baseT_Full); + phylink_set(mac_supported, 2500baseX_Full); + } } else if (priv->plat->has_xgmac) { if (!max_speed || (max_speed >= 2500)) { phylink_set(mac_supported, 2500baseT_Full); @@ -996,29 +1001,14 @@ static void stmmac_validate(struct phylink_config *config, linkmode_andnot(state->advertising, state->advertising, mask); /* If PCS is supported, check which modes it supports. */ - stmmac_xpcs_validate(priv, &priv->hw->xpcs_args, supported, state); -} - -static void stmmac_mac_pcs_get_state(struct phylink_config *config, - struct phylink_link_state *state) -{ - struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); - - state->link = 0; - stmmac_xpcs_get_state(priv, &priv->hw->xpcs_args, state); + if (priv->hw->xpcs) + xpcs_validate(priv->hw->xpcs, supported, state); } static void stmmac_mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state) { - struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); - - stmmac_xpcs_config(priv, &priv->hw->xpcs_args, state); -} - -static void stmmac_mac_an_restart(struct phylink_config *config) -{ - /* Not Supported */ + /* Nothing to do, xpcs_config() handles everything */ } static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up) @@ -1031,8 +1021,8 @@ static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up) if (is_up && *hs_enable) { stmmac_fpe_send_mpacket(priv, priv->ioaddr, MPACKET_VERIFY); } else { - *lo_state = FPE_EVENT_UNKNOWN; - *lp_state = FPE_EVENT_UNKNOWN; + *lo_state = FPE_STATE_OFF; + *lp_state = FPE_STATE_OFF; } } @@ -1060,8 +1050,6 @@ static void stmmac_mac_link_up(struct phylink_config *config, struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); u32 ctrl; - stmmac_xpcs_link_up(priv, &priv->hw->xpcs_args, speed, interface); - ctrl = readl(priv->ioaddr + MAC_CTRL_REG); ctrl &= ~priv->hw->link.speed_mask; @@ -1154,9 +1142,7 @@ static void stmmac_mac_link_up(struct phylink_config *config, static const struct phylink_mac_ops stmmac_phylink_mac_ops = { .validate = stmmac_validate, - .mac_pcs_get_state = stmmac_mac_pcs_get_state, .mac_config = stmmac_mac_config, - .mac_an_restart = stmmac_mac_an_restart, .mac_link_down = stmmac_mac_link_down, .mac_link_up = stmmac_mac_link_up, }; @@ -1233,6 +1219,7 @@ static int stmmac_init_phy(struct net_device *dev) static int stmmac_phy_setup(struct stmmac_priv *priv) { + struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node); int mode = priv->plat->phy_interface; struct phylink *phylink; @@ -1242,7 +1229,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.pcs_poll = true; if (priv->plat->mdio_bus_data) priv->phylink_config.ovr_an_inband = - priv->plat->mdio_bus_data->xpcs_an_inband; + mdio_bus_data->xpcs_an_inband; if (!fwnode) fwnode = dev_fwnode(priv->device); @@ -1252,6 +1239,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) if (IS_ERR(phylink)) return PTR_ERR(phylink); + if (priv->hw->xpcs) + phylink_set_pcs(phylink, &priv->hw->xpcs->pcs); + priv->phylink = phylink; return 0; } @@ -3173,7 +3163,8 @@ static void stmmac_safety_feat_configuration(struct stmmac_priv *priv) { if (priv->dma_cap.asp) { netdev_info(priv->dev, "Enabling Safety Features\n"); - stmmac_safety_feat_config(priv, priv->ioaddr, priv->dma_cap.asp); + stmmac_safety_feat_config(priv, priv->ioaddr, priv->dma_cap.asp, + priv->plat->safety_feat_cfg); } else { netdev_info(priv->dev, "No Safety Features support found\n"); } @@ -3415,8 +3406,8 @@ static void stmmac_free_irq(struct net_device *dev, static int stmmac_request_irq_multi_msi(struct net_device *dev) { - enum request_irq_err irq_err = REQ_IRQ_ERR_NO; struct stmmac_priv *priv = netdev_priv(dev); + enum request_irq_err irq_err; cpumask_t cpu_mask; int irq_idx = 0; char *int_name; @@ -3563,8 +3554,8 @@ irq_error: static int stmmac_request_irq_single(struct net_device *dev) { - enum request_irq_err irq_err = REQ_IRQ_ERR_NO; struct stmmac_priv *priv = netdev_priv(dev); + enum request_irq_err irq_err; int ret; ret = request_irq(dev->irq, stmmac_interrupt, @@ -3574,7 +3565,7 @@ static int stmmac_request_irq_single(struct net_device *dev) "%s: ERROR: allocating the IRQ %d (error: %d)\n", __func__, dev->irq, ret); irq_err = REQ_IRQ_ERR_MAC; - return ret; + goto irq_error; } /* Request the Wake IRQ in case of another line @@ -3588,7 +3579,7 @@ static int stmmac_request_irq_single(struct net_device *dev) "%s: ERROR: allocating the WoL IRQ %d (%d)\n", __func__, priv->wol_irq, ret); irq_err = REQ_IRQ_ERR_WOL; - return ret; + goto irq_error; } } @@ -3638,6 +3629,7 @@ static int stmmac_request_irq(struct net_device *dev) int stmmac_open(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); + int mode = priv->plat->phy_interface; int bfsize = 0; u32 chan; int ret; @@ -3650,7 +3642,8 @@ int stmmac_open(struct net_device *dev) if (priv->hw->pcs != STMMAC_PCS_TBI && priv->hw->pcs != STMMAC_PCS_RTBI && - priv->hw->xpcs_args.an_mode != DW_AN_C73) { + (!priv->hw->xpcs || + xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73)) { ret = stmmac_init_phy(dev); if (ret) { netdev_err(priv->dev, @@ -4658,7 +4651,6 @@ static int stmmac_xdp_xmit_back(struct stmmac_priv *priv, return res; } -/* This function assumes rcu_read_lock() is held by the caller. */ static int __stmmac_xdp_run_prog(struct stmmac_priv *priv, struct bpf_prog *prog, struct xdp_buff *xdp) @@ -4700,17 +4692,14 @@ static struct sk_buff *stmmac_xdp_run_prog(struct stmmac_priv *priv, struct bpf_prog *prog; int res; - rcu_read_lock(); - prog = READ_ONCE(priv->xdp_prog); if (!prog) { res = STMMAC_XDP_PASS; - goto unlock; + goto out; } res = __stmmac_xdp_run_prog(priv, prog, xdp); -unlock: - rcu_read_unlock(); +out: return ERR_PTR(-res); } @@ -4980,10 +4969,8 @@ read_again: buf->xdp->data_end = buf->xdp->data + buf1_len; xsk_buff_dma_sync_for_cpu(buf->xdp, rx_q->xsk_pool); - rcu_read_lock(); prog = READ_ONCE(priv->xdp_prog); res = __stmmac_xdp_run_prog(priv, prog, buf->xdp); - rcu_read_unlock(); switch (res) { case STMMAC_XDP_PASS: @@ -5138,7 +5125,7 @@ read_again: /* Buffer is good. Go on. */ - prefetch(page_address(buf->page)); + prefetch(page_address(buf->page) + buf->page_offset); if (buf->sec_page) prefetch(page_address(buf->sec_page)); @@ -5171,12 +5158,9 @@ read_again: dma_sync_single_for_cpu(priv->device, buf->addr, buf1_len, dma_dir); - xdp.data = page_address(buf->page) + buf->page_offset; - xdp.data_end = xdp.data + buf1_len; - xdp.data_hard_start = page_address(buf->page); - xdp_set_data_meta_invalid(&xdp); - xdp.frame_sz = buf_sz; - xdp.rxq = &rx_q->xdp_rxq; + xdp_init_buff(&xdp, buf_sz, &rx_q->xdp_rxq); + xdp_prepare_buff(&xdp, page_address(buf->page), + buf->page_offset, buf1_len, false); pre_len = xdp.data_end - xdp.data_hard_start - buf->page_offset; @@ -6545,7 +6529,8 @@ static int stmmac_hw_init(struct stmmac_priv *priv) * register (if supported). */ priv->plat->enh_desc = priv->dma_cap.enh_desc; - priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; + priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up && + !priv->plat->use_phy_wol; priv->hw->pmt = priv->plat->pmt; if (priv->dma_cap.hash_tb_sz) { priv->hw->multicast_filter_bins = @@ -6854,6 +6839,11 @@ int stmmac_dvr_probe(struct device *device, reset_control_reset(priv->plat->stmmac_rst); } + ret = reset_control_deassert(priv->plat->stmmac_ahb_rst); + if (ret == -ENOTSUPP) + dev_err(priv->device, "unable to bring out of ahb reset: %pe\n", + ERR_PTR(ret)); + /* Init MAC and get the capabilities */ ret = stmmac_hw_init(priv); if (ret) @@ -7005,6 +6995,15 @@ int stmmac_dvr_probe(struct device *device, } } + if (priv->plat->speed_mode_2500) + priv->plat->speed_mode_2500(ndev, priv->plat->bsp_priv); + + if (priv->plat->mdio_bus_data && priv->plat->mdio_bus_data->has_xpcs) { + ret = stmmac_xpcs_setup(priv->mii); + if (ret) + goto error_xpcs_setup; + } + ret = stmmac_phy_setup(priv); if (ret) { netdev_err(ndev, "failed to setup phy (%d)\n", ret); @@ -7041,6 +7040,7 @@ error_serdes_powerup: unregister_netdev(ndev); error_netdev_register: phylink_destroy(priv->phylink); +error_xpcs_setup: error_phy_setup: if (priv->hw->pcs != STMMAC_PCS_TBI && priv->hw->pcs != STMMAC_PCS_RTBI) @@ -7085,6 +7085,7 @@ int stmmac_dvr_remove(struct device *dev) phylink_destroy(priv->phylink); if (priv->plat->stmmac_rst) reset_control_assert(priv->plat->stmmac_rst); + reset_control_assert(priv->plat->stmmac_ahb_rst); pm_runtime_put(dev); pm_runtime_disable(dev); if (priv->hw->pcs != STMMAC_PCS_TBI && |