Commit 883b5984 authored by Jiawen Wu's avatar Jiawen Wu Committed by David S. Miller

net: wangxun: add ethtool_ops for ring parameters

Support to query RX/TX depth with ethtool -g, and change RX/TX depth
with ethtool -G.
Signed-off-by: default avatarJiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2fe2ca09
...@@ -229,3 +229,21 @@ int wx_set_pauseparam(struct net_device *netdev, ...@@ -229,3 +229,21 @@ int wx_set_pauseparam(struct net_device *netdev,
return phylink_ethtool_set_pauseparam(wx->phylink, pause); return phylink_ethtool_set_pauseparam(wx->phylink, pause);
} }
EXPORT_SYMBOL(wx_set_pauseparam); EXPORT_SYMBOL(wx_set_pauseparam);
void wx_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct wx *wx = netdev_priv(netdev);
ring->rx_max_pending = WX_MAX_RXD;
ring->tx_max_pending = WX_MAX_TXD;
ring->rx_mini_max_pending = 0;
ring->rx_jumbo_max_pending = 0;
ring->rx_pending = wx->rx_ring_count;
ring->tx_pending = wx->tx_ring_count;
ring->rx_mini_pending = 0;
ring->rx_jumbo_pending = 0;
}
EXPORT_SYMBOL(wx_get_ringparam);
...@@ -22,4 +22,8 @@ void wx_get_pauseparam(struct net_device *netdev, ...@@ -22,4 +22,8 @@ void wx_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause); struct ethtool_pauseparam *pause);
int wx_set_pauseparam(struct net_device *netdev, int wx_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause); struct ethtool_pauseparam *pause);
void wx_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack);
#endif /* _WX_ETHTOOL_H_ */ #endif /* _WX_ETHTOOL_H_ */
...@@ -2671,4 +2671,70 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features) ...@@ -2671,4 +2671,70 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
} }
EXPORT_SYMBOL(wx_set_features); EXPORT_SYMBOL(wx_set_features);
void wx_set_ring(struct wx *wx, u32 new_tx_count,
u32 new_rx_count, struct wx_ring *temp_ring)
{
int i, err = 0;
/* Setup new Tx resources and free the old Tx resources in that order.
* We can then assign the new resources to the rings via a memcpy.
* The advantage to this approach is that we are guaranteed to still
* have resources even in the case of an allocation failure.
*/
if (new_tx_count != wx->tx_ring_count) {
for (i = 0; i < wx->num_tx_queues; i++) {
memcpy(&temp_ring[i], wx->tx_ring[i],
sizeof(struct wx_ring));
temp_ring[i].count = new_tx_count;
err = wx_setup_tx_resources(&temp_ring[i]);
if (err) {
wx_err(wx, "setup new tx resources failed, keep using the old config\n");
while (i) {
i--;
wx_free_tx_resources(&temp_ring[i]);
}
return;
}
}
for (i = 0; i < wx->num_tx_queues; i++) {
wx_free_tx_resources(wx->tx_ring[i]);
memcpy(wx->tx_ring[i], &temp_ring[i],
sizeof(struct wx_ring));
}
wx->tx_ring_count = new_tx_count;
}
/* Repeat the process for the Rx rings if needed */
if (new_rx_count != wx->rx_ring_count) {
for (i = 0; i < wx->num_rx_queues; i++) {
memcpy(&temp_ring[i], wx->rx_ring[i],
sizeof(struct wx_ring));
temp_ring[i].count = new_rx_count;
err = wx_setup_rx_resources(&temp_ring[i]);
if (err) {
wx_err(wx, "setup new rx resources failed, keep using the old config\n");
while (i) {
i--;
wx_free_rx_resources(&temp_ring[i]);
}
return;
}
}
for (i = 0; i < wx->num_rx_queues; i++) {
wx_free_rx_resources(wx->rx_ring[i]);
memcpy(wx->rx_ring[i], &temp_ring[i],
sizeof(struct wx_ring));
}
wx->rx_ring_count = new_rx_count;
}
}
EXPORT_SYMBOL(wx_set_ring);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -29,5 +29,7 @@ int wx_setup_resources(struct wx *wx); ...@@ -29,5 +29,7 @@ int wx_setup_resources(struct wx *wx);
void wx_get_stats64(struct net_device *netdev, void wx_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats); struct rtnl_link_stats64 *stats);
int wx_set_features(struct net_device *netdev, netdev_features_t features); int wx_set_features(struct net_device *netdev, netdev_features_t features);
void wx_set_ring(struct wx *wx, u32 new_tx_count,
u32 new_rx_count, struct wx_ring *temp_ring);
#endif /* _NGBE_LIB_H_ */ #endif /* _NGBE_LIB_H_ */
...@@ -412,6 +412,12 @@ enum WX_MSCA_CMD_value { ...@@ -412,6 +412,12 @@ enum WX_MSCA_CMD_value {
#define WX_MAX_RXD 8192 #define WX_MAX_RXD 8192
#define WX_MAX_TXD 8192 #define WX_MAX_TXD 8192
#define WX_MIN_RXD 128
#define WX_MIN_TXD 128
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
#define WX_REQ_RX_DESCRIPTOR_MULTIPLE 8
#define WX_REQ_TX_DESCRIPTOR_MULTIPLE 8
#define WX_MAX_JUMBO_FRAME_SIZE 9432 /* max payload 9414 */ #define WX_MAX_JUMBO_FRAME_SIZE 9432 /* max payload 9414 */
#define VMDQ_P(p) p #define VMDQ_P(p) p
......
...@@ -7,7 +7,10 @@ ...@@ -7,7 +7,10 @@
#include "../libwx/wx_ethtool.h" #include "../libwx/wx_ethtool.h"
#include "../libwx/wx_type.h" #include "../libwx/wx_type.h"
#include "../libwx/wx_lib.h"
#include "../libwx/wx_hw.h"
#include "ngbe_ethtool.h" #include "ngbe_ethtool.h"
#include "ngbe_type.h"
static void ngbe_get_wol(struct net_device *netdev, static void ngbe_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol) struct ethtool_wolinfo *wol)
...@@ -41,6 +44,54 @@ static int ngbe_set_wol(struct net_device *netdev, ...@@ -41,6 +44,54 @@ static int ngbe_set_wol(struct net_device *netdev,
return 0; return 0;
} }
static int ngbe_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct wx *wx = netdev_priv(netdev);
u32 new_rx_count, new_tx_count;
struct wx_ring *temp_ring;
int i;
new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
if (new_tx_count == wx->tx_ring_count &&
new_rx_count == wx->rx_ring_count)
return 0;
if (!netif_running(wx->netdev)) {
for (i = 0; i < wx->num_tx_queues; i++)
wx->tx_ring[i]->count = new_tx_count;
for (i = 0; i < wx->num_rx_queues; i++)
wx->rx_ring[i]->count = new_rx_count;
wx->tx_ring_count = new_tx_count;
wx->rx_ring_count = new_rx_count;
return 0;
}
/* allocate temporary buffer to store rings in */
i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL);
if (!temp_ring)
return -ENOMEM;
ngbe_down(wx);
wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);
kvfree(temp_ring);
wx_configure(wx);
ngbe_up(wx);
return 0;
}
static const struct ethtool_ops ngbe_ethtool_ops = { static const struct ethtool_ops ngbe_ethtool_ops = {
.get_drvinfo = wx_get_drvinfo, .get_drvinfo = wx_get_drvinfo,
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
...@@ -56,6 +107,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = { ...@@ -56,6 +107,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
.get_pause_stats = wx_get_pause_stats, .get_pause_stats = wx_get_pause_stats,
.get_pauseparam = wx_get_pauseparam, .get_pauseparam = wx_get_pauseparam,
.set_pauseparam = wx_set_pauseparam, .set_pauseparam = wx_set_pauseparam,
.get_ringparam = wx_get_ringparam,
.set_ringparam = ngbe_set_ringparam,
}; };
void ngbe_set_ethtool_ops(struct net_device *netdev) void ngbe_set_ethtool_ops(struct net_device *netdev)
......
...@@ -334,7 +334,7 @@ static void ngbe_disable_device(struct wx *wx) ...@@ -334,7 +334,7 @@ static void ngbe_disable_device(struct wx *wx)
wx_update_stats(wx); wx_update_stats(wx);
} }
static void ngbe_down(struct wx *wx) void ngbe_down(struct wx *wx)
{ {
phylink_stop(wx->phylink); phylink_stop(wx->phylink);
ngbe_disable_device(wx); ngbe_disable_device(wx);
...@@ -342,7 +342,7 @@ static void ngbe_down(struct wx *wx) ...@@ -342,7 +342,7 @@ static void ngbe_down(struct wx *wx)
wx_clean_all_rx_rings(wx); wx_clean_all_rx_rings(wx);
} }
static void ngbe_up(struct wx *wx) void ngbe_up(struct wx *wx)
{ {
wx_configure_vectors(wx); wx_configure_vectors(wx);
......
...@@ -130,4 +130,7 @@ ...@@ -130,4 +130,7 @@
extern char ngbe_driver_name[]; extern char ngbe_driver_name[];
void ngbe_down(struct wx *wx);
void ngbe_up(struct wx *wx);
#endif /* _NGBE_TYPE_H_ */ #endif /* _NGBE_TYPE_H_ */
...@@ -7,9 +7,57 @@ ...@@ -7,9 +7,57 @@
#include "../libwx/wx_ethtool.h" #include "../libwx/wx_ethtool.h"
#include "../libwx/wx_type.h" #include "../libwx/wx_type.h"
#include "../libwx/wx_lib.h"
#include "txgbe_type.h" #include "txgbe_type.h"
#include "txgbe_ethtool.h" #include "txgbe_ethtool.h"
static int txgbe_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct wx *wx = netdev_priv(netdev);
u32 new_rx_count, new_tx_count;
struct wx_ring *temp_ring;
int i;
new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
if (new_tx_count == wx->tx_ring_count &&
new_rx_count == wx->rx_ring_count)
return 0;
if (!netif_running(wx->netdev)) {
for (i = 0; i < wx->num_tx_queues; i++)
wx->tx_ring[i]->count = new_tx_count;
for (i = 0; i < wx->num_rx_queues; i++)
wx->rx_ring[i]->count = new_rx_count;
wx->tx_ring_count = new_tx_count;
wx->rx_ring_count = new_rx_count;
return 0;
}
/* allocate temporary buffer to store rings in */
i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL);
if (!temp_ring)
return -ENOMEM;
txgbe_down(wx);
wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);
kvfree(temp_ring);
txgbe_up(wx);
return 0;
}
static const struct ethtool_ops txgbe_ethtool_ops = { static const struct ethtool_ops txgbe_ethtool_ops = {
.get_drvinfo = wx_get_drvinfo, .get_drvinfo = wx_get_drvinfo,
.nway_reset = wx_nway_reset, .nway_reset = wx_nway_reset,
...@@ -23,6 +71,8 @@ static const struct ethtool_ops txgbe_ethtool_ops = { ...@@ -23,6 +71,8 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
.get_pause_stats = wx_get_pause_stats, .get_pause_stats = wx_get_pause_stats,
.get_pauseparam = wx_get_pauseparam, .get_pauseparam = wx_get_pauseparam,
.set_pauseparam = wx_set_pauseparam, .set_pauseparam = wx_set_pauseparam,
.get_ringparam = wx_get_ringparam,
.set_ringparam = txgbe_set_ringparam,
}; };
void txgbe_set_ethtool_ops(struct net_device *netdev) void txgbe_set_ethtool_ops(struct net_device *netdev)
......
...@@ -288,7 +288,7 @@ static void txgbe_disable_device(struct wx *wx) ...@@ -288,7 +288,7 @@ static void txgbe_disable_device(struct wx *wx)
wx_update_stats(wx); wx_update_stats(wx);
} }
static void txgbe_down(struct wx *wx) void txgbe_down(struct wx *wx)
{ {
txgbe_disable_device(wx); txgbe_disable_device(wx);
txgbe_reset(wx); txgbe_reset(wx);
...@@ -298,6 +298,12 @@ static void txgbe_down(struct wx *wx) ...@@ -298,6 +298,12 @@ static void txgbe_down(struct wx *wx)
wx_clean_all_rx_rings(wx); wx_clean_all_rx_rings(wx);
} }
void txgbe_up(struct wx *wx)
{
wx_configure(wx);
txgbe_up_complete(wx);
}
/** /**
* txgbe_init_type_code - Initialize the shared code * txgbe_init_type_code - Initialize the shared code
* @wx: pointer to hardware structure * @wx: pointer to hardware structure
......
...@@ -129,6 +129,9 @@ ...@@ -129,6 +129,9 @@
extern char txgbe_driver_name[]; extern char txgbe_driver_name[];
void txgbe_down(struct wx *wx);
void txgbe_up(struct wx *wx);
#define NODE_PROP(_NAME, _PROP) \ #define NODE_PROP(_NAME, _PROP) \
(const struct software_node) { \ (const struct software_node) { \
.name = _NAME, \ .name = _NAME, \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment