diff options
author | Cristian Bercaru <cristian.bercaru@freescale.com> | 2014-07-23 11:12:25 (GMT) |
---|---|---|
committer | Madalin Bucur <madalin.bucur@freescale.com> | 2014-10-08 13:20:00 (GMT) |
commit | 4e96b2079d2b6570fc622f2123d800d6b6113777 (patch) | |
tree | da2d17a47fdaa283eb7acf05d56b6188908dbaa5 /drivers | |
parent | 8f0464965a63eb46dd4e1f827b8b996226e70602 (diff) | |
download | linux-fsl-qoriq-4e96b2079d2b6570fc622f2123d800d6b6113777.tar.xz |
dpaa_eth: add required and active PAUSE frame settings
Because the pause frame settings of a MAC device are forced to false
when the link goes half-duplex and cannot be restored if
autonegotiation is disabled, this patch introduces 2 sets of settings:
requested and active.
Requested settings are introduced by the users, via user-space
programs such as ethtool, whereas active settings reflect whether
FMan truly enables/disables PAUSE frames on TX/RX.
Requested settings can only be changed by the user. Active settings
can be changed by events such as auto-negotiation or a change in
link duplexity and are derived from requested settings.
Signed-off-by: Cristian Bercaru <cristian.bercaru@freescale.com>
Change-Id: I5ea563614b28d6ba1827b571097861d39ff8751a
Reviewed-on: http://git.am.freescale.net:8181/15553
Reviewed-by: Madalin-Cristian Bucur <madalin.bucur@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/mac-api.c | 44 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/mac.c | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/mac.h | 10 |
4 files changed, 36 insertions, 66 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c index 8a755ef..60a1b22 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c @@ -189,8 +189,8 @@ static void __cold dpa_get_pauseparam(struct net_device *net_dev, } epause->autoneg = mac_dev->autoneg_pause; - epause->rx_pause = mac_dev->rx_pause; - epause->tx_pause = mac_dev->tx_pause; + epause->rx_pause = mac_dev->rx_pause_active; + epause->tx_pause = mac_dev->tx_pause_active; } static int __cold dpa_set_pauseparam(struct net_device *net_dev, @@ -201,6 +201,7 @@ static int __cold dpa_set_pauseparam(struct net_device *net_dev, struct phy_device *phy_dev; int _errno; u32 newadv, oldadv; + bool rx_pause, tx_pause; priv = netdev_priv(net_dev); mac_dev = priv->mac_dev; @@ -226,6 +227,8 @@ static int __cold dpa_set_pauseparam(struct net_device *net_dev, * settings. */ mac_dev->autoneg_pause = !!epause->autoneg; + mac_dev->rx_pause_req = !!epause->rx_pause; + mac_dev->tx_pause_req = !!epause->tx_pause; /* Determine the sym/asym advertised PAUSE capabilities from the desired * rx/tx pause settings. @@ -254,25 +257,12 @@ static int __cold dpa_set_pauseparam(struct net_device *net_dev, } } - if (epause->autoneg) - return 0; - - /* If PAUSE frame autonegotiation is disabled, - * ethtool rx/tx settings are enforced. - */ - _errno = set_mac_rx_pause(mac_dev, !!epause->rx_pause); - if (unlikely(_errno < 0)) { - netdev_err(net_dev, "set_mac_rx_pause() = %d\n", _errno); - return _errno; - } - - _errno = set_mac_tx_pause(mac_dev, !!epause->tx_pause); - if (unlikely(_errno < 0)) { - netdev_err(net_dev, "set_mac_tx_pause() = %d\n", _errno); - return _errno; - } + get_pause_cfg(mac_dev, &rx_pause, &tx_pause); + _errno = set_mac_active_pause(mac_dev, rx_pause, tx_pause); + if (unlikely(_errno < 0)) + netdev_err(net_dev, "set_mac_active_pause() = %d\n", _errno); - return 0; + return _errno; } #ifdef CONFIG_PM diff --git a/drivers/net/ethernet/freescale/dpa/mac-api.c b/drivers/net/ethernet/freescale/dpa/mac-api.c index 3f79a1b..f5d6c73 100644 --- a/drivers/net/ethernet/freescale/dpa/mac-api.c +++ b/drivers/net/ethernet/freescale/dpa/mac-api.c @@ -330,33 +330,24 @@ static int __cold set_multi(struct net_device *net_dev, } /* Avoid redundant calls to FMD, if the MAC driver already contains the desired - * settings. Otherwise, the new MAC settings should be reflected in FMan. + * active PAUSE settings. Otherwise, the new active settings should be reflected + * in FMan. */ -int set_mac_rx_pause(struct mac_device *mac_dev, bool en) +int set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx) { - struct fm_mac_dev *fm_mac_dev; + struct fm_mac_dev *fm_mac_dev = mac_dev->get_mac_handle(mac_dev); int _errno = 0; - if (unlikely(en != mac_dev->rx_pause)) { - fm_mac_dev = mac_dev->get_mac_handle(mac_dev); - _errno = fm_mac_set_rx_pause_frames(fm_mac_dev, en); + if (unlikely(rx != mac_dev->rx_pause_active)) { + _errno = fm_mac_set_rx_pause_frames(fm_mac_dev, rx); if (likely(_errno == 0)) - mac_dev->rx_pause = en; + mac_dev->rx_pause_active = rx; } - return _errno; -} - -int set_mac_tx_pause(struct mac_device *mac_dev, bool en) -{ - int _errno = 0; - struct fm_mac_dev *fm_mac_dev; - - if (unlikely(en != mac_dev->tx_pause)) { - fm_mac_dev = mac_dev->get_mac_handle(mac_dev); - _errno = fm_mac_set_tx_pause_frames(fm_mac_dev, en); + if (unlikely(tx != mac_dev->tx_pause_active)) { + _errno = fm_mac_set_tx_pause_frames(fm_mac_dev, tx); if (likely(_errno == 0)) - mac_dev->tx_pause = en; + mac_dev->tx_pause_active = tx; } return _errno; @@ -365,8 +356,7 @@ int set_mac_tx_pause(struct mac_device *mac_dev, bool en) /* Determine the MAC RX/TX PAUSE frames settings based on PHY * autonegotiation or values set by eththool. */ -static void get_pause_cfg(struct mac_device *mac_dev, - bool *rx_pause, bool *tx_pause) +void get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, bool *tx_pause) { struct phy_device *phy_dev = mac_dev->phy_dev; u16 lcl_adv, rmt_adv; @@ -381,8 +371,8 @@ static void get_pause_cfg(struct mac_device *mac_dev, * are those set by ethtool. */ if (!mac_dev->autoneg_pause) { - *rx_pause = mac_dev->rx_pause; - *tx_pause = mac_dev->tx_pause; + *rx_pause = mac_dev->rx_pause_req; + *tx_pause = mac_dev->tx_pause_req; return; } @@ -428,13 +418,9 @@ static void adjust_link(struct net_device *net_dev) phy_dev->duplex); get_pause_cfg(mac_dev, &rx_pause, &tx_pause); - - _errno = set_mac_rx_pause(mac_dev, rx_pause); - if (unlikely(_errno < 0)) - netdev_err(net_dev, "set_rx_pause() = %d\n", _errno); - _errno = set_mac_tx_pause(mac_dev, tx_pause); + _errno = set_mac_active_pause(mac_dev, rx_pause, tx_pause); if (unlikely(_errno < 0)) - netdev_err(net_dev, "set_tx_pause() = %d\n", _errno); + netdev_err(net_dev, "set_mac_active_pause() = %d\n", _errno); } /* Initializes driver's PHY state, and attaches to the PHY. diff --git a/drivers/net/ethernet/freescale/dpa/mac.c b/drivers/net/ethernet/freescale/dpa/mac.c index 2c349ac..69b4b6c 100644 --- a/drivers/net/ethernet/freescale/dpa/mac.c +++ b/drivers/net/ethernet/freescale/dpa/mac.c @@ -364,19 +364,11 @@ static int __cold mac_probe(struct platform_device *_of_dev) /* by intializing the values to false, force FMD to enable PAUSE frames * on RX and TX */ - mac_dev->rx_pause = mac_dev->tx_pause = false; - /* does not ignore PAUSE frames */ - _errno = set_mac_rx_pause(mac_dev, true); - if (unlikely(_errno < 0)) { - dev_err(dev, "set_mac_rx_pause() = %d\n", _errno); - return _errno; - } - /* transmits PAUSE frames when congested */ - _errno = set_mac_tx_pause(mac_dev, true); - if (unlikely(_errno < 0)) { - dev_err(dev, "set_mac_tx_pause() = %d\n", _errno); - return _errno; - } + mac_dev->rx_pause_req = mac_dev->tx_pause_req = true; + mac_dev->rx_pause_active = mac_dev->tx_pause_active = false; + _errno = set_mac_active_pause(mac_dev, true, true); + if (unlikely(_errno < 0)) + dev_err(dev, "set_mac_active_pause() = %d\n", _errno); dev_info(dev, "FMan MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n", diff --git a/drivers/net/ethernet/freescale/dpa/mac.h b/drivers/net/ethernet/freescale/dpa/mac.h index d2ca0d0..f9e2db2 100644 --- a/drivers/net/ethernet/freescale/dpa/mac.h +++ b/drivers/net/ethernet/freescale/dpa/mac.h @@ -68,8 +68,10 @@ struct mac_device { struct list_head mc_addr_list; bool autoneg_pause; - bool rx_pause; - bool tx_pause; + bool rx_pause_req; + bool tx_pause_req; + bool rx_pause_active; + bool tx_pause_active; struct fm_mac_dev *(*get_mac_handle)(struct mac_device *mac_dev); int (*init_phy)(struct net_device *net_dev, struct mac_device *mac_dev); @@ -121,7 +123,7 @@ extern const char *mac_driver_description; extern const size_t mac_sizeof_priv[]; extern void (*const mac_setup[])(struct mac_device *mac_dev); -int set_mac_rx_pause(struct mac_device *mac_dev, bool en); -int set_mac_tx_pause(struct mac_device *mac_dev, bool en); +int set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx); +void get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, bool *tx_pause); #endif /* __MAC_H */ |