aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-02-01 19:57:05 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-01 19:57:05 -0500
commite95c3edaaa4547387b36fbe13f27fa8cd788ebbc (patch)
treeb5ef2ec4c4d1ce8684000222739f1eb8354db927
parent65b80cae7a72e94df9335552e1a77a3a8946566c (diff)
parentbee7bacd18612564b85dc0b3e54063316c5bb32d (diff)
Merge branch 'ethoc'
Max Filippov says: ==================== OpenCores 10/100 MAC ethtool operations this series implements ethtool callbacks for the ethoc driver as was requested by Florian. Changes v1->v2: - fix {get,set}_settings return code in case there's no PHY; - fix set_ringparam: check ring sizes, change ring sizes on the fly. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ethoc.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 4de8cfd149cf..f9c1cf536298 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -51,6 +51,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
51#define ETH_HASH0 0x48 51#define ETH_HASH0 0x48
52#define ETH_HASH1 0x4c 52#define ETH_HASH1 0x4c
53#define ETH_TXCTRL 0x50 53#define ETH_TXCTRL 0x50
54#define ETH_END 0x54
54 55
55/* mode register */ 56/* mode register */
56#define MODER_RXEN (1 << 0) /* receive enable */ 57#define MODER_RXEN (1 << 0) /* receive enable */
@@ -179,6 +180,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
179 * @membase: pointer to buffer memory region 180 * @membase: pointer to buffer memory region
180 * @dma_alloc: dma allocated buffer size 181 * @dma_alloc: dma allocated buffer size
181 * @io_region_size: I/O memory region size 182 * @io_region_size: I/O memory region size
183 * @num_bd: number of buffer descriptors
182 * @num_tx: number of send buffers 184 * @num_tx: number of send buffers
183 * @cur_tx: last send buffer written 185 * @cur_tx: last send buffer written
184 * @dty_tx: last buffer actually sent 186 * @dty_tx: last buffer actually sent
@@ -199,6 +201,7 @@ struct ethoc {
199 int dma_alloc; 201 int dma_alloc;
200 resource_size_t io_region_size; 202 resource_size_t io_region_size;
201 203
204 unsigned int num_bd;
202 unsigned int num_tx; 205 unsigned int num_tx;
203 unsigned int cur_tx; 206 unsigned int cur_tx;
204 unsigned int dty_tx; 207 unsigned int dty_tx;
@@ -890,6 +893,102 @@ out:
890 return NETDEV_TX_OK; 893 return NETDEV_TX_OK;
891} 894}
892 895
896static int ethoc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
897{
898 struct ethoc *priv = netdev_priv(dev);
899 struct phy_device *phydev = priv->phy;
900
901 if (!phydev)
902 return -EOPNOTSUPP;
903
904 return phy_ethtool_gset(phydev, cmd);
905}
906
907static int ethoc_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
908{
909 struct ethoc *priv = netdev_priv(dev);
910 struct phy_device *phydev = priv->phy;
911
912 if (!phydev)
913 return -EOPNOTSUPP;
914
915 return phy_ethtool_sset(phydev, cmd);
916}
917
918static int ethoc_get_regs_len(struct net_device *netdev)
919{
920 return ETH_END;
921}
922
923static void ethoc_get_regs(struct net_device *dev, struct ethtool_regs *regs,
924 void *p)
925{
926 struct ethoc *priv = netdev_priv(dev);
927 u32 *regs_buff = p;
928 unsigned i;
929
930 regs->version = 0;
931 for (i = 0; i < ETH_END / sizeof(u32); ++i)
932 regs_buff[i] = ethoc_read(priv, i * sizeof(u32));
933}
934
935static void ethoc_get_ringparam(struct net_device *dev,
936 struct ethtool_ringparam *ring)
937{
938 struct ethoc *priv = netdev_priv(dev);
939
940 ring->rx_max_pending = priv->num_bd - 1;
941 ring->rx_mini_max_pending = 0;
942 ring->rx_jumbo_max_pending = 0;
943 ring->tx_max_pending = priv->num_bd - 1;
944
945 ring->rx_pending = priv->num_rx;
946 ring->rx_mini_pending = 0;
947 ring->rx_jumbo_pending = 0;
948 ring->tx_pending = priv->num_tx;
949}
950
951static int ethoc_set_ringparam(struct net_device *dev,
952 struct ethtool_ringparam *ring)
953{
954 struct ethoc *priv = netdev_priv(dev);
955
956 if (ring->tx_pending < 1 || ring->rx_pending < 1 ||
957 ring->tx_pending + ring->rx_pending > priv->num_bd)
958 return -EINVAL;
959 if (ring->rx_mini_pending || ring->rx_jumbo_pending)
960 return -EINVAL;
961
962 if (netif_running(dev)) {
963 netif_tx_disable(dev);
964 ethoc_disable_rx_and_tx(priv);
965 ethoc_disable_irq(priv, INT_MASK_TX | INT_MASK_RX);
966 synchronize_irq(dev->irq);
967 }
968
969 priv->num_tx = rounddown_pow_of_two(ring->tx_pending);
970 priv->num_rx = ring->rx_pending;
971 ethoc_init_ring(priv, dev->mem_start);
972
973 if (netif_running(dev)) {
974 ethoc_enable_irq(priv, INT_MASK_TX | INT_MASK_RX);
975 ethoc_enable_rx_and_tx(priv);
976 netif_wake_queue(dev);
977 }
978 return 0;
979}
980
981const struct ethtool_ops ethoc_ethtool_ops = {
982 .get_settings = ethoc_get_settings,
983 .set_settings = ethoc_set_settings,
984 .get_regs_len = ethoc_get_regs_len,
985 .get_regs = ethoc_get_regs,
986 .get_link = ethtool_op_get_link,
987 .get_ringparam = ethoc_get_ringparam,
988 .set_ringparam = ethoc_set_ringparam,
989 .get_ts_info = ethtool_op_get_ts_info,
990};
991
893static const struct net_device_ops ethoc_netdev_ops = { 992static const struct net_device_ops ethoc_netdev_ops = {
894 .ndo_open = ethoc_open, 993 .ndo_open = ethoc_open,
895 .ndo_stop = ethoc_stop, 994 .ndo_stop = ethoc_stop,
@@ -1016,6 +1115,7 @@ static int ethoc_probe(struct platform_device *pdev)
1016 ret = -ENODEV; 1115 ret = -ENODEV;
1017 goto error; 1116 goto error;
1018 } 1117 }
1118 priv->num_bd = num_bd;
1019 /* num_tx must be a power of two */ 1119 /* num_tx must be a power of two */
1020 priv->num_tx = rounddown_pow_of_two(num_bd >> 1); 1120 priv->num_tx = rounddown_pow_of_two(num_bd >> 1);
1021 priv->num_rx = num_bd - priv->num_tx; 1121 priv->num_rx = num_bd - priv->num_tx;
@@ -1111,6 +1211,7 @@ static int ethoc_probe(struct platform_device *pdev)
1111 netdev->netdev_ops = &ethoc_netdev_ops; 1211 netdev->netdev_ops = &ethoc_netdev_ops;
1112 netdev->watchdog_timeo = ETHOC_TIMEOUT; 1212 netdev->watchdog_timeo = ETHOC_TIMEOUT;
1113 netdev->features |= 0; 1213 netdev->features |= 0;
1214 netdev->ethtool_ops = &ethoc_ethtool_ops;
1114 1215
1115 /* setup NAPI */ 1216 /* setup NAPI */
1116 netif_napi_add(netdev, &priv->napi, ethoc_poll, 64); 1217 netif_napi_add(netdev, &priv->napi, ethoc_poll, 64);