aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2014-01-31 00:41:07 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-01 19:56:49 -0500
commitbee7bacd18612564b85dc0b3e54063316c5bb32d (patch)
treeb5ef2ec4c4d1ce8684000222739f1eb8354db927
parent1112909f76650e1d4c6de44b80c2d044c7c11e59 (diff)
net: ethoc: implement ethtool get/set ring parameters
TX and RX rings share memory and descriptors. Maximal number of descriptors reported is one less than the total available nuber of descriptors. For the set operation the requested number of TX descriptors is rounded down to the nearest power of two (driver logic requirement). Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ethoc.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 5da32a71e8ac..f9c1cf536298 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -180,6 +180,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
180 * @membase: pointer to buffer memory region 180 * @membase: pointer to buffer memory region
181 * @dma_alloc: dma allocated buffer size 181 * @dma_alloc: dma allocated buffer size
182 * @io_region_size: I/O memory region size 182 * @io_region_size: I/O memory region size
183 * @num_bd: number of buffer descriptors
183 * @num_tx: number of send buffers 184 * @num_tx: number of send buffers
184 * @cur_tx: last send buffer written 185 * @cur_tx: last send buffer written
185 * @dty_tx: last buffer actually sent 186 * @dty_tx: last buffer actually sent
@@ -200,6 +201,7 @@ struct ethoc {
200 int dma_alloc; 201 int dma_alloc;
201 resource_size_t io_region_size; 202 resource_size_t io_region_size;
202 203
204 unsigned int num_bd;
203 unsigned int num_tx; 205 unsigned int num_tx;
204 unsigned int cur_tx; 206 unsigned int cur_tx;
205 unsigned int dty_tx; 207 unsigned int dty_tx;
@@ -930,12 +932,60 @@ static void ethoc_get_regs(struct net_device *dev, struct ethtool_regs *regs,
930 regs_buff[i] = ethoc_read(priv, i * sizeof(u32)); 932 regs_buff[i] = ethoc_read(priv, i * sizeof(u32));
931} 933}
932 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
933const struct ethtool_ops ethoc_ethtool_ops = { 981const struct ethtool_ops ethoc_ethtool_ops = {
934 .get_settings = ethoc_get_settings, 982 .get_settings = ethoc_get_settings,
935 .set_settings = ethoc_set_settings, 983 .set_settings = ethoc_set_settings,
936 .get_regs_len = ethoc_get_regs_len, 984 .get_regs_len = ethoc_get_regs_len,
937 .get_regs = ethoc_get_regs, 985 .get_regs = ethoc_get_regs,
938 .get_link = ethtool_op_get_link, 986 .get_link = ethtool_op_get_link,
987 .get_ringparam = ethoc_get_ringparam,
988 .set_ringparam = ethoc_set_ringparam,
939 .get_ts_info = ethtool_op_get_ts_info, 989 .get_ts_info = ethtool_op_get_ts_info,
940}; 990};
941 991
@@ -1065,6 +1115,7 @@ static int ethoc_probe(struct platform_device *pdev)
1065 ret = -ENODEV; 1115 ret = -ENODEV;
1066 goto error; 1116 goto error;
1067 } 1117 }
1118 priv->num_bd = num_bd;
1068 /* num_tx must be a power of two */ 1119 /* num_tx must be a power of two */
1069 priv->num_tx = rounddown_pow_of_two(num_bd >> 1); 1120 priv->num_tx = rounddown_pow_of_two(num_bd >> 1);
1070 priv->num_rx = num_bd - priv->num_tx; 1121 priv->num_rx = num_bd - priv->num_tx;