summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorCristian Bercaru <cristian.bercaru@freescale.com>2014-07-23 11:12:25 (GMT)
committerMadalin Bucur <madalin.bucur@freescale.com>2014-10-08 13:20:00 (GMT)
commit4e96b2079d2b6570fc622f2123d800d6b6113777 (patch)
treeda2d17a47fdaa283eb7acf05d56b6188908dbaa5 /drivers
parent8f0464965a63eb46dd4e1f827b8b996226e70602 (diff)
downloadlinux-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.c30
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac-api.c44
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac.c18
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac.h10
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 */