librecmc : Bump to v1.5.15
[librecmc/librecmc.git] / target / linux / ar71xx / files / drivers / net / ethernet / atheros / ag71xx / ag71xx_ethtool.c
1 /*
2  *  Atheros AR71xx built-in ethernet mac driver
3  *
4  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6  *
7  *  Based on Atheros' AG7100 driver
8  *
9  *  This program is free software; you can redistribute it and/or modify it
10  *  under the terms of the GNU General Public License version 2 as published
11  *  by the Free Software Foundation.
12  */
13
14 #include "ag71xx.h"
15 #include <linux/version.h>
16
17 static void ag71xx_ethtool_get_drvinfo(struct net_device *dev,
18                                        struct ethtool_drvinfo *info)
19 {
20         struct ag71xx *ag = netdev_priv(dev);
21
22         strcpy(info->driver, ag->pdev->dev.driver->name);
23         strcpy(info->version, AG71XX_DRV_VERSION);
24         strcpy(info->bus_info, dev_name(&ag->pdev->dev));
25 }
26
27 static u32 ag71xx_ethtool_get_msglevel(struct net_device *dev)
28 {
29         struct ag71xx *ag = netdev_priv(dev);
30
31         return ag->msg_enable;
32 }
33
34 static void ag71xx_ethtool_set_msglevel(struct net_device *dev, u32 msg_level)
35 {
36         struct ag71xx *ag = netdev_priv(dev);
37
38         ag->msg_enable = msg_level;
39 }
40
41 static void ag71xx_ethtool_get_ringparam(struct net_device *dev,
42                                          struct ethtool_ringparam *er)
43 {
44         struct ag71xx *ag = netdev_priv(dev);
45
46         er->tx_max_pending = AG71XX_TX_RING_SIZE_MAX;
47         er->rx_max_pending = AG71XX_RX_RING_SIZE_MAX;
48         er->rx_mini_max_pending = 0;
49         er->rx_jumbo_max_pending = 0;
50
51         er->tx_pending = BIT(ag->tx_ring.order);
52         er->rx_pending = BIT(ag->rx_ring.order);
53         er->rx_mini_pending = 0;
54         er->rx_jumbo_pending = 0;
55
56         if (ag->tx_ring.desc_split)
57                 er->tx_pending /= AG71XX_TX_RING_DS_PER_PKT;
58 }
59
60 static int ag71xx_ethtool_set_ringparam(struct net_device *dev,
61                                         struct ethtool_ringparam *er)
62 {
63         struct ag71xx *ag = netdev_priv(dev);
64         unsigned tx_size;
65         unsigned rx_size;
66         int err = 0;
67
68         if (er->rx_mini_pending != 0||
69             er->rx_jumbo_pending != 0 ||
70             er->rx_pending == 0 ||
71             er->tx_pending == 0)
72                 return -EINVAL;
73
74         tx_size = er->tx_pending < AG71XX_TX_RING_SIZE_MAX ?
75                   er->tx_pending : AG71XX_TX_RING_SIZE_MAX;
76
77         rx_size = er->rx_pending < AG71XX_RX_RING_SIZE_MAX ?
78                   er->rx_pending : AG71XX_RX_RING_SIZE_MAX;
79
80         if (netif_running(dev)) {
81                 err = dev->netdev_ops->ndo_stop(dev);
82                 if (err)
83                         return err;
84         }
85
86         if (ag->tx_ring.desc_split)
87                 tx_size *= AG71XX_TX_RING_DS_PER_PKT;
88
89         ag->tx_ring.order = ag71xx_ring_size_order(tx_size);
90         ag->rx_ring.order = ag71xx_ring_size_order(rx_size);
91
92         if (netif_running(dev))
93                 err = dev->netdev_ops->ndo_open(dev);
94
95         return err;
96 }
97
98 static int ag71xx_ethtool_nway_reset(struct net_device *dev)
99 {
100         struct ag71xx *ag = netdev_priv(dev);
101         struct phy_device *phydev = ag->phy_dev;
102
103         if (!phydev)
104                 return -ENODEV;
105
106         return genphy_restart_aneg(phydev);
107 }
108
109 struct ethtool_ops ag71xx_ethtool_ops = {
110         .get_drvinfo    = ag71xx_ethtool_get_drvinfo,
111         .get_msglevel   = ag71xx_ethtool_get_msglevel,
112         .set_msglevel   = ag71xx_ethtool_set_msglevel,
113         .get_ringparam  = ag71xx_ethtool_get_ringparam,
114         .set_ringparam  = ag71xx_ethtool_set_ringparam,
115         .get_link_ksettings = phy_ethtool_get_link_ksettings,
116         .set_link_ksettings = phy_ethtool_set_link_ksettings,
117         .get_link       = ethtool_op_get_link,
118         .get_ts_info    = ethtool_op_get_ts_info,
119         .nway_reset     = ag71xx_ethtool_nway_reset,
120 };