net: hinic3: PF initialization
Subsystems (4)
Fan Gong
maintainerv11 cover net: hinic3: PF initialization
From: Super User <[email protected]>
This is [3/3] part of hinic3 Ethernet driver second submission. With this patch hinic3 becomes a complete Ethernet driver with pf and vf.
Add 20 ethtool ops for information of queue, rss, coalesce and eth data. Add MTU size validation
Config netdev watchdog timeout.
Remove unneed coalesce parameters.
Changes:
PATCH 03 V01: https://lore.kernel.org/netdev/[email protected]/
* Add rmon/pause/phy/mac/ctrl stats (Ioana Ciornei)
PATCH 03 V02: https://lore.kernel.org/netdev/[email protected]/
* Modify "return -EINVAL" intension problem (AI review)
* Use le16_to_cpu for rss_indir pair.out->buf (AI review)
* Use u32 instead of int in coalesce_limits to avoid overflow (AI review)
* Remove redundant u64_stats_update_begin/end when reading stats without concurrent reader (AI review)
* Modify nic_dev->stats.syncp logic (AI review)
* Complete rxq/txq stats stats fileds in hinic3_rx/txq_get_stats (AI review)
* Remove statistics values in rtnl_link_stats64 from ethtool statistics values (AI review)
* Add channel_cfg_lock & channel_res_lock to protect resources access (AI review)
* Remove OutOfRangeLengthField, FrameToolong and InRangeLengthErrors (Ioana Ciornei)
* Remove redundant mtu commit (Maxime Chevialler)
PATCH 03 V03: https://lore.kernel.org/netdev/[email protected]/
* Change unnedd to unneeded (AI review)
* Remove packets,bytes,errors and dropped in hinic3_rx/tx_queue_stats (AI review)
* Remove duplicated entried in hinic3_port_stats[] (AI review)
* change stats_info.head.status to ps->head.status (AI review)
PATCH 03 V04: https://lore.kernel.org/netdev/[email protected]/
* Remove restore_drop_sge in hinic3_rx_queue_stats (AI review)
* Remove hinic3_nic_stats (AI review)
* Use old_q_param to store old config and use it in error handling (Mohsin Bashir)
* Add netdev_info to inform the user that depth is trimmed (Mohsin Bashir)
* Remove const in hinic3_get_qp_stats_strings parameters (Mohsin Bashir)
* Change EOPNOTSUPP to ERANGE in is_coalesce_exceed_limit (Mohsin Bashir)
* Update nic_dev->rss_type after hinic3_set_rss_type (Mohsin Bashir)
* Modify MGMT_STATUS_CMD_UNSUPPORTED to EOPNOTSUPP for complying with the error code specifications (Mohsin Bashir)
PATCH 03 V05: https://lore.kernel.org/netdev/[email protected]/
* Clear HINIC3_CHANGE_RES_INVALID bit in error handling (AI review)
* Use low >= high to avoid low=high in is_coalesce_legal (AI review)
* As tx and rx share interrupts, we only use ETHTOOL_COALESCE_RX_USECS for user setting to avoid user misunderstanding. So we do not add ETHTOOL_COALESCE_TX_USECS. (Mohsin Bashir & AI review)
PATCH 03 V06: https://lore.kernel.org/netdev/[email protected]/
* Remove redundant rx_jumbo_pending and rx_mini_pending judgement (Jakub Kicinski)
* Remove redundant max tx_pending judgement when .get_ringparam already got the max value (Jakub Kicinski)
* Use extack instead of netdev_err/netdev_info/netdev_warning (Jakub Kicinski)
* Remove HINIC3_CHANNEL_RES_VALID and only use HINIC3_CHANGE_RES_INVALID
bit (Jakub Kicinski)
* Deference freed pointers in hinic3_change_channel_settings error
handling (Jakub Kicinski)
* Modify hinic3_open_channel (Jakub Kicinski)
PATCH 03 V07: https://lore.kernel.org/netdev/[email protected]/
* Remove the trailing '\n' in NL_SET_ERR_MSG* (Jakub Kicinski)
PATCH 03 V08: https://lore.kernel.org/netdev/[email protected]/
* Update patch commit to be more accurate for change information (AI review)
* Modify <net/devlink.h> to <linux/netlink.h> (AI review)
* Use sq/rq_depth instead of rx/txqs[0].q_depth (AI review)
* hinic3_change_channel_settings() runs under change_res_mutex
to protect dynamic channel updates (AI review)
* hinic3_close() serializes close and channel reconfiguration paths (AI review)
* Remove useless u64_stats_init in hinic3_get_drv_queue_stats() (AI review)
* hinic3_get_drv_queue_stats() fills rxq stats at correct idx
when txq is null (AI review)
* Remove unnecessary semicolons after the closing bracket of
static inline functions (AI review)
* Disable preemption in hinic3_rx_fill_buffers() (AI review)
* Add spinlock to protect per-queue coalesce parameters from
concurrent access (AI review)
* Reject static coalesce config when adaptive RX coalesce is
enabled (AI review)
* Validate interface state and queue ID before modifying coalesce parameters (AI review)
* Differentiate get_coalesce output for adaptive/static modes and zero-fill the struct (AI review)
* Return -ERANGE for invalid coalesce frame limits and simplify
error message (AI review)
* Remove unused watchdog timeout definition and assignment (AI review)
* Return -EOPNOTSUPP when RSS type query is unsupported by firmware (AI review)
* Reject L4 hash bits for pure L3 flow types (AI review)
* Split RSS type conversion to correctly handle L3-only flows (AI review)
* Reprogram RSS indir table and HW parameters after channel count changes (AI review)
* Propagate exact error code from channel parameter validation (AI review)
* Update SW RSS indir copy only after HW programming succeeds (AI review)
* Program RSS hash type to HW before updating SW state to prevent inconsistency (AI review)
PATCH 03 V09: https://lore.kernel.org/netdev/[email protected]/
* Remove useless messages in hinic3_set_ringparam() (Jakub Kicinski)
* Solve the big-endian and little-endian issue (Jakub Kicinski)
PATCH 03 V10: https://lore.kernel.org/netdev/[email protected]/
* Unify 3 mutex in struct hinic3_nic_dev: port_state_mutex, change_res_mutex, coal_lock.
* Correct copy-paste error in hinic3_get_ringparam() (AI Review and Harshitha Ramamurthy)
* hinic3_set_interrupt_moder() now compare q_id and num_qps inside mutex lock (AI Review)
* Error branches in hinic3_link_status_change() goto unlock mutex before return (AI Review)
* In hinic3_change_channel_settings(), hinic3_config_num_qps() and hinic3_alloc_channel_resources() now run inside mutex lock. (AI Review)
* Call hinic3_free_qp_ctxts() in error paths of hinic3_open_channel(), thus hinic3_change_channel_settings() don't call it in error path (AI Review)
* Unset HINIC3_INTF_UP during close and reopen in hinic3_change_channel_settings
* hinic3_change_channel_settings() restore previous resources before freeing new_qp_params (AI Review)
* Delete unused macro HINIC3_LRO_PKT_HDR_LEN (AI Review)
* Drop packets when skb_checksum_help() return error (AI Review)
* Use rxq->q_mask instead of rxq->q_depth - 1 in hinic3_configure_rxqs() (Dimitri Daskalakis)
* Clarify extack error message in hinic3_check_ringparam_valid() (Harshitha Ramamurthy)
* Use rounddown_pow_of_two() instead of 1U << ilog2() in hinic3_set_ringparam() for readability. (Harshitha Ramamurthy)
* Protect interrupt coalesce parameter reads with state_lock to prevent data races(AI Review)
* Restore previous coalesce parameters on HW configuration failure (AI Review)
* Always report all coalesce parameters regardless of adaptive mode (AI Review)
* Safely stop DIM work when disabling adaptive RX coalescing (AI Review)
* Change coalesce disabled message from extack error to info log (AI Review)
* Implement dedicated get_rx_ring_count ethtool operation (Dimitri Daskalakis)
* Pass new RSS hash type to HW instead of the old one (AI Review)
* Initialize default RSS indirection table before HW programming when not user-configured(AI Review)
* Revert queue count on RSS reprogramming failure (AI Review)
* Use sizeof for RSS indirection table copy to prevent size mismatch (AI Review)
PATCH 03 V11:
* Remove state_lock in hinic3_set_interrupt_moder() and hinic3_link_status_change() (Andrew Lunn and AI Review)
* In hinic3_change_channel_settings(), cur_trxq_params is read after taking lock, and get symmetrically restored when alloc resources failed. (AI Review)
* Remove preempt_disable()/preempt_enable() pairs in hinic3_rx_fill_buffers(). (AI Review)
* Add a comment about csum_err, and rewrite its judgement in hinic3_rx_csum(). (AI Review)
* Rollback hash function type to previous state if setting RSS indirection table or key fails (AI Review)
* Allow users to disable L3 hashing for IPV4/IPV6 flows by properly handling empty hash tuple in ethtool (AI Review)
* Update software queue coalesce state only after successful hardware configuration to avoid manual rollback (AI Review)
* Use READ_ONCE and WRITE_ONCE for adaptive_rx_coal to ensure safe concurrent memory access (AI Review)
* Reset RX queue DIM state to DIM_START_MEASURE when canceling adaptive RX coalescing work (AI Review)
* Remove unnecessary state_lock mutexes when reading queue coalesce parameters in IRQ and update paths (AI Review)
* Rename is_coalesce_legal to hinic3_validate_coalesce for better code readability and naming consistency (AI Review)
Fan Gong (5):
hinic3: Add ethtool queue ops
hinic3: Add ethtool statistic ops
hinic3: Add ethtool coalesce ops
hinic3: Add ethtool rss ops
hinic3: Remove unneeded coalesce parameters
.../ethernet/huawei/hinic3/hinic3_ethtool.c | 870 +++++++++++++++++- .../ethernet/huawei/hinic3/hinic3_hw_intf.h | 11 + .../net/ethernet/huawei/hinic3/hinic3_irq.c | 18 +- .../net/ethernet/huawei/hinic3/hinic3_main.c | 6 +- .../huawei/hinic3/hinic3_mgmt_interface.h | 39 + .../huawei/hinic3/hinic3_netdev_ops.c | 106 ++- .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 64 ++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 109 +++ .../ethernet/huawei/hinic3/hinic3_nic_dev.h | 11 +- .../ethernet/huawei/hinic3/hinic3_nic_io.c | 4 +- .../ethernet/huawei/hinic3/hinic3_nic_io.h | 8 +- .../net/ethernet/huawei/hinic3/hinic3_rss.c | 561 ++++++++++- .../net/ethernet/huawei/hinic3/hinic3_rss.h | 20 + .../net/ethernet/huawei/hinic3/hinic3_rx.c | 71 +- .../net/ethernet/huawei/hinic3/hinic3_rx.h | 18 +- .../net/ethernet/huawei/hinic3/hinic3_tx.c | 69 +- .../net/ethernet/huawei/hinic3/hinic3_tx.h | 2 + 17 files changed, 1942 insertions(+), 45 deletions(-)
base-commit: ce6b4d3216b63f902bb8e9695ee6c10c83415f65
Signature · 1 line
2.54.0
Fan Gong
maintainerPATCH v11 1/5 hinic3: Add ethtool queue ops
Implement following ethtool callback function:
.get_ringparam
.set_ringparam
These callbacks allow users to utilize ethtool for detailed
queue depth configuration and monitoring.
Change port_state_mutex to state_lock as a unified mutex lock
in hinic3_nic_dev.
Tightens the success criterion for hinic3_rx_fill_buffers() inhinic3_configure_rxqs().
Changes hinic3_tx_csum()/hinic3_tx_offload() to propagateskb_checksum_help() failures into a TX drop.
Renames hinic3_uninit_qps() to hinic3_get_cur_qps().
Splits hinic3_open_channel() into hinic3_prepare_channel() andhinic3_open_channel().
--- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 91 +++++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_main.c | 4 +- .../huawei/hinic3/hinic3_netdev_ops.c | 106 ++++++++++++++++-- .../ethernet/huawei/hinic3/hinic3_nic_dev.h | 11 +- .../ethernet/huawei/hinic3/hinic3_nic_io.c | 4 +- .../ethernet/huawei/hinic3/hinic3_nic_io.h | 8 +- .../net/ethernet/huawei/hinic3/hinic3_rx.c | 2 +- .../net/ethernet/huawei/hinic3/hinic3_tx.c | 7 +- 8 files changed, 216 insertions(+), 17 deletions(-)
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +91 -0
@@ -9,6 +9,7 @@#include <linux/errno.h> #include <linux/etherdevice.h> #include <linux/netdevice.h> +#include <linux/netlink.h> #include <linux/ethtool.h> #include "hinic3_lld.h"
@@ -409,6 +410,94 @@ hinic3_get_link_ksettings(struct net_device *netdev,return 0 ; } +static void hinic3_get_ringparam (struct net_device *netdev, +struct ethtool_ringparam *ring, +struct kernel_ethtool_ringparam *kernel_ring, +struct netlink_ext_ack *extack) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); + + ring->rx_max_pending =HINIC3_MAX_RX_QUEUE_DEPTH ; + ring->tx_max_pending =HINIC3_MAX_TX_QUEUE_DEPTH ; + ring->rx_pending = nic_dev->q_params.rq_depth; + ring->tx_pending = nic_dev->q_params.sq_depth; +} + +static void hinic3_update_qp_depth (struct net_device *netdev, +u32 sq_depth,u32 rq_depth) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +u16 i; + + nic_dev->q_params.sq_depth = sq_depth; + nic_dev->q_params.rq_depth = rq_depth; +for (i =0 ; i < nic_dev->max_qps; i++) { + nic_dev->txqs[i].q_depth = sq_depth; + nic_dev->txqs[i].q_mask = sq_depth -1 ; + nic_dev->rxqs[i].q_depth = rq_depth; + nic_dev->rxqs[i].q_mask = rq_depth -1 ; + } +} + +static int hinic3_check_ringparam_valid (struct net_device *netdev, +const struct ethtool_ringparam *ring, +struct netlink_ext_ack *extack) +{ +if (ring->tx_pending <HINIC3_MIN_QUEUE_DEPTH || + ring->rx_pending <HINIC3_MIN_QUEUE_DEPTH ) { +NL_SET_ERR_MSG_FMT_MOD (extack, +"Queue depth underflow[%d]: tx[%d], rx[%d]" , +HINIC3_MIN_QUEUE_DEPTH , + ring->tx_pending, ring->rx_pending); + +return -EINVAL ; + } + +return 0 ; +} + +static int hinic3_set_ringparam (struct net_device *netdev, +struct ethtool_ringparam *ring, +struct kernel_ethtool_ringparam *kernel_ring, +struct netlink_ext_ack *extack) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct hinic3_dyna_txrxq_params q_params = {}; +u32 new_sq_depth, new_rq_depth; +int err; + + err =hinic3_check_ringparam_valid (netdev, ring, extack); +if (err) +return err; + + new_sq_depth =rounddown_pow_of_two (ring->tx_pending); + new_rq_depth =rounddown_pow_of_two (ring->rx_pending); +if (new_sq_depth == nic_dev->q_params.sq_depth && + new_rq_depth == nic_dev->q_params.rq_depth) +return 0 ; + +if (new_sq_depth != ring->tx_pending || + new_rq_depth != ring->rx_pending) +NL_SET_ERR_MSG_FMT_MOD (extack, +"Requested Tx/Rx ring depth %u/%u trimmed to %u/%u" , + ring->tx_pending, ring->rx_pending, + new_sq_depth, new_rq_depth); + +if (!netif_running (netdev)) { +hinic3_update_qp_depth (netdev, new_sq_depth, new_rq_depth); + }else { + q_params = nic_dev->q_params; + q_params.sq_depth = new_sq_depth; + q_params.rq_depth = new_rq_depth; + + err =hinic3_change_channel_settings (netdev, &q_params); +if (err) +return err; + } + +return 0 ; +} +static const struct ethtool_ops hinic3_ethtool_ops = { .supported_coalesce_params =ETHTOOL_COALESCE_USECS |ETHTOOL_COALESCE_PKT_RATE_RX_USECS ,
@@ -417,6 +506,8 @@ static const struct ethtool_ops hinic3_ethtool_ops = { .get_msglevel = hinic3_get_msglevel, .set_msglevel = hinic3_set_msglevel, .get_link = ethtool_op_get_link, + .get_ringparam = hinic3_get_ringparam, + .set_ringparam = hinic3_set_ringparam, };void hinic3_set_ethtool_ops (struct net_device *netdev)
drivers/net/ethernet/huawei/hinic3/hinic3_main.c +3 -1
@@ -178,7 +178,7 @@ static int hinic3_sw_init(struct net_device *netdev)u8 mac_addr[ETH_ALEN ];int err; -mutex_init (&nic_dev->port_state_mutex); +mutex_init (&nic_dev->state_lock); nic_dev->q_params.sq_depth =HINIC3_SQ_DEPTH ; nic_dev->q_params.rq_depth =HINIC3_RQ_DEPTH ;
@@ -330,6 +330,8 @@ static void hinic3_link_status_change(struct net_device *netdev,netif_carrier_off (netdev);netdev_dbg (netdev,"Link is down\n" ); } + +return ; } static void hinic3_port_module_event_handler(struct net_device *netdev,
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +99 -7
162 lines not on this page · raw message
drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h +9 -2
@@ -10,6 +10,9 @@#include "hinic3_hw_cfg.h" #include "hinic3_hwdev.h" #include "hinic3_mgmt_interface.h" +#include "hinic3_nic_io.h" +#include "hinic3_tx.h" +#include "hinic3_rx.h" #define HINIC3_VLAN_BITMAP_BYTE_SIZE (nic_dev) (sizeof(*(nic_dev)->vlan_bitmap))#define HINIC3_VLAN_BITMAP_SIZE (nic_dev) \
@@ -127,8 +130,8 @@ struct hinic3_nic_dev {struct workqueue_struct *workq;struct delayed_work periodic_work;struct work_struct rx_mode_work; -/* lock for enable/disable port */ -struct mutex port_state_mutex; +/* Protects Interface state */ +struct mutex state_lock;struct list_head uc_filter_list;struct list_head mc_filter_list;
@@ -143,6 +146,10 @@ struct hinic3_nic_dev {void hinic3_set_netdev_ops (struct net_device *netdev);int hinic3_set_hw_features (struct net_device *netdev); +int +hinic3_change_channel_settings (struct net_device *netdev, +struct hinic3_dyna_txrxq_params *trxq_params); +int hinic3_qps_irq_init (struct net_device *netdev);void hinic3_qps_irq_uninit (struct net_device *netdev);
drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c +2 -2
@@ -484,8 +484,8 @@ void hinic3_init_qps(struct hinic3_nic_dev *nic_dev, } } -void hinic3_uninit_qps (struct hinic3_nic_dev *nic_dev, -struct hinic3_dyna_qp_params *qp_params) +void hinic3_get_cur_qps (struct hinic3_nic_dev *nic_dev, +struct hinic3_dyna_qp_params *qp_params) {struct hinic3_nic_io *nic_io = nic_dev->nic_io;
drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h +6 -2
@@ -14,6 +14,10 @@ struct hinic3_nic_dev;#define HINIC3_RQ_WQEBB_SHIFT 3#define HINIC3_SQ_WQEBB_SIZE BIT(HINIC3_SQ_WQEBB_SHIFT) +#define HINIC3_MAX_TX_QUEUE_DEPTH 65536 +#define HINIC3_MAX_RX_QUEUE_DEPTH 16384 +#define HINIC3_MIN_QUEUE_DEPTH 128 +/* ******************** RQ_CTRL ******************** */ enum hinic3_rq_wqe_type {HINIC3_NORMAL_RQ_WQE =1 ,
@@ -136,8 +140,8 @@ void hinic3_free_qps(struct hinic3_nic_dev *nic_dev, struct hinic3_dyna_qp_params *qp_params);void hinic3_init_qps (struct hinic3_nic_dev *nic_dev,struct hinic3_dyna_qp_params *qp_params); -void hinic3_uninit_qps (struct hinic3_nic_dev *nic_dev, -struct hinic3_dyna_qp_params *qp_params); +void hinic3_get_cur_qps (struct hinic3_nic_dev *nic_dev, +struct hinic3_dyna_qp_params *qp_params);int hinic3_init_qp_ctxts (struct hinic3_nic_dev *nic_dev);void hinic3_free_qp_ctxts (struct hinic3_nic_dev *nic_dev);
drivers/net/ethernet/huawei/hinic3/hinic3_rx.c +1 -1
@@ -541,7 +541,7 @@ int hinic3_configure_rxqs(struct net_device *netdev, u16 num_rq,rq_associate_cqes (rxq); pkts =hinic3_rx_fill_buffers (rxq); -if (!pkts) { +if (pkts < rxq->q_mask) {netdev_err (netdev,"Failed to fill Rx buffer\n" );return -ENOMEM ; }
drivers/net/ethernet/huawei/hinic3/hinic3_tx.c +5 -2
@@ -261,8 +261,7 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struct hinic3_sq_task *task, ((struct udphdr *)skb_transport_header(skb))->dest != VXLAN_OFFLOAD_PORT_LE) {/* Unsupported tunnel packet, disable csum offload */ -skb_checksum_help (skb); -return 0 ; +return skb_checksum_help (skb); } }
@@ -412,6 +411,10 @@ static u32 hinic3_tx_offload(struct sk_buff *skb, struct hinic3_sq_task *task, offload |=HINIC3_TX_OFFLOAD_TSO ; }else { tso_cs_en =hinic3_tx_csum (txq, task, skb); +if (tso_cs_en <0 ) { + offload =HINIC3_TX_OFFLOAD_INVALID ; +return offload; + }if (tso_cs_en) offload |=HINIC3_TX_OFFLOAD_CSUM ; }
Signature · 1 line
2.54.0
Re: [PATCH net-next v11 1/5] hinic3: Add ethtool queue ops
Quoted 13 lines · Fan Gong
Implement following ethtool callback function:
.get_ringparam
.set_ringparamThese callbacks allow users to utilize ethtool for detailed
queue depth configuration and monitoring.Change
port_state_mutextostate_lockas a unified mutex lock
inhinic3_nic_dev.Tightens the success criterion for
hinic3_rx_fill_buffers()inhinic3_configure_rxqs().
Quoted 8 lines
Changes hinic3_tx_csum()/hinic3_tx_offload() to propagate
skb_checksum_help()failures into a TX drop.Renames
hinic3_uninit_qps()tohinic3_get_cur_qps().Splits
hinic3_open_channel()intohinic3_prepare_channel()andhinic3_open_channel().
It may just be me, but I feel like there is a lot going in this single patch. Ideally, a patch should carry one logical change. This patch is doing 3 things: refactor, new code, bug-fixing in the hinic3_close() path.
Quoted 146 lines
Co-developed-by Wu Di <[email protected]>Signed-off-by Wu Di <[email protected]>Co-developed-by Teng Peisen <[email protected]>Signed-off-by Teng Peisen <[email protected]>Signed-off-by Fan Gong <[email protected]>--- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 91 +++++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_main.c | 4 +- .../huawei/hinic3/hinic3_netdev_ops.c | 106 ++++++++++++++++-- .../ethernet/huawei/hinic3/hinic3_nic_dev.h | 11 +- .../ethernet/huawei/hinic3/hinic3_nic_io.c | 4 +- .../ethernet/huawei/hinic3/hinic3_nic_io.h | 8 +- .../net/ethernet/huawei/hinic3/hinic3_rx.c | 2 +- .../net/ethernet/huawei/hinic3/hinic3_tx.c | 7 +- 8 files changed, 216 insertions(+), 17 deletions(-)drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +91
-0@@ -9,6 +9,7 @@#include <linux/errno.h> #include <linux/etherdevice.h> #include <linux/netdevice.h> +#include <linux/netlink.h> #include <linux/ethtool.h> #include "hinic3_lld.h" @@ -409,6 +410,94 @@ hinic3_get_link_ksettings(struct net_device *netdev,return 0 ; } +static void hinic3_get_ringparam (struct net_device *netdev, +struct ethtool_ringparam *ring, +struct kernel_ethtool_ringparam *kernel_ring, +struct netlink_ext_ack *extack) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); + + ring->rx_max_pending =HINIC3_MAX_RX_QUEUE_DEPTH ; + ring->tx_max_pending =HINIC3_MAX_TX_QUEUE_DEPTH ; + ring->rx_pending = nic_dev->q_params.rq_depth; + ring->tx_pending = nic_dev->q_params.sq_depth; +} + +static void hinic3_update_qp_depth (struct net_device *netdev, +u32 sq_depth,u32 rq_depth) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +u16 i; + + nic_dev->q_params.sq_depth = sq_depth; + nic_dev->q_params.rq_depth = rq_depth; +for (i =0 ; i < nic_dev->max_qps; i++) { + nic_dev->txqs[i].q_depth = sq_depth; + nic_dev->txqs[i].q_mask = sq_depth -1 ; + nic_dev->rxqs[i].q_depth = rq_depth; + nic_dev->rxqs[i].q_mask = rq_depth -1 ; + } +} + +static int hinic3_check_ringparam_valid (struct net_device *netdev, +const struct ethtool_ringparam *ring, +struct netlink_ext_ack *extack) +{ +if (ring->tx_pending <HINIC3_MIN_QUEUE_DEPTH || + ring->rx_pending <HINIC3_MIN_QUEUE_DEPTH ) { +NL_SET_ERR_MSG_FMT_MOD (extack, +"Queue depth underflow[%d]: tx[%d], rx[%d]" , +HINIC3_MIN_QUEUE_DEPTH , + ring->tx_pending, ring->rx_pending); + +return -EINVAL ; + } + +return 0 ; +} + +static int hinic3_set_ringparam (struct net_device *netdev, +struct ethtool_ringparam *ring, +struct kernel_ethtool_ringparam *kernel_ring, +struct netlink_ext_ack *extack) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct hinic3_dyna_txrxq_params q_params = {}; +u32 new_sq_depth, new_rq_depth; +int err; + + err =hinic3_check_ringparam_valid (netdev, ring, extack); +if (err) +return err; + + new_sq_depth =rounddown_pow_of_two (ring->tx_pending); + new_rq_depth =rounddown_pow_of_two (ring->rx_pending); +if (new_sq_depth == nic_dev->q_params.sq_depth && + new_rq_depth == nic_dev->q_params.rq_depth) +return 0 ; + +if (new_sq_depth != ring->tx_pending || + new_rq_depth != ring->rx_pending) +NL_SET_ERR_MSG_FMT_MOD (extack, +"Requested Tx/Rx ring depth %u/%u trimmed to %u/%u" , + ring->tx_pending, ring->rx_pending, + new_sq_depth, new_rq_depth); + +if (!netif_running (netdev)) { +hinic3_update_qp_depth (netdev, new_sq_depth, new_rq_depth); + }else { + q_params = nic_dev->q_params; + q_params.sq_depth = new_sq_depth; + q_params.rq_depth = new_rq_depth; + + err =hinic3_change_channel_settings (netdev, &q_params); +if (err) +return err; + } + +return 0 ; +} +static const struct ethtool_ops hinic3_ethtool_ops = { .supported_coalesce_params =ETHTOOL_COALESCE_USECS |ETHTOOL_COALESCE_PKT_RATE_RX_USECS ,@@ -417,6 +506,8 @@ static const struct ethtool_ops hinic3_ethtool_ops = { .get_msglevel = hinic3_get_msglevel, .set_msglevel = hinic3_set_msglevel, .get_link = ethtool_op_get_link, + .get_ringparam = hinic3_get_ringparam, + .set_ringparam = hinic3_set_ringparam, };void hinic3_set_ethtool_ops (struct net_device *netdev)drivers/net/ethernet/huawei/hinic3/hinic3_main.c +1
-1@@ -178,7 +178,7 @@ static int hinic3_sw_init(struct net_device *netdev)u8 mac_addr[ETH_ALEN ];int err; -mutex_init (&nic_dev->port_state_mutex); +mutex_init (&nic_dev->state_lock); nic_dev->q_params.sq_depth =HINIC3_SQ_DEPTH ; nic_dev->q_params.rq_depth =HINIC3_RQ_DEPTH ;
drivers/net/ethernet/huawei/hinic3/hinic3_main.c static void hinic3_link_status_change(struct net_device *netdev, · line 334
Quoted 5 lines
drivers/net/ethernet/huawei/hinic3/hinic3_main.c +2
-0@@ -330,6 +330,8 @@ static void hinic3_link_status_change(struct net_device *netdev,netif_carrier_off (netdev);netdev_dbg (netdev,"Link is down\n" ); } + +return ;
Unrelated?
Quoted 163 lines
drivers/net/ethernet/huawei/hinic3/hinic3_main.c +0
-0} static void hinic3_port_module_event_handler(struct net_device *netdev,drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +92
-5@@ -288,7 +288,8 @@ static void hinic3_free_channel_resources(struct net_device *netdev,hinic3_free_qps (nic_dev, qp_params); } -static int hinic3_open_channel (struct net_device *netdev) +static int hinic3_prepare_channel (struct net_device *netdev, +struct hinic3_dyna_txrxq_params *qp_params) {struct hinic3_nic_dev *nic_dev =netdev_priv (netdev);int err;@@ -299,12 +300,25 @@ static int hinic3_open_channel(struct net_device *netdev)return err; } - err =hinic3_configure_txrxqs (netdev, &nic_dev->q_params); + err =hinic3_configure_txrxqs (netdev, qp_params);if (err) {netdev_err (netdev,"Failed to configure txrxqs\n" ); goto err_free_qp_ctxts; } +return 0 ; + +err_free_qp_ctxts: +hinic3_free_qp_ctxts (nic_dev); + +return err; +} + +static int hinic3_open_channel (struct net_device *netdev) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +int err; + err =hinic3_qps_irq_init (netdev);if (err) {netdev_err (netdev,"Failed to init txrxq irq\n" );@@ -321,6 +335,7 @@ static int hinic3_open_channel(struct net_device *netdev) err_uninit_qps_irq:hinic3_qps_irq_uninit (netdev); + err_free_qp_ctxts:hinic3_free_qp_ctxts (nic_dev);@@ -341,9 +356,7 @@ static int hinic3_maybe_set_port_state(struct net_device *netdev, bool enable)struct hinic3_nic_dev *nic_dev =netdev_priv (netdev);int err; -mutex_lock (&nic_dev->port_state_mutex); err =hinic3_set_port_enable (nic_dev->hwdev, enable); -mutex_unlock (&nic_dev->port_state_mutex);return err; }@@ -428,6 +441,76 @@ static void hinic3_vport_down(struct net_device *netdev) } } +int +hinic3_change_channel_settings (struct net_device *netdev, +struct hinic3_dyna_txrxq_params *trxq_params) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct hinic3_dyna_txrxq_params cur_trxq_params = {}; +struct hinic3_dyna_qp_params new_qp_params = {}; +struct hinic3_dyna_qp_params cur_qp_params = {}; +int err; + +mutex_lock (&nic_dev->state_lock); + cur_trxq_params = nic_dev->q_params; + +hinic3_config_num_qps (netdev, trxq_params); + + err =hinic3_alloc_channel_resources (netdev, &new_qp_params, + trxq_params); +if (err) { +netdev_err (netdev,"Failed to alloc channel resources\n" ); +hinic3_config_num_qps (netdev, &cur_trxq_params); +mutex_unlock (&nic_dev->state_lock); +return err; + } + +hinic3_vport_down (netdev); +hinic3_close_channel (netdev); +hinic3_get_cur_qps (nic_dev, &cur_qp_params); + +hinic3_init_qps (nic_dev, &new_qp_params); + + err =hinic3_prepare_channel (netdev, trxq_params); +if (err) + goto err_uninit_qps; + +if (nic_dev->num_qp_irq > trxq_params->num_qps) +hinic3_qp_irq_change (netdev, trxq_params->num_qps); + + nic_dev->q_params = *trxq_params; + + err =hinic3_open_channel (netdev); +if (err) + goto err_qp_irq_reset; + + err =hinic3_vport_up (netdev); +if (err) + goto err_close_channel; + +hinic3_free_channel_resources (netdev, &cur_qp_params, &cur_trxq_params); + +mutex_unlock (&nic_dev->state_lock); + +return 0 ; + +err_close_channel: +hinic3_close_channel (netdev); +err_qp_irq_reset: + nic_dev->q_params = cur_trxq_params; + +if (trxq_params->num_qps > cur_trxq_params.num_qps) +hinic3_qp_irq_change (netdev, cur_trxq_params.num_qps); +err_uninit_qps: +hinic3_get_cur_qps (nic_dev, &new_qp_params); +hinic3_config_num_qps (netdev, &cur_trxq_params); +hinic3_init_qps (nic_dev, &cur_qp_params); +hinic3_free_channel_resources (netdev, &new_qp_params, trxq_params); +mutex_unlock (&nic_dev->state_lock); + +return err; +} +static int hinic3_open (struct net_device *netdev) {struct hinic3_nic_dev *nic_dev =netdev_priv (netdev);@@ -458,6 +541,10 @@ static int hinic3_open(struct net_device *netdev)hinic3_init_qps (nic_dev, &qp_params); + err =hinic3_prepare_channel (netdev, &nic_dev->q_params); +if (err) + goto err_uninit_qps; + err =hinic3_open_channel (netdev);if (err) goto err_uninit_qps;@@ -473,7 +560,7 @@ static int hinic3_open(struct net_device *netdev) err_close_channel:hinic3_close_channel (netdev); err_uninit_qps: -hinic3_uninit_qps (nic_dev, &qp_params); +hinic3_get_cur_qps (nic_dev, &qp_params);hinic3_free_channel_resources (netdev, &qp_params, &nic_dev->q_params); err_destroy_num_qps:hinic3_destroy_num_qps (netdev);@@ -493,10 +580,15 @@ static int hinic3_close(struct net_device *netdev)return 0 ; }
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c static int hinic3_close(struct net_device *netdev) · line 590
Quoted 10 lines
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +6
-2+mutex_lock (&nic_dev->state_lock);hinic3_vport_down (netdev);hinic3_close_channel (netdev); -hinic3_uninit_qps (nic_dev, &qp_params); -hinic3_free_channel_resources (netdev, &qp_params, &nic_dev->q_params); +hinic3_get_cur_qps (nic_dev, &qp_params); +hinic3_free_channel_resources (netdev, &qp_params, + &nic_dev->q_params); +hinic3_free_nicio_res (nic_dev); +hinic3_destroy_num_qps (netdev);
free_nicio_res(), and destroy_num_qps() looks like fixes to me on the clean-up path. Should these go to the net tree?
Quoted 119 lines
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +1
-0+mutex_unlock (&nic_dev->state_lock);return 0 ; }drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h +9
-2@@ -10,6 +10,9 @@#include "hinic3_hw_cfg.h" #include "hinic3_hwdev.h" #include "hinic3_mgmt_interface.h" +#include "hinic3_nic_io.h" +#include "hinic3_tx.h" +#include "hinic3_rx.h" #define HINIC3_VLAN_BITMAP_BYTE_SIZE (nic_dev) (sizeof(*(nic_dev)->vlan_bitmap))#define HINIC3_VLAN_BITMAP_SIZE (nic_dev) \@@ -127,8 +130,8 @@ struct hinic3_nic_dev {struct workqueue_struct *workq;struct delayed_work periodic_work;struct work_struct rx_mode_work; -/* lock for enable/disable port */ -struct mutex port_state_mutex; +/* Protects Interface state */ +struct mutex state_lock;struct list_head uc_filter_list;struct list_head mc_filter_list;@@ -143,6 +146,10 @@ struct hinic3_nic_dev {void hinic3_set_netdev_ops (struct net_device *netdev);int hinic3_set_hw_features (struct net_device *netdev); +int +hinic3_change_channel_settings (struct net_device *netdev, +struct hinic3_dyna_txrxq_params *trxq_params); +int hinic3_qps_irq_init (struct net_device *netdev);void hinic3_qps_irq_uninit (struct net_device *netdev);drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c +2
-2@@ -484,8 +484,8 @@ void hinic3_init_qps(struct hinic3_nic_dev *nic_dev, } } -void hinic3_uninit_qps (struct hinic3_nic_dev *nic_dev, -struct hinic3_dyna_qp_params *qp_params) +void hinic3_get_cur_qps (struct hinic3_nic_dev *nic_dev, +struct hinic3_dyna_qp_params *qp_params) {struct hinic3_nic_io *nic_io = nic_dev->nic_io;drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h +6
-2@@ -14,6 +14,10 @@ struct hinic3_nic_dev;#define HINIC3_RQ_WQEBB_SHIFT 3#define HINIC3_SQ_WQEBB_SIZE BIT(HINIC3_SQ_WQEBB_SHIFT) +#define HINIC3_MAX_TX_QUEUE_DEPTH 65536 +#define HINIC3_MAX_RX_QUEUE_DEPTH 16384 +#define HINIC3_MIN_QUEUE_DEPTH 128 +/* ******************** RQ_CTRL ******************** */ enum hinic3_rq_wqe_type {HINIC3_NORMAL_RQ_WQE =1 ,@@ -136,8 +140,8 @@ void hinic3_free_qps(struct hinic3_nic_dev *nic_dev, struct hinic3_dyna_qp_params *qp_params);void hinic3_init_qps (struct hinic3_nic_dev *nic_dev,struct hinic3_dyna_qp_params *qp_params); -void hinic3_uninit_qps (struct hinic3_nic_dev *nic_dev, -struct hinic3_dyna_qp_params *qp_params); +void hinic3_get_cur_qps (struct hinic3_nic_dev *nic_dev, +struct hinic3_dyna_qp_params *qp_params);int hinic3_init_qp_ctxts (struct hinic3_nic_dev *nic_dev);void hinic3_free_qp_ctxts (struct hinic3_nic_dev *nic_dev);drivers/net/ethernet/huawei/hinic3/hinic3_rx.c +1
-1@@ -541,7 +541,7 @@ int hinic3_configure_rxqs(struct net_device *netdev, u16 num_rq,rq_associate_cqes (rxq); pkts =hinic3_rx_fill_buffers (rxq); -if (!pkts) { +if (pkts < rxq->q_mask) {netdev_err (netdev,"Failed to fill Rx buffer\n" );return -ENOMEM ; }drivers/net/ethernet/huawei/hinic3/hinic3_tx.c +5
-2@@ -261,8 +261,7 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struct hinic3_sq_task *task, ((struct udphdr *)skb_transport_header(skb))->dest != VXLAN_OFFLOAD_PORT_LE) {/* Unsupported tunnel packet, disable csum offload */ -skb_checksum_help (skb); -return 0 ; +return skb_checksum_help (skb); } }@@ -412,6 +411,10 @@ static u32 hinic3_tx_offload(struct sk_buff *skb, struct hinic3_sq_task *task, offload |=HINIC3_TX_OFFLOAD_TSO ; }else { tso_cs_en =hinic3_tx_csum (txq, task, skb); +if (tso_cs_en <0 ) { + offload =HINIC3_TX_OFFLOAD_INVALID ; +return offload; + }if (tso_cs_en) offload |=HINIC3_TX_OFFLOAD_CSUM ; }
Fan Gong
maintainerRe: Re: [PATCH net-next v11 1/5] hinic3: Add ethtool queue ops
Quoted 18 lines
Quoted 18 lines
Implement following ethtool callback function:
.get_ringparam
.set_ringparamThese callbacks allow users to utilize ethtool for detailed
queue depth configuration and monitoring.Change
port_state_mutextostate_lockas a unified mutex lock
inhinic3_nic_dev.Tightens the success criterion for
hinic3_rx_fill_buffers()inhinic3_configure_rxqs().Changes hinic3_tx_csum()/hinic3_tx_offload() to propagate
skb_checksum_help()failures into a TX drop.Renames
hinic3_uninit_qps()tohinic3_get_cur_qps().
Quoted 7 lines
Quoted 3 lines
Splits
hinic3_open_channel()intohinic3_prepare_channel()andhinic3_open_channel().It may just be me, but I feel like there is a lot going in this single patch. Ideally, a patch should carry one logical change. This patch is doing 3 things: refactor, new code, bug-fixing in the
hinic3_close()path.
Thanks for the following 3 review comments. We are pushing new codes to the net-next. However, fixing review comments leads to some refactoring and bug-fixing codes.
We are considering split patch #1 into smaller ones in the next patchset.
Quoted 8 lines
drivers/net/ethernet/huawei/hinic3/hinic3_main.c static void hinic3_link_status_change(struct net_device *netdev, · line 334
Quoted 6 lines
drivers/net/ethernet/huawei/hinic3/hinic3_main.c +2
-0@@ -330,6 +330,8 @@ static void hinic3_link_status_change(struct net_device *netdev,netif_carrier_off (netdev);netdev_dbg (netdev,"Link is down\n" ); } + +return ;Unrelated?
Sorry for our negligence. We will remove this unrelated change in the next patchset.
Quoted 4 lines
Quoted 4 lines
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +0
-0@@ -493,10 +580,15 @@ static int hinic3_close(struct net_device *netdev)return 0 ; }
Quoted 13 lines
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c static int hinic3_close(struct net_device *netdev) · line 590
Quoted 10 lines
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +6
-2+mutex_lock (&nic_dev->state_lock);hinic3_vport_down (netdev);hinic3_close_channel (netdev); -hinic3_uninit_qps (nic_dev, &qp_params); -hinic3_free_channel_resources (netdev, &qp_params, &nic_dev->q_params); +hinic3_get_cur_qps (nic_dev, &qp_params); +hinic3_free_channel_resources (netdev, &qp_params, + &nic_dev->q_params); +hinic3_free_nicio_res (nic_dev); +hinic3_destroy_num_qps (netdev);
free_nicio_res(), anddestroy_num_qps()looks like fixes to me on the clean-up path. Should these go to the net tree?
As mentioned above, we reckon it as a necessary fix to commit new codes, thus we put it in this patch.
Fan Gong
maintainerPATCH v11 2/5 hinic3: Add ethtool statistic ops
In reply to Fan Gong Add PF/VF statistics functions in TX and RX processing. Implement following ethtool callback function:
.get_sset_count
.get_ethtool_stats
.get_strings
.get_eth_phy_stats
.get_eth_mac_stats
.get_eth_ctrl_stats
.get_rmon_stats
.get_pause_stats
These callbacks allow users to utilize ethtool for detailed
TX and RX netdev stats monitoring.
Add mgmt_msg_params_init_in_out() to support management
commands that require separate input and output buffers. This is needed for retrieving the expanded PF/VF MAC statistics from HW, which no longer fit in the input buffer used by the existing path.
Remove unused stats "restore_drop_sge" in struct hinic3_rxq_stats.
--- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 483 ++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_hw_intf.h | 11 + .../huawei/hinic3/hinic3_mgmt_interface.h | 37 ++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 64 +++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 109 ++++ .../net/ethernet/huawei/hinic3/hinic3_rx.c | 69 ++- .../net/ethernet/huawei/hinic3/hinic3_rx.h | 15 +- .../net/ethernet/huawei/hinic3/hinic3_tx.c | 62 ++- .../net/ethernet/huawei/hinic3/hinic3_tx.h | 2 + 9 files changed, 841 insertions(+), 11 deletions(-)
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +483 -0
@@ -498,6 +498,481 @@ static int hinic3_set_ringparam(struct net_device *netdev,return 0 ; } +struct hinic3_stats { +char name[ETH_GSTRING_LEN ]; +u32 size; +int offset; +}; + +#define HINIC3_RXQ_STAT (_stat_item) { \ + .name = "rxq%d_"#_stat_item, \ + .size = sizeof_field(struct hinic3_rxq_stats, _stat_item), \ + .offset = offsetof(struct hinic3_rxq_stats, _stat_item) \ +} + +#define HINIC3_TXQ_STAT (_stat_item) { \ + .name = "txq%d_"#_stat_item, \ + .size = sizeof_field(struct hinic3_txq_stats, _stat_item), \ + .offset = offsetof(struct hinic3_txq_stats, _stat_item) \ +} + +static struct hinic3_stats hinic3_rx_queue_stats[] = { +HINIC3_RXQ_STAT (csum_errors), +HINIC3_RXQ_STAT (other_errors), +HINIC3_RXQ_STAT (rx_buf_empty), +HINIC3_RXQ_STAT (alloc_skb_err), +HINIC3_RXQ_STAT (alloc_rx_buf_err), +}; + +static struct hinic3_stats hinic3_tx_queue_stats[] = { +HINIC3_TXQ_STAT (busy), +HINIC3_TXQ_STAT (skb_pad_err), +HINIC3_TXQ_STAT (frag_len_overflow), +HINIC3_TXQ_STAT (offload_cow_skb_err), +HINIC3_TXQ_STAT (map_frag_err), +HINIC3_TXQ_STAT (unknown_tunnel_pkt), +HINIC3_TXQ_STAT (frag_size_err), +}; + +#define HINIC3_FUNC_STAT (_stat_item) { \ + .name = #_stat_item, \ + .size = sizeof_field(struct l2nic_vport_stats, _stat_item), \ + .offset = offsetof(struct l2nic_vport_stats, _stat_item) \ +} + +static struct hinic3_stats hinic3_function_stats[] = { +HINIC3_FUNC_STAT (tx_unicast_pkts_vport), +HINIC3_FUNC_STAT (tx_unicast_bytes_vport), +HINIC3_FUNC_STAT (tx_multicast_pkts_vport), +HINIC3_FUNC_STAT (tx_multicast_bytes_vport), +HINIC3_FUNC_STAT (tx_broadcast_pkts_vport), +HINIC3_FUNC_STAT (tx_broadcast_bytes_vport), + +HINIC3_FUNC_STAT (rx_unicast_pkts_vport), +HINIC3_FUNC_STAT (rx_unicast_bytes_vport), +HINIC3_FUNC_STAT (rx_multicast_pkts_vport), +HINIC3_FUNC_STAT (rx_multicast_bytes_vport), +HINIC3_FUNC_STAT (rx_broadcast_pkts_vport), +HINIC3_FUNC_STAT (rx_broadcast_bytes_vport), + +HINIC3_FUNC_STAT (tx_discard_vport), +HINIC3_FUNC_STAT (rx_discard_vport), +HINIC3_FUNC_STAT (tx_err_vport), +HINIC3_FUNC_STAT (rx_err_vport), +}; + +#define HINIC3_PORT_STAT (_stat_item) { \ + .name = #_stat_item, \ + .size = sizeof_field(struct mag_cmd_port_stats, _stat_item), \ + .offset = offsetof(struct mag_cmd_port_stats, _stat_item) \ +} + +static struct hinic3_stats hinic3_port_stats[] = { +HINIC3_PORT_STAT (mac_tx_fragment_pkt_num), +HINIC3_PORT_STAT (mac_tx_undersize_pkt_num), +HINIC3_PORT_STAT (mac_tx_undermin_pkt_num), +HINIC3_PORT_STAT (mac_tx_1519_max_bad_pkt_num), +HINIC3_PORT_STAT (mac_tx_1519_max_good_pkt_num), +HINIC3_PORT_STAT (mac_tx_oversize_pkt_num), +HINIC3_PORT_STAT (mac_tx_jabber_pkt_num), +HINIC3_PORT_STAT (mac_tx_bad_pkt_num), +HINIC3_PORT_STAT (mac_tx_bad_oct_num), +HINIC3_PORT_STAT (mac_tx_good_oct_num), +HINIC3_PORT_STAT (mac_tx_total_pkt_num), +HINIC3_PORT_STAT (mac_tx_uni_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pri0_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pri1_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pri2_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pri3_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pri4_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pri5_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pri6_pkt_num), +HINIC3_PORT_STAT (mac_tx_pfc_pri7_pkt_num), +HINIC3_PORT_STAT (mac_tx_err_all_pkt_num), +HINIC3_PORT_STAT (mac_tx_from_app_good_pkt_num), +HINIC3_PORT_STAT (mac_tx_from_app_bad_pkt_num), + +HINIC3_PORT_STAT (mac_rx_undermin_pkt_num), +HINIC3_PORT_STAT (mac_rx_1519_max_bad_pkt_num), +HINIC3_PORT_STAT (mac_rx_1519_max_good_pkt_num), +HINIC3_PORT_STAT (mac_rx_bad_pkt_num), +HINIC3_PORT_STAT (mac_rx_bad_oct_num), +HINIC3_PORT_STAT (mac_rx_good_oct_num), +HINIC3_PORT_STAT (mac_rx_total_pkt_num), +HINIC3_PORT_STAT (mac_rx_uni_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pri0_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pri1_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pri2_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pri3_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pri4_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pri5_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pri6_pkt_num), +HINIC3_PORT_STAT (mac_rx_pfc_pri7_pkt_num), +HINIC3_PORT_STAT (mac_rx_send_app_good_pkt_num), +HINIC3_PORT_STAT (mac_rx_send_app_bad_pkt_num), +HINIC3_PORT_STAT (mac_rx_unfilter_pkt_num), +}; + +static int hinic3_get_sset_count (struct net_device *netdev,int sset) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +int count, q_num; + +switch (sset) { +case ETH_SS_STATS : + q_num = nic_dev->q_params.num_qps; + count =ARRAY_SIZE (hinic3_function_stats) + + (ARRAY_SIZE (hinic3_tx_queue_stats) + +ARRAY_SIZE (hinic3_rx_queue_stats)) * + q_num; + +if (!HINIC3_IS_VF (nic_dev->hwdev)) + count +=ARRAY_SIZE (hinic3_port_stats); + +return count; +default : +return -EOPNOTSUPP ; + } +} + +static u64 get_val_of_ptr (u32 size,const void *ptr) +{ +u64 ret = size ==sizeof (u64) ? *(u64 *)ptr : + size ==sizeof (u32) ? *(u32 *)ptr : + size ==sizeof (u16) ? *(u16 *)ptr : + *(u8 *)ptr; + +return ret; +} + +static void hinic3_get_drv_queue_stats (struct net_device *netdev,u64 *data) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct hinic3_txq_stats txq_stats = {}; +struct hinic3_rxq_stats rxq_stats = {}; +u16 i =0 , j, qid; +char *p; + +for (qid =0 ; qid < nic_dev->q_params.num_qps; qid++) { +if (!nic_dev->txqs) +break ; + +hinic3_txq_get_stats (&nic_dev->txqs[qid], &txq_stats); +for (j =0 ; j <ARRAY_SIZE (hinic3_tx_queue_stats); j++, i++) { + p = (char *)&txq_stats + + hinic3_tx_queue_stats[j].offset; + data[i] =get_val_of_ptr (hinic3_tx_queue_stats[j].size, + p); + } + } + + i = nic_dev->q_params.num_qps *ARRAY_SIZE (hinic3_tx_queue_stats); +for (qid =0 ; qid < nic_dev->q_params.num_qps; qid++) { +if (!nic_dev->rxqs) +break ; + +hinic3_rxq_get_stats (&nic_dev->rxqs[qid], &rxq_stats); +for (j =0 ; j <ARRAY_SIZE (hinic3_rx_queue_stats); j++, i++) { + p = (char *)&rxq_stats + + hinic3_rx_queue_stats[j].offset; + data[i] =get_val_of_ptr (hinic3_rx_queue_stats[j].size, + p); + } + } +} + +static u16 hinic3_get_ethtool_port_stats (struct net_device *netdev,u64 *data) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct mag_cmd_port_stats *ps; +u16 i =0 , j; +char *p; +int err; + + ps =kmalloc_obj (*ps); +if (!ps) + goto err_zero_stats; + + err =hinic3_get_phy_port_stats (nic_dev->hwdev, ps); +if (err) { +kfree (ps); +netdev_err (netdev,"Failed to get port stats from fw\n" ); + goto err_zero_stats; + } + +for (j =0 ; j <ARRAY_SIZE (hinic3_port_stats); j++, i++) { + p = (char *)ps + hinic3_port_stats[j].offset; + data[i] =get_val_of_ptr (hinic3_port_stats[j].size, p); + } + +kfree (ps); + +return i; + +err_zero_stats: +memset (&data[i],0 ,ARRAY_SIZE (hinic3_port_stats) *sizeof (*data)); + +return i +ARRAY_SIZE (hinic3_port_stats); +} + +static void hinic3_get_ethtool_stats (struct net_device *netdev, +struct ethtool_stats *stats,u64 *data) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct l2nic_vport_stats vport_stats = {}; +u16 i =0 , j; +char *p; +int err; + + err =hinic3_get_vport_stats (nic_dev->hwdev, +hinic3_global_func_id (nic_dev->hwdev), + &vport_stats); +if (err) +netdev_err (netdev,"Failed to get function stats from fw\n" ); + +for (j =0 ; j <ARRAY_SIZE (hinic3_function_stats); j++, i++) { + p = (char *)&vport_stats + hinic3_function_stats[j].offset; + data[i] =get_val_of_ptr (hinic3_function_stats[j].size, p); + } + +if (!HINIC3_IS_VF (nic_dev->hwdev)) + i +=hinic3_get_ethtool_port_stats (netdev, data + i); + +hinic3_get_drv_queue_stats (netdev, data + i); +} + +static u16 hinic3_get_hw_stats_strings (struct net_device *netdev,char *p) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +u16 i, cnt =0 ; + +for (i =0 ; i <ARRAY_SIZE (hinic3_function_stats); i++) { +memcpy (p, hinic3_function_stats[i].name,ETH_GSTRING_LEN ); + p +=ETH_GSTRING_LEN ; + cnt++; + } + +if (!HINIC3_IS_VF (nic_dev->hwdev)) { +for (i =0 ; i <ARRAY_SIZE (hinic3_port_stats); i++) { +memcpy (p, hinic3_port_stats[i].name,ETH_GSTRING_LEN ); + p +=ETH_GSTRING_LEN ; + cnt++; + } + } + +return cnt; +} + +static void hinic3_get_qp_stats_strings (struct net_device *netdev,char *p) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +u8 *data = p; +u16 i, j; + +for (i =0 ; i < nic_dev->q_params.num_qps; i++) { +for (j =0 ; j <ARRAY_SIZE (hinic3_tx_queue_stats); j++) +ethtool_sprintf (&data, + hinic3_tx_queue_stats[j].name, i); + } + +for (i =0 ; i < nic_dev->q_params.num_qps; i++) { +for (j =0 ; j <ARRAY_SIZE (hinic3_rx_queue_stats); j++) +ethtool_sprintf (&data, + hinic3_rx_queue_stats[j].name, i); + } +} + +static void hinic3_get_strings (struct net_device *netdev, +u32 stringset,u8 *data) +{ +char *p = (char *)data; +u16 offset; + +switch (stringset) { +case ETH_SS_STATS : + offset =hinic3_get_hw_stats_strings (netdev, p); +hinic3_get_qp_stats_strings (netdev, + p + offset *ETH_GSTRING_LEN ); + +return ; +default : +netdev_err (netdev,"Invalid string set %u.\n" , stringset); +return ; + } +} + +static void hinic3_get_eth_phy_stats (struct net_device *netdev, +struct ethtool_eth_phy_stats *phy_stats) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct mag_cmd_port_stats *ps; +int err; + + ps =kmalloc_obj (*ps); +if (!ps) +return ; + + err =hinic3_get_phy_port_stats (nic_dev->hwdev, ps); +if (err) { +kfree (ps); +netdev_err (netdev,"Failed to get eth phy stats from fw\n" ); +return ; + } + + phy_stats->SymbolErrorDuringCarrier = ps->mac_rx_sym_err_pkt_num; + +kfree (ps); +} + +static void hinic3_get_eth_mac_stats (struct net_device *netdev, +struct ethtool_eth_mac_stats *mac_stats) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct mag_cmd_port_stats *ps; +int err; + + ps =kmalloc_obj (*ps); +if (!ps) +return ; + + err =hinic3_get_phy_port_stats (nic_dev->hwdev, ps); +if (err) { +kfree (ps); +netdev_err (netdev,"Failed to get eth mac stats from fw\n" ); +return ; + } + + mac_stats->FramesTransmittedOK = ps->mac_tx_good_pkt_num; + mac_stats->FramesReceivedOK = ps->mac_rx_good_pkt_num; + mac_stats->FrameCheckSequenceErrors = ps->mac_rx_fcs_err_pkt_num; + mac_stats->OctetsTransmittedOK = ps->mac_tx_total_oct_num; + mac_stats->OctetsReceivedOK = ps->mac_rx_total_oct_num; + mac_stats->MulticastFramesXmittedOK = ps->mac_tx_multi_pkt_num; + mac_stats->BroadcastFramesXmittedOK = ps->mac_tx_broad_pkt_num; + mac_stats->MulticastFramesReceivedOK = ps->mac_rx_multi_pkt_num; + mac_stats->BroadcastFramesReceivedOK = ps->mac_rx_broad_pkt_num; + +kfree (ps); +} + +static void hinic3_get_eth_ctrl_stats (struct net_device *netdev, +struct ethtool_eth_ctrl_stats *ctrl_stats) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct mag_cmd_port_stats *ps; +int err; + + ps =kmalloc_obj (*ps); +if (!ps) +return ; + + err =hinic3_get_phy_port_stats (nic_dev->hwdev, ps); +if (err) { +kfree (ps); +netdev_err (netdev,"Failed to get eth ctrl stats from fw\n" ); +return ; + } + + ctrl_stats->MACControlFramesTransmitted = ps->mac_tx_control_pkt_num; + ctrl_stats->MACControlFramesReceived = ps->mac_rx_control_pkt_num; + +kfree (ps); +} + +static const struct ethtool_rmon_hist_range hinic3_rmon_ranges[] = { + {0 ,64 }, + {65 ,127 }, + {128 ,255 }, + {256 ,511 }, + {512 ,1023 }, + {1024 ,1518 }, + {1519 ,2047 }, + {2048 ,4095 }, + {4096 ,8191 }, + {8192 ,9216 }, + {9217 ,12287 }, + {} +}; + +static void hinic3_get_rmon_stats (struct net_device *netdev, +struct ethtool_rmon_stats *rmon_stats, +const struct ethtool_rmon_hist_range **ranges) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct mag_cmd_port_stats *ps; +int err; + + ps =kmalloc_obj (*ps); +if (!ps) +return ; + + err =hinic3_get_phy_port_stats (nic_dev->hwdev, ps); +if (err) { +kfree (ps); +netdev_err (netdev,"Failed to get eth rmon stats from fw\n" ); +return ; + } + + rmon_stats->undersize_pkts = ps->mac_rx_undersize_pkt_num; + rmon_stats->oversize_pkts = ps->mac_rx_oversize_pkt_num; + rmon_stats->fragments = ps->mac_rx_fragment_pkt_num; + rmon_stats->jabbers = ps->mac_rx_jabber_pkt_num; + + rmon_stats->hist[0 ] = ps->mac_rx_64_oct_pkt_num; + rmon_stats->hist[1 ] = ps->mac_rx_65_127_oct_pkt_num; + rmon_stats->hist[2 ] = ps->mac_rx_128_255_oct_pkt_num; + rmon_stats->hist[3 ] = ps->mac_rx_256_511_oct_pkt_num; + rmon_stats->hist[4 ] = ps->mac_rx_512_1023_oct_pkt_num; + rmon_stats->hist[5 ] = ps->mac_rx_1024_1518_oct_pkt_num; + rmon_stats->hist[6 ] = ps->mac_rx_1519_2047_oct_pkt_num; + rmon_stats->hist[7 ] = ps->mac_rx_2048_4095_oct_pkt_num; + rmon_stats->hist[8 ] = ps->mac_rx_4096_8191_oct_pkt_num; + rmon_stats->hist[9 ] = ps->mac_rx_8192_9216_oct_pkt_num; + rmon_stats->hist[10 ] = ps->mac_rx_9217_12287_oct_pkt_num; + + rmon_stats->hist_tx[0 ] = ps->mac_tx_64_oct_pkt_num; + rmon_stats->hist_tx[1 ] = ps->mac_tx_65_127_oct_pkt_num; + rmon_stats->hist_tx[2 ] = ps->mac_tx_128_255_oct_pkt_num; + rmon_stats->hist_tx[3 ] = ps->mac_tx_256_511_oct_pkt_num; + rmon_stats->hist_tx[4 ] = ps->mac_tx_512_1023_oct_pkt_num; + rmon_stats->hist_tx[5 ] = ps->mac_tx_1024_1518_oct_pkt_num; + rmon_stats->hist_tx[6 ] = ps->mac_tx_1519_2047_oct_pkt_num; + rmon_stats->hist_tx[7 ] = ps->mac_tx_2048_4095_oct_pkt_num; + rmon_stats->hist_tx[8 ] = ps->mac_tx_4096_8191_oct_pkt_num; + rmon_stats->hist_tx[9 ] = ps->mac_tx_8192_9216_oct_pkt_num; + rmon_stats->hist_tx[10 ] = ps->mac_tx_9217_12287_oct_pkt_num; + + *ranges = hinic3_rmon_ranges; + +kfree (ps); +} + +static void hinic3_get_pause_stats (struct net_device *netdev, +struct ethtool_pause_stats *pause_stats) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct mag_cmd_port_stats *ps; +int err; + + ps =kmalloc_obj (*ps); +if (!ps) +return ; + + err =hinic3_get_phy_port_stats (nic_dev->hwdev, ps); +if (err) { +kfree (ps); +netdev_err (netdev,"Failed to get eth pause stats from fw\n" ); +return ; + } + + pause_stats->tx_pause_frames = ps->mac_tx_pause_num; + pause_stats->rx_pause_frames = ps->mac_rx_pause_num; + +kfree (ps); +} +static const struct ethtool_ops hinic3_ethtool_ops = { .supported_coalesce_params =ETHTOOL_COALESCE_USECS |ETHTOOL_COALESCE_PKT_RATE_RX_USECS ,
@@ -508,6 +983,14 @@ static const struct ethtool_ops hinic3_ethtool_ops = { .get_link = ethtool_op_get_link, .get_ringparam = hinic3_get_ringparam, .set_ringparam = hinic3_set_ringparam, + .get_sset_count = hinic3_get_sset_count, + .get_ethtool_stats = hinic3_get_ethtool_stats, + .get_strings = hinic3_get_strings, + .get_eth_phy_stats = hinic3_get_eth_phy_stats, + .get_eth_mac_stats = hinic3_get_eth_mac_stats, + .get_eth_ctrl_stats = hinic3_get_eth_ctrl_stats, + .get_rmon_stats = hinic3_get_rmon_stats, + .get_pause_stats = hinic3_get_pause_stats, };void hinic3_set_ethtool_ops (struct net_device *netdev)
drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h +11 -0
@@ -53,6 +53,17 @@ static inline void mgmt_msg_params_init_default(struct mgmt_msg_params *msg_para msg_params->timeout_ms =0 ; } +static inline void +mgmt_msg_params_init_in_out (struct mgmt_msg_params *msg_params,void *in_buf, +void *out_buf,u32 in_buf_size,u32 out_buf_size) +{ + msg_params->buf_in = in_buf; + msg_params->buf_out = out_buf; + msg_params->in_size = in_buf_size; + msg_params->expected_out_size = out_buf_size; + msg_params->timeout_ms =0 ; +} +enum cfg_cmd {CFG_CMD_GET_DEV_CAP =0 , };
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +37 -0
@@ -143,6 +143,41 @@ struct l2nic_cmd_set_dcb_state {u8 rsvd[7 ]; }; +struct l2nic_port_stats_info { +struct mgmt_msg_head msg_head; +u16 func_id; +u16 rsvd1; +}; + +struct l2nic_vport_stats { +u64 tx_unicast_pkts_vport; +u64 tx_unicast_bytes_vport; +u64 tx_multicast_pkts_vport; +u64 tx_multicast_bytes_vport; +u64 tx_broadcast_pkts_vport; +u64 tx_broadcast_bytes_vport; + +u64 rx_unicast_pkts_vport; +u64 rx_unicast_bytes_vport; +u64 rx_multicast_pkts_vport; +u64 rx_multicast_bytes_vport; +u64 rx_broadcast_pkts_vport; +u64 rx_broadcast_bytes_vport; + +u64 tx_discard_vport; +u64 rx_discard_vport; +u64 tx_err_vport; +u64 rx_err_vport; +}; + +struct l2nic_cmd_vport_stats { +struct mgmt_msg_head msg_head; +u32 stats_size; +u32 rsvd1; +struct l2nic_vport_stats stats; +u64 rsvd2[6 ]; +}; +struct l2nic_cmd_lro_config {struct mgmt_msg_head msg_head;u16 func_id;
@@ -234,6 +269,7 @@ enum l2nic_cmd {L2NIC_CMD_SET_VPORT_ENABLE =6 ,L2NIC_CMD_SET_RX_MODE =7 ,L2NIC_CMD_SET_SQ_CI_ATTR =8 , +L2NIC_CMD_GET_VPORT_STAT =9 ,L2NIC_CMD_CLEAR_QP_RESOURCE =11 ,L2NIC_CMD_CFG_RX_LRO =13 , L2NIC_CMD_CFG_LRO_TIMER = 14,
@@ -272,6 +308,7 @@ enum mag_cmd {MAG_CMD_SET_PORT_ENABLE =6 ,MAG_CMD_GET_LINK_STATUS =7 , +MAG_CMD_GET_PORT_STAT =151 , MAG_CMD_GET_PORT_INFO = 153, };
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +64 -0
73 lines not on this page · raw message
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h +109 -0
121 lines not on this page · raw message
drivers/net/ethernet/huawei/hinic3/hinic3_rx.c +61 -8
137 lines not on this page · raw message
drivers/net/ethernet/huawei/hinic3/hinic3_rx.h +14 -1
@@ -8,6 +8,17 @@#include <linux/dim.h> #include <linux/netdevice.h> +/* rx cqe checksum err */ +#define HINIC3_RX_CSUM_IP_CSUM_ERR BIT(0) +#define HINIC3_RX_CSUM_TCP_CSUM_ERR BIT(1) +#define HINIC3_RX_CSUM_UDP_CSUM_ERR BIT(2) +#define HINIC3_RX_CSUM_IGMP_CSUM_ERR BIT(3) +#define HINIC3_RX_CSUM_ICMPV4_CSUM_ERR BIT(4) +#define HINIC3_RX_CSUM_ICMPV6_CSUM_ERR BIT(5) +#define HINIC3_RX_CSUM_SCTP_CRC_ERR BIT(6) +#define HINIC3_RX_CSUM_HW_CHECK_NONE BIT(7) +#define HINIC3_RX_CSUM_IPSU_OTHER_ERR BIT(8) +#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK GENMASK(4, 0)#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_MASK GENMASK(6, 5)#define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_MASK GENMASK(11, 8)
@@ -39,7 +50,6 @@ struct hinic3_rxq_stats {u64 rx_buf_empty;u64 alloc_skb_err;u64 alloc_rx_buf_err; -u64 restore_drop_sge;struct u64_stats_sync syncp; };
@@ -123,6 +133,9 @@ void hinic3_free_rxqs_res(struct net_device *netdev, u16 num_rq, u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res);int hinic3_configure_rxqs (struct net_device *netdev,u16 num_rq,u32 rq_depth,struct hinic3_dyna_rxq_res *rxqs_res); + +void hinic3_rxq_get_stats (struct hinic3_rxq *rxq, +struct hinic3_rxq_stats *stats);int hinic3_rx_poll (struct hinic3_rxq *rxq,int budget);#endif
drivers/net/ethernet/huawei/hinic3/hinic3_tx.c +60 -2
112 lines not on this page · raw message
drivers/net/ethernet/huawei/hinic3/hinic3_tx.h +2 -0
@@ -157,6 +157,8 @@ int hinic3_configure_txqs(struct net_device *netdev, u16 num_sq, u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res);netdev_tx_t hinic3_xmit_frame (struct sk_buff *skb,struct net_device *netdev); +void hinic3_txq_get_stats (struct hinic3_txq *txq, +struct hinic3_txq_stats *stats);bool hinic3_tx_poll (struct hinic3_txq *txq,int budget);void hinic3_flush_txqs (struct net_device *netdev);
Signature · 1 line
2.54.0
Re: [PATCH net-next v11 2/5] hinic3: Add ethtool statistic ops
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c static int hinic3_set_ringparam(struct net_device *netdev, · line 648
Quoted 10 lines · Fan Gong
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +10
-0+ +static u64 get_val_of_ptr (u32 size,const void *ptr) +{ +u64 ret = size ==sizeof (u64) ? *(u64 *)ptr : + size ==sizeof (u32) ? *(u32 *)ptr : + size ==sizeof (u16) ? *(u16 *)ptr : + *(u8 *)ptr; + +return ret; +}
Why is this needed? It looks like all the counters in hinic3_rx_queue_stats, hinic3_tx_queue_stats, and hinic3_port_stats are u64.
Fan Gong
maintainerRe: Re: [PATCH net-next v11 2/5] hinic3: Add ethtool statistic ops
Quoted 5 lines
Quoted 5 lines
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +5
-0+ +static u64 get_val_of_ptr (u32 size,const void *ptr) +{ +u64 ret = size ==sizeof (u64) ? *(u64 *)ptr : + size == sizeof(u32) ? *(u32 *)ptr :
Quoted 8 lines
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c static int hinic3_set_ringparam(struct net_device *netdev, · line 648
Quoted 5 lines
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +5
-0+ size ==sizeof (u16) ? *(u16 *)ptr : + *(u8 *)ptr; + +return ret; +}Why is this needed? It looks like all the counters in
hinic3_rx_queue_stats,hinic3_tx_queue_stats, andhinic3_port_statsare u64.
Thanks for the review. We will remove it in the next patchset.
Fan Gong
maintainerPATCH v11 3/5 hinic3: Add ethtool coalesce ops
In reply to Fan Gong Implement following ethtool callback function:
.get_coalesce
.set_coalesce
These callbacks allow users to utilize ethtool for detailed
RX coalesce configuration and monitoring.
--- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 286 +++++++++++++++++- .../net/ethernet/huawei/hinic3/hinic3_irq.c | 12 +- .../net/ethernet/huawei/hinic3/hinic3_main.c | 2 +- 3 files changed, 293 insertions(+), 7 deletions(-)
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +284 -2
@@ -18,6 +18,11 @@#include "hinic3_nic_cfg.h" #define HINIC3_MGMT_VERSION_MAX_LEN 32 +/* Coalesce time properties in microseconds */ +#define COALESCE_PENDING_LIMIT_UNIT 8 +#define COALESCE_TIMER_CFG_UNIT 5 +#define COALESCE_MAX_PENDING_LIMIT (255 * COALESCE_PENDING_LIMIT_UNIT) +#define COALESCE_MAX_TIMER_CFG (255 * COALESCE_TIMER_CFG_UNIT)static void hinic3_get_drvinfo (struct net_device *netdev,struct ethtool_drvinfo *info)
@@ -973,9 +978,284 @@ static void hinic3_get_pause_stats(struct net_device *netdev,kfree (ps); } +static int hinic3_set_queue_coalesce (struct net_device *netdev,u16 q_id, +struct hinic3_intr_coal_info *coal, +struct netlink_ext_ack *extack) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct hinic3_intr_coal_info *intr_coal; +struct hinic3_interrupt_info info = {}; +bool is_active; +int err; + +mutex_lock (&nic_dev->state_lock); + is_active =test_bit (HINIC3_INTF_UP , &nic_dev->flags) && + (q_id < nic_dev->q_params.num_qps); + +if (is_active) { + info.msix_index = + nic_dev->q_params.irq_cfg[q_id].msix_entry_idx; + info.resend_timer_cfg = + nic_dev->intr_coalesce[q_id].resend_timer_cfg; + } +mutex_unlock (&nic_dev->state_lock); + +if (is_active) { + info.interrupt_coalesc_set =1 ; + info.coalesc_timer_cfg = coal->coalesce_timer_cfg; + info.pending_limit = coal->pending_limit; + + err =hinic3_set_interrupt_cfg (nic_dev->hwdev, info); +if (err) { +NL_SET_ERR_MSG_FMT_MOD (extack, +"Failed to set queue%u coalesce" , + q_id); +return err; + } + } + +mutex_lock (&nic_dev->state_lock); + intr_coal = &nic_dev->intr_coalesce[q_id]; + intr_coal->coalesce_timer_cfg = coal->coalesce_timer_cfg; + intr_coal->pending_limit = coal->pending_limit; + intr_coal->rx_pending_limit_low = coal->rx_pending_limit_low; + intr_coal->rx_pending_limit_high = coal->rx_pending_limit_high; +mutex_unlock (&nic_dev->state_lock); + +return 0 ; +} + +static int is_coalesce_exceed_limit (const struct ethtool_coalesce *coal, +struct netlink_ext_ack *extack) +{ +const struct { +const char *name; +u32 value; +u32 limit; + } coalesce_limits[] = { + {"rx_coalesce_usecs" , + coal->rx_coalesce_usecs, +COALESCE_MAX_TIMER_CFG }, + {"rx_max_coalesced_frames" , + coal->rx_max_coalesced_frames, +COALESCE_MAX_PENDING_LIMIT }, + {"rx_max_coalesced_frames_low" , + coal->rx_max_coalesced_frames_low, +COALESCE_MAX_PENDING_LIMIT }, + {"rx_max_coalesced_frames_high" , + coal->rx_max_coalesced_frames_high, +COALESCE_MAX_PENDING_LIMIT }, + }; + +for (int i =0 ; i <ARRAY_SIZE (coalesce_limits); i++) { +if (coalesce_limits[i].value > coalesce_limits[i].limit) { +NL_SET_ERR_MSG_FMT_MOD (extack,"%s out of range %d-%d" , + coalesce_limits[i].name,0 , + coalesce_limits[i].limit); +return -ERANGE ; + } + } +return 0 ; +} + +static int hinic3_validate_coalesce (const struct ethtool_coalesce *coal, +struct netlink_ext_ack *extack) +{ +int err; + + err =is_coalesce_exceed_limit (coal, extack); +if (err) +return err; + +if (coal->rx_max_coalesced_frames_low > + coal->rx_max_coalesced_frames_high) { +NL_SET_ERR_MSG_FMT_MOD (extack, +"invalid coalesce frame high %u, low %u" , + coal->rx_max_coalesced_frames_high, + coal->rx_max_coalesced_frames_low); +return -ERANGE ; + } + +return 0 ; +} + +static void check_coalesce_align (struct net_device *netdev, +u32 item,u32 unit,const char *str) +{ +if (item % unit) +netdev_warn (netdev,"%s in %d units, change to %u\n" , + str, unit, item - item % unit); +} + +#define CHECK_COALESCE_ALIGN (member, unit) \ + check_coalesce_align(netdev, member, unit, #member) + +static void check_coalesce_changed (struct net_device *netdev, +u32 item,u32 unit,u32 ori_val, +const char *obj_str,const char *str) +{ +if ((item / unit) != ori_val) +netdev_dbg (netdev,"Change %s from %d to %u %s\n" , + str, ori_val * unit, item - item % unit, obj_str); +} + +#define CHECK_COALESCE_CHANGED (member, unit, ori_val, obj_str) \ + check_coalesce_changed(netdev, member, unit, ori_val, obj_str, #member) + +static int hinic3_set_hw_coal_param (struct net_device *netdev, +struct hinic3_intr_coal_info *intr_coal, +struct netlink_ext_ack *extack) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +int err; +u16 i; + +for (i =0 ; i < nic_dev->max_qps; i++) { + err =hinic3_set_queue_coalesce (netdev, i, intr_coal, extack); +if (err) +return err; + } + +return 0 ; +} + +static int hinic3_get_coalesce (struct net_device *netdev, +struct ethtool_coalesce *coal, +struct kernel_ethtool_coalesce *kernel_coal, +struct netlink_ext_ack *extack) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct hinic3_intr_coal_info *interrupt_info; + + interrupt_info = &nic_dev->intr_coalesce[0 ]; + + coal->use_adaptive_rx_coalesce =READ_ONCE (nic_dev->adaptive_rx_coal); + +mutex_lock (&nic_dev->state_lock); + + coal->rx_max_coalesced_frames_low = + interrupt_info->rx_pending_limit_low * +COALESCE_PENDING_LIMIT_UNIT ; + + coal->rx_max_coalesced_frames_high = + interrupt_info->rx_pending_limit_high * +COALESCE_PENDING_LIMIT_UNIT ; + +/* TX/RX uses the same interrupt. +* So we only declare RX ethtool_coalesce parameters. +*/ + coal->rx_coalesce_usecs = interrupt_info->coalesce_timer_cfg * +COALESCE_TIMER_CFG_UNIT ; + + coal->rx_max_coalesced_frames = interrupt_info->pending_limit * +COALESCE_PENDING_LIMIT_UNIT ; + +mutex_unlock (&nic_dev->state_lock); + +return 0 ; +} + +static int hinic3_set_coalesce (struct net_device *netdev, +struct ethtool_coalesce *coal, +struct kernel_ethtool_coalesce *kernel_coal, +struct netlink_ext_ack *extack) +{ +struct hinic3_nic_dev *nic_dev =netdev_priv (netdev); +struct hinic3_intr_coal_info *ori_intr_coal; +struct hinic3_intr_coal_info intr_coal = {}; +const char *obj_str ="for netdev" ; +bool old_adaptive, new_adaptive; +struct hinic3_rxq *rxq =NULL ; +bool dim_stopped = false; +int err; +int i; + + err =hinic3_validate_coalesce (coal, extack); +if (err) +return err; + +CHECK_COALESCE_ALIGN (coal->rx_coalesce_usecs,COALESCE_TIMER_CFG_UNIT ); +CHECK_COALESCE_ALIGN (coal->rx_max_coalesced_frames, +COALESCE_PENDING_LIMIT_UNIT ); +CHECK_COALESCE_ALIGN (coal->rx_max_coalesced_frames_high, +COALESCE_PENDING_LIMIT_UNIT ); +CHECK_COALESCE_ALIGN (coal->rx_max_coalesced_frames_low, +COALESCE_PENDING_LIMIT_UNIT ); + + ori_intr_coal = &nic_dev->intr_coalesce[0 ]; + +CHECK_COALESCE_CHANGED (coal->rx_coalesce_usecs,COALESCE_TIMER_CFG_UNIT , + ori_intr_coal->coalesce_timer_cfg, obj_str); +CHECK_COALESCE_CHANGED (coal->rx_max_coalesced_frames, +COALESCE_PENDING_LIMIT_UNIT , + ori_intr_coal->pending_limit, obj_str); +CHECK_COALESCE_CHANGED (coal->rx_max_coalesced_frames_high, +COALESCE_PENDING_LIMIT_UNIT , + ori_intr_coal->rx_pending_limit_high, obj_str); +CHECK_COALESCE_CHANGED (coal->rx_max_coalesced_frames_low, +COALESCE_PENDING_LIMIT_UNIT , + ori_intr_coal->rx_pending_limit_low, obj_str); + + old_adaptive =READ_ONCE (nic_dev->adaptive_rx_coal); + new_adaptive = !!coal->use_adaptive_rx_coalesce; + +if (old_adaptive) { +WRITE_ONCE (nic_dev->adaptive_rx_coal, false); + +synchronize_net (); + +for (i =0 ; i < nic_dev->q_params.num_qps; i++) { + rxq = nic_dev->q_params.irq_cfg[i].rxq; +if (!rxq) +continue ; + +cancel_work_sync (&rxq->dim.work); + + rxq->dim.state =DIM_START_MEASURE ; + } + + dim_stopped = true; + } + + intr_coal.coalesce_timer_cfg = + (u8)(coal->rx_coalesce_usecs /COALESCE_TIMER_CFG_UNIT ); + + intr_coal.pending_limit = + (u8)(coal->rx_max_coalesced_frames / +COALESCE_PENDING_LIMIT_UNIT ); + + intr_coal.rx_pending_limit_high = + (u8)(coal->rx_max_coalesced_frames_high / +COALESCE_PENDING_LIMIT_UNIT ); + + intr_coal.rx_pending_limit_low = + (u8)(coal->rx_max_coalesced_frames_low / +COALESCE_PENDING_LIMIT_UNIT ); + +/* coalesce timer or pending set to zero will disable coalesce */ +if (!new_adaptive && + (!intr_coal.coalesce_timer_cfg || !intr_coal.pending_limit)) +netdev_info (netdev,"Coalesce will be disabled\n" ); + + err =hinic3_set_hw_coal_param (netdev, &intr_coal, extack); +if (err) { +if (dim_stopped) +WRITE_ONCE (nic_dev->adaptive_rx_coal, old_adaptive); + +return err; + } + +WRITE_ONCE (nic_dev->adaptive_rx_coal, new_adaptive); + +return 0 ; +} +static const struct ethtool_ops hinic3_ethtool_ops = { - .supported_coalesce_params =ETHTOOL_COALESCE_USECS | -ETHTOOL_COALESCE_PKT_RATE_RX_USECS , + .supported_coalesce_params =ETHTOOL_COALESCE_RX_USECS | +ETHTOOL_COALESCE_RX_MAX_FRAMES | +ETHTOOL_COALESCE_USE_ADAPTIVE_RX | +ETHTOOL_COALESCE_RX_MAX_FRAMES_LOW | +ETHTOOL_COALESCE_RX_MAX_FRAMES_HIGH , .get_link_ksettings = hinic3_get_link_ksettings, .get_drvinfo = hinic3_get_drvinfo, .get_msglevel = hinic3_get_msglevel,
@@ -991,6 +1271,8 @@ static const struct ethtool_ops hinic3_ethtool_ops = { .get_eth_ctrl_stats = hinic3_get_eth_ctrl_stats, .get_rmon_stats = hinic3_get_rmon_stats, .get_pause_stats = hinic3_get_pause_stats, + .get_coalesce = hinic3_get_coalesce, + .set_coalesce = hinic3_set_coalesce, };void hinic3_set_ethtool_ops (struct net_device *netdev)
drivers/net/ethernet/huawei/hinic3/hinic3_irq.c +8 -4
@@ -20,7 +20,7 @@ static void hinic3_net_dim(struct hinic3_nic_dev *nic_dev,struct dim_sample sample = {};if (!test_bit (HINIC3_INTF_UP , &nic_dev->flags) || - !nic_dev->adaptive_rx_coal) + !READ_ONCE (nic_dev->adaptive_rx_coal))return ; dim_update_sample(irq_cfg->total_events, rxq->rxq_stats.packets,
@@ -105,6 +105,7 @@ static int hinic3_request_irq(struct hinic3_irq_cfg *irq_cfg, u16 q_id) info.coalesc_timer_cfg = nic_dev->intr_coalesce[q_id].coalesce_timer_cfg; info.resend_timer_cfg = nic_dev->intr_coalesce[q_id].resend_timer_cfg; + err =hinic3_set_interrupt_cfg (nic_dev->hwdev, info);if (err) {netdev_err (netdev,"Failed to set RX interrupt coalescing attribute.\n" );
@@ -162,17 +163,20 @@ static int hinic3_set_interrupt_moder(struct net_device *netdev, u16 q_id,static void hinic3_update_queue_coal (struct net_device *netdev,u16 q_id,u16 coal_timer,u16 coal_pkts) { +u8 coalesc_timer_cfg, pending_limit, limit_low, limit_high;struct hinic3_intr_coal_info *q_coal; -u8 coalesc_timer_cfg, pending_limit;struct hinic3_nic_dev *nic_dev; nic_dev =netdev_priv (netdev); q_coal = &nic_dev->intr_coalesce[q_id]; coalesc_timer_cfg = (u8 )coal_timer; + + limit_low = q_coal->rx_pending_limit_low; + limit_high = q_coal->rx_pending_limit_high; + pending_limit =clamp_t (u8, coal_pkts >>HINIC3_COAL_PKT_SHIFT , - q_coal->rx_pending_limit_low, - q_coal->rx_pending_limit_high); + limit_low, limit_high);hinic3_set_interrupt_moder (nic_dev->netdev, q_id, coalesc_timer_cfg, pending_limit);
drivers/net/ethernet/huawei/hinic3/hinic3_main.c +1 -1
@@ -51,7 +51,7 @@ static void init_intr_coal_param(struct net_device *netdev) info->rx_pending_limit_low =HINIC3_RX_PENDING_LIMIT_LOW ; } - nic_dev->adaptive_rx_coal =1 ; +WRITE_ONCE (nic_dev->adaptive_rx_coal,1 ); }static int hinic3_init_intr_coalesce (struct net_device *netdev)
Signature · 1 line
2.54.0
Fan Gong
maintainerPATCH v11 4/5 hinic3: Add ethtool rss ops
In reply to Fan Gong Implement following ethtool callback function:
.get_rxnfc
.set_rxnfc
.get_channels
.set_channels
.get_rxfh_indir_size
.get_rxfh_key_size
.get_rxfh
.set_rxfh
These callbacks allow users to utilize ethtool for detailed
RSS parameters configuration and monitoring.
--- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 10 + .../huawei/hinic3/hinic3_mgmt_interface.h | 2 + .../net/ethernet/huawei/hinic3/hinic3_rss.c | 561 +++++++++++++++++- .../net/ethernet/huawei/hinic3/hinic3_rss.h | 20 + 4 files changed, 591 insertions(+), 2 deletions(-)
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +10 -0
@@ -16,6 +16,7 @@#include "hinic3_hw_comm.h" #include "hinic3_nic_dev.h" #include "hinic3_nic_cfg.h" +#include "hinic3_rss.h" #define HINIC3_MGMT_VERSION_MAX_LEN 32/* Coalesce time properties in microseconds */
@@ -1273,6 +1274,15 @@ static const struct ethtool_ops hinic3_ethtool_ops = { .get_pause_stats = hinic3_get_pause_stats, .get_coalesce = hinic3_get_coalesce, .set_coalesce = hinic3_set_coalesce, + .get_rxnfc = hinic3_get_rxnfc, + .set_rxnfc = hinic3_set_rxnfc, + .get_rx_ring_count = hinic3_get_rx_ring_count, + .get_channels = hinic3_get_channels, + .set_channels = hinic3_set_channels, + .get_rxfh_indir_size = hinic3_get_rxfh_indir_size, + .get_rxfh_key_size = hinic3_get_rxfh_key_size, + .get_rxfh = hinic3_get_rxfh, + .set_rxfh = hinic3_set_rxfh, };void hinic3_set_ethtool_ops (struct net_device *netdev)
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +2 -0
@@ -282,6 +282,7 @@ enum l2nic_cmd {L2NIC_CMD_SET_VLAN_FILTER_EN =26 ,L2NIC_CMD_SET_RX_VLAN_OFFLOAD =27 ,L2NIC_CMD_CFG_RSS =60 , +L2NIC_CMD_GET_RSS_CTX_TBL =62 ,L2NIC_CMD_CFG_RSS_HASH_KEY =63 ,L2NIC_CMD_CFG_RSS_HASH_ENGINE =64 , L2NIC_CMD_SET_RSS_CTX_TBL = 65,
@@ -301,6 +302,7 @@ enum l2nic_ucode_cmd {L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX =0 ,L2NIC_UCODE_CMD_CLEAN_QUEUE_CTX =1 ,L2NIC_UCODE_CMD_SET_RSS_INDIR_TBL =4 , + L2NIC_UCODE_CMD_GET_RSS_INDIR_TBL = 6, };/* hilink mac group command */
drivers/net/ethernet/huawei/hinic3/hinic3_rss.c +559 -2
582 lines not on this page · raw message
drivers/net/ethernet/huawei/hinic3/hinic3_rss.h +20 -0
@@ -5,10 +5,30 @@#define _HINIC3_RSS_H_#include <linux/netdevice.h> +#include <linux/ethtool.h> int hinic3_rss_init (struct net_device *netdev);void hinic3_rss_uninit (struct net_device *netdev);void hinic3_try_to_enable_rss (struct net_device *netdev);void hinic3_clear_rss_config (struct net_device *netdev); +int hinic3_get_rxnfc (struct net_device *netdev, +struct ethtool_rxnfc *cmd,u32 *rule_locs); +int hinic3_set_rxnfc (struct net_device *netdev,struct ethtool_rxnfc *cmd); + +void hinic3_get_channels (struct net_device *netdev, +struct ethtool_channels *channels); +int hinic3_set_channels (struct net_device *netdev, +struct ethtool_channels *channels); + +u32 hinic3_get_rxfh_indir_size (struct net_device *netdev); +u32 hinic3_get_rxfh_key_size (struct net_device *netdev); + +u32 hinic3_get_rx_ring_count (struct net_device *netdev); +int hinic3_get_rxfh (struct net_device *netdev, +struct ethtool_rxfh_param *rxfh); +int hinic3_set_rxfh (struct net_device *netdev, +struct ethtool_rxfh_param *rxfh, +struct netlink_ext_ack *extack); +#endif
Signature · 1 line
2.54.0
Fan Gong
maintainerPATCH v11 5/5 hinic3: Remove unneeded coalesce parameters
In reply to Fan GongRemove unneeded coalesce parameters in irq handling.
--- drivers/net/ethernet/huawei/hinic3/hinic3_irq.c | 6 +----- drivers/net/ethernet/huawei/hinic3/hinic3_rx.h | 3 --- 2 files changed, 1 insertion(+), 8 deletions(-)
drivers/net/ethernet/huawei/hinic3/hinic3_irq.c +1 -5
@@ -149,13 +149,9 @@ static int hinic3_set_interrupt_moder(struct net_device *netdev, u16 q_id, nic_dev->intr_coalesce[q_id].resend_timer_cfg; err =hinic3_set_interrupt_cfg (nic_dev->hwdev, info); -if (err) { +if (err)netdev_err (netdev,"Failed to modify moderation for Queue: %u\n" , q_id); - }else { - nic_dev->rxqs[q_id].last_coalesc_timer_cfg = coalesc_timer_cfg; - nic_dev->rxqs[q_id].last_pending_limit = pending_limit; - }return err; }
drivers/net/ethernet/huawei/hinic3/hinic3_rx.h +0 -3
@@ -111,9 +111,6 @@ struct hinic3_rxq {dma_addr_t cqe_start_paddr;struct dim dim; - -u8 last_coalesc_timer_cfg; -u8 last_pending_limit; }____cacheline_aligned ;struct hinic3_dyna_rxq_res {
Signature · 1 line
2.54.0