From 3308f15e4a74e33e8ccf7237b7842fdaf1b320ad Mon Sep 17 00:00:00 2001 From: Cristian Bercaru Date: Thu, 18 Apr 2013 19:08:33 +0300 Subject: dpaa_eth: add ethtool PAUSE frame support Change-Id: I52222f0bf60bb073bb3b77bf935a31e84b4939c0 Reviewed-on: http://git.am.freescale.net:8181/1545 Reviewed-by: Bucur Madalin-Cristian-B32716 Reviewed-by: Sovaiala Cristian-Constantin-B39531 Reviewed-by: Fleming Andrew-AFLEMING Tested-by: Fleming Andrew-AFLEMING diff --git a/drivers/net/ethernet/freescale/dpa/dpa-ethtool.c b/drivers/net/ethernet/freescale/dpa/dpa-ethtool.c index 1bdd8d2..2ba6966 100644 --- a/drivers/net/ethernet/freescale/dpa/dpa-ethtool.c +++ b/drivers/net/ethernet/freescale/dpa/dpa-ethtool.c @@ -168,12 +168,16 @@ void __cold dpa_get_pauseparam(struct net_device *net_dev, struct ethtool_pausep return; } - et_pauseparam->autoneg = priv->mac_dev->phy_dev->autoneg; + et_pauseparam->autoneg = priv->mac_dev->autoneg_pause; + et_pauseparam->rx_pause = priv->mac_dev->rx_pause; + et_pauseparam->tx_pause = priv->mac_dev->tx_pause; } int __cold dpa_set_pauseparam(struct net_device *net_dev, struct ethtool_pauseparam *et_pauseparam) { struct dpa_priv_s *priv; + int _errno; + bool en; priv = netdev_priv(net_dev); @@ -186,7 +190,23 @@ int __cold dpa_set_pauseparam(struct net_device *net_dev, struct ethtool_pausepa return -ENODEV; } - priv->mac_dev->phy_dev->autoneg = et_pauseparam->autoneg; + en = et_pauseparam->rx_pause ? true : false; + _errno = priv->mac_dev->set_rx_pause(priv->mac_dev, en); + if (unlikely(_errno < 0)) { + netdev_err(net_dev, "set_rx_pause() = %d\n", _errno); + return _errno; + } + + en = et_pauseparam->tx_pause ? true : false; + _errno = priv->mac_dev->set_tx_pause(priv->mac_dev, en); + if (unlikely(_errno < 0)) { + netdev_err(net_dev, "set_tx_pause() = %d\n", _errno); + return _errno; + } + + priv->mac_dev->autoneg_pause = et_pauseparam->autoneg; + priv->mac_dev->rx_pause = et_pauseparam->rx_pause; + priv->mac_dev->tx_pause = et_pauseparam->tx_pause; return 0; } diff --git a/drivers/net/ethernet/freescale/dpa/mac-api.c b/drivers/net/ethernet/freescale/dpa/mac-api.c index b7987fa..717e005 100644 --- a/drivers/net/ethernet/freescale/dpa/mac-api.c +++ b/drivers/net/ethernet/freescale/dpa/mac-api.c @@ -624,6 +624,49 @@ static void *get_mac_handle(struct mac_device *mac_dev) return (void*)priv->mac; } +static int __cold set_rx_pause(struct mac_device *mac_dev, bool en) +{ + int _errno; + t_Error err; + + /* if rx pause is enabled, do NOT ignore pause frames */ + err = FM_MAC_SetRxIgnorePauseFrames( + ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, !en); + + _errno = -GET_ERROR_TYPE(err); + if (_errno < 0) + dev_err(mac_dev->dev, + "FM_MAC_SetRxIgnorePauseFrames() = 0x%08x\n", err); + + return _errno; +} + +static int __cold set_tx_pause(struct mac_device *mac_dev, bool en) +{ + int _errno; + t_Error err; + + if (en) + err = FM_MAC_SetTxPauseFrames( + ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, + TX_PAUSE_PRIO_ENABLE, + TX_PAUSE_TIME_ENABLE, + TX_PAUSE_THRESH_DEFAULT); + else + err = FM_MAC_SetTxPauseFrames( + ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, + TX_PAUSE_PRIO_DISABLE, + TX_PAUSE_TIME_DISABLE, + TX_PAUSE_THRESH_DEFAULT); + + _errno = -GET_ERROR_TYPE(err); + if (_errno < 0) + dev_err(mac_dev->dev, + "FM_MAC_SetTxPauseFrames() = 0x%08x\n", err); + + return _errno; +} + static int __cold fm_rtc_enable(struct net_device *net_dev) { struct dpa_priv_s *priv = netdev_priv(net_dev); @@ -763,7 +806,6 @@ static int __cold fm_rtc_set_fiper(struct net_device *net_dev, uint32_t id, return _errno; } - void fm_mac_dump_regs(struct mac_device *mac_dev) { struct mac_priv_s *mac_priv = macdev_priv(mac_dev); @@ -784,6 +826,8 @@ static void __cold setup_dtsec(struct mac_device *mac_dev) mac_dev->ptp_enable = ptp_enable; mac_dev->ptp_disable = ptp_disable; mac_dev->get_mac_handle = get_mac_handle; + mac_dev->set_tx_pause = set_tx_pause; + mac_dev->set_rx_pause = set_rx_pause; mac_dev->fm_rtc_enable = fm_rtc_enable; mac_dev->fm_rtc_disable = fm_rtc_disable; mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt; @@ -804,6 +848,8 @@ static void __cold setup_xgmac(struct mac_device *mac_dev) mac_dev->change_addr = change_addr; mac_dev->set_multi = set_multi; mac_dev->uninit = uninit; + mac_dev->set_tx_pause = set_tx_pause; + mac_dev->set_rx_pause = set_rx_pause; } static void __cold setup_memac(struct mac_device *mac_dev) @@ -816,6 +862,8 @@ static void __cold setup_memac(struct mac_device *mac_dev) mac_dev->change_addr = change_addr; mac_dev->set_multi = set_multi; mac_dev->uninit = uninit; + mac_dev->set_tx_pause = set_tx_pause; + mac_dev->set_rx_pause = set_rx_pause; mac_dev->fm_rtc_enable = fm_rtc_enable; mac_dev->fm_rtc_disable = fm_rtc_disable; mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt; diff --git a/drivers/net/ethernet/freescale/dpa/mac.c b/drivers/net/ethernet/freescale/dpa/mac.c index 310b2a8..87739e9 100644 --- a/drivers/net/ethernet/freescale/dpa/mac.c +++ b/drivers/net/ethernet/freescale/dpa/mac.c @@ -166,6 +166,13 @@ static int __cold mac_probe(struct platform_device *_of_dev) INIT_LIST_HEAD(&mac_dev->mc_addr_list); + /* pause frame autonegotiation enabled*/ + mac_dev->autoneg_pause = true; + /* does not ignore PAUSE frames */ + mac_dev->rx_pause = true; + /* transmits PAUSE frames when congested */ + mac_dev->tx_pause = true; + /* Get the FM node */ dev_node = of_get_parent(mac_node); if (unlikely(dev_node == NULL)) { diff --git a/drivers/net/ethernet/freescale/dpa/mac.h b/drivers/net/ethernet/freescale/dpa/mac.h index 5cdb57c..9cf1740 100644 --- a/drivers/net/ethernet/freescale/dpa/mac.h +++ b/drivers/net/ethernet/freescale/dpa/mac.h @@ -67,6 +67,10 @@ struct mac_device { /* List of multicast addresses */ struct list_head mc_addr_list; + u32 autoneg_pause; + u32 rx_pause; + u32 tx_pause; + int (*init_phy)(struct net_device *net_dev); int (*init)(struct mac_device *mac_dev); int (*start)(struct mac_device *mac_dev); @@ -78,6 +82,8 @@ struct mac_device { int (*ptp_enable)(struct mac_device *mac_dev); int (*ptp_disable)(struct mac_device *mac_dev); void *(*get_mac_handle)(struct mac_device *mac_dev); + int (*set_rx_pause)(struct mac_device *mac_dev, bool en); + int (*set_tx_pause)(struct mac_device *mac_dev, bool en); int (*fm_rtc_enable)(struct net_device *net_dev); int (*fm_rtc_disable)(struct net_device *net_dev); int (*fm_rtc_get_cnt)(struct net_device *net_dev, uint64_t *ts); @@ -107,4 +113,10 @@ extern const char *mac_driver_description; extern const size_t mac_sizeof_priv[]; extern void (*const mac_setup[])(struct mac_device *mac_dev); +#define TX_PAUSE_PRIO_ENABLE 0 +#define TX_PAUSE_PRIO_DISABLE 0xff +#define TX_PAUSE_TIME_ENABLE 0xf000 +#define TX_PAUSE_TIME_DISABLE 0 +#define TX_PAUSE_THRESH_DEFAULT 0 + #endif /* __MAC_H */ -- cgit v0.10.2