Commit c3e79baf authored by Aviad Krawczyk's avatar Aviad Krawczyk Committed by David S. Miller

net-next/hinic: Add logical Txq and Rxq

Create the logical queues of the nic.
Signed-off-by: default avatarAviad Krawczyk <aviad.krawczyk@huawei.com>
Signed-off-by: default avatarZhao Chen <zhaochen6@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c4d06d2d
obj-$(CONFIG_HINIC) += hinic.o
hinic-y := hinic_main.o hinic_port.o hinic_hw_dev.o hinic_hw_mgmt.o \
hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o
hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \
hinic_hw_io.o hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o \
hinic_hw_if.o
......@@ -23,6 +23,8 @@
#include <linux/bitops.h>
#include "hinic_hw_dev.h"
#include "hinic_tx.h"
#include "hinic_rx.h"
#define HINIC_DRV_NAME "hinic"
......@@ -49,6 +51,9 @@ struct hinic_dev {
struct hinic_rx_mode_work rx_mode_work;
struct workqueue_struct *workq;
struct hinic_txq *txqs;
struct hinic_rxq *rxqs;
};
#endif
......@@ -25,6 +25,8 @@
#include "hinic_hw_if.h"
#include "hinic_hw_eqs.h"
#include "hinic_hw_mgmt.h"
#include "hinic_hw_qp.h"
#include "hinic_hw_io.h"
#include "hinic_hw_dev.h"
#define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \
......@@ -229,6 +231,99 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
HINIC_MGMT_MSG_SYNC);
}
/**
* get_base_qpn - get the first qp number
* @hwdev: the NIC HW device
* @base_qpn: returned qp number
*
* Return 0 - Success, negative - Failure
**/
static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn)
{
struct hinic_cmd_base_qpn cmd_base_qpn;
struct hinic_hwif *hwif = hwdev->hwif;
struct pci_dev *pdev = hwif->pdev;
u16 out_size;
int err;
cmd_base_qpn.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_GLOBAL_QPN,
&cmd_base_qpn, sizeof(cmd_base_qpn),
&cmd_base_qpn, &out_size);
if (err || (out_size != sizeof(cmd_base_qpn)) || cmd_base_qpn.status) {
dev_err(&pdev->dev, "Failed to get base qpn, status = %d\n",
cmd_base_qpn.status);
return -EFAULT;
}
*base_qpn = cmd_base_qpn.qpn;
return 0;
}
/**
* hinic_hwdev_ifup - Preparing the HW for passing IO
* @hwdev: the NIC HW device
*
* Return 0 - Success, negative - Failure
**/
int hinic_hwdev_ifup(struct hinic_hwdev *hwdev)
{
struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
struct hinic_cap *nic_cap = &hwdev->nic_cap;
struct hinic_hwif *hwif = hwdev->hwif;
int err, num_aeqs, num_ceqs, num_qps;
struct msix_entry *sq_msix_entries;
struct msix_entry *rq_msix_entries;
struct pci_dev *pdev = hwif->pdev;
u16 base_qpn;
err = get_base_qpn(hwdev, &base_qpn);
if (err) {
dev_err(&pdev->dev, "Failed to get global base qp number\n");
return err;
}
num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);
err = hinic_io_init(func_to_io, hwif, nic_cap->max_qps, 0, NULL);
if (err) {
dev_err(&pdev->dev, "Failed to init IO channel\n");
return err;
}
num_qps = nic_cap->num_qps;
sq_msix_entries = &hwdev->msix_entries[num_aeqs + num_ceqs];
rq_msix_entries = &hwdev->msix_entries[num_aeqs + num_ceqs + num_qps];
err = hinic_io_create_qps(func_to_io, base_qpn, num_qps,
sq_msix_entries, rq_msix_entries);
if (err) {
dev_err(&pdev->dev, "Failed to create QPs\n");
goto err_create_qps;
}
return 0;
err_create_qps:
hinic_io_free(func_to_io);
return err;
}
/**
* hinic_hwdev_ifdown - Closing the HW for passing IO
* @hwdev: the NIC HW device
*
**/
void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev)
{
struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
struct hinic_cap *nic_cap = &hwdev->nic_cap;
hinic_io_destroy_qps(func_to_io, nic_cap->num_qps);
hinic_io_free(func_to_io);
}
/**
* hinic_hwdev_cb_register - register callback handler for MGMT events
* @hwdev: the NIC HW device
......@@ -499,3 +594,39 @@ int hinic_hwdev_num_qps(struct hinic_hwdev *hwdev)
return nic_cap->num_qps;
}
/**
* hinic_hwdev_get_sq - get SQ
* @hwdev: the NIC HW device
* @i: the position of the SQ
*
* Return: the SQ in the i position
**/
struct hinic_sq *hinic_hwdev_get_sq(struct hinic_hwdev *hwdev, int i)
{
struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
struct hinic_qp *qp = &func_to_io->qps[i];
if (i >= hinic_hwdev_num_qps(hwdev))
return NULL;
return &qp->sq;
}
/**
* hinic_hwdev_get_sq - get RQ
* @hwdev: the NIC HW device
* @i: the position of the RQ
*
* Return: the RQ in the i position
**/
struct hinic_rq *hinic_hwdev_get_rq(struct hinic_hwdev *hwdev, int i)
{
struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
struct hinic_qp *qp = &func_to_io->qps[i];
if (i >= hinic_hwdev_num_qps(hwdev))
return NULL;
return &qp->rq;
}
......@@ -23,6 +23,8 @@
#include "hinic_hw_if.h"
#include "hinic_hw_eqs.h"
#include "hinic_hw_mgmt.h"
#include "hinic_hw_qp.h"
#include "hinic_hw_io.h"
#define HINIC_MAX_QPS 32
......@@ -72,11 +74,21 @@ enum hinic_cb_state {
HINIC_CB_RUNNING = BIT(1),
};
struct hinic_cmd_base_qpn {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
u16 qpn;
};
struct hinic_hwdev {
struct hinic_hwif *hwif;
struct msix_entry *msix_entries;
struct hinic_aeqs aeqs;
struct hinic_func_to_io func_to_io;
struct hinic_cap nic_cap;
};
......@@ -111,10 +123,18 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
void *buf_in, u16 in_size, void *buf_out,
u16 *out_size);
int hinic_hwdev_ifup(struct hinic_hwdev *hwdev);
void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev);
struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev);
void hinic_free_hwdev(struct hinic_hwdev *hwdev);
int hinic_hwdev_num_qps(struct hinic_hwdev *hwdev);
struct hinic_sq *hinic_hwdev_get_sq(struct hinic_hwdev *hwdev, int i);
struct hinic_rq *hinic_hwdev_get_rq(struct hinic_hwdev *hwdev, int i);
#endif
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include "hinic_hw_if.h"
#include "hinic_hw_qp.h"
#include "hinic_hw_io.h"
/**
* init_qp - Initialize a Queue Pair
* @func_to_io: func to io channel that holds the IO components
* @qp: pointer to the qp to initialize
* @q_id: the id of the qp
* @sq_msix_entry: msix entry for sq
* @rq_msix_entry: msix entry for rq
*
* Return 0 - Success, negative - Failure
**/
static int init_qp(struct hinic_func_to_io *func_to_io,
struct hinic_qp *qp, int q_id,
struct msix_entry *sq_msix_entry,
struct msix_entry *rq_msix_entry)
{
/* should be implemented */
return 0;
}
/**
* destroy_qp - Clean the resources of a Queue Pair
* @func_to_io: func to io channel that holds the IO components
* @qp: pointer to the qp to clean
**/
static void destroy_qp(struct hinic_func_to_io *func_to_io,
struct hinic_qp *qp)
{
/* should be implemented */
}
/**
* hinic_io_create_qps - Create Queue Pairs
* @func_to_io: func to io channel that holds the IO components
* @base_qpn: base qp number
* @num_qps: number queue pairs to create
* @sq_msix_entry: msix entries for sq
* @rq_msix_entry: msix entries for rq
*
* Return 0 - Success, negative - Failure
**/
int hinic_io_create_qps(struct hinic_func_to_io *func_to_io,
u16 base_qpn, int num_qps,
struct msix_entry *sq_msix_entries,
struct msix_entry *rq_msix_entries)
{
struct hinic_hwif *hwif = func_to_io->hwif;
struct pci_dev *pdev = hwif->pdev;
size_t qps_size;
int i, j, err;
qps_size = num_qps * sizeof(*func_to_io->qps);
func_to_io->qps = devm_kzalloc(&pdev->dev, qps_size, GFP_KERNEL);
if (!func_to_io->qps)
return -ENOMEM;
for (i = 0; i < num_qps; i++) {
err = init_qp(func_to_io, &func_to_io->qps[i], i,
&sq_msix_entries[i], &rq_msix_entries[i]);
if (err) {
dev_err(&pdev->dev, "Failed to create QP %d\n", i);
goto err_init_qp;
}
}
return 0;
err_init_qp:
for (j = 0; j < i; j++)
destroy_qp(func_to_io, &func_to_io->qps[j]);
devm_kfree(&pdev->dev, func_to_io->qps);
return err;
}
/**
* hinic_io_destroy_qps - Destroy the IO Queue Pairs
* @func_to_io: func to io channel that holds the IO components
* @num_qps: number queue pairs to destroy
**/
void hinic_io_destroy_qps(struct hinic_func_to_io *func_to_io, int num_qps)
{
struct hinic_hwif *hwif = func_to_io->hwif;
struct pci_dev *pdev = hwif->pdev;
int i;
for (i = 0; i < num_qps; i++)
destroy_qp(func_to_io, &func_to_io->qps[i]);
devm_kfree(&pdev->dev, func_to_io->qps);
}
/**
* hinic_io_init - Initialize the IO components
* @func_to_io: func to io channel that holds the IO components
* @hwif: HW interface for accessing IO
* @max_qps: maximum QPs in HW
* @num_ceqs: number completion event queues
* @ceq_msix_entries: msix entries for ceqs
*
* Return 0 - Success, negative - Failure
**/
int hinic_io_init(struct hinic_func_to_io *func_to_io,
struct hinic_hwif *hwif, u16 max_qps, int num_ceqs,
struct msix_entry *ceq_msix_entries)
{
func_to_io->hwif = hwif;
func_to_io->qps = NULL;
func_to_io->max_qps = max_qps;
return 0;
}
/**
* hinic_io_free - Free the IO components
* @func_to_io: func to io channel that holds the IO components
**/
void hinic_io_free(struct hinic_func_to_io *func_to_io)
{
}
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#ifndef HINIC_HW_IO_H
#define HINIC_HW_IO_H
#include <linux/types.h>
#include <linux/pci.h>
#include "hinic_hw_if.h"
#include "hinic_hw_qp.h"
struct hinic_func_to_io {
struct hinic_hwif *hwif;
struct hinic_qp *qps;
u16 max_qps;
};
int hinic_io_create_qps(struct hinic_func_to_io *func_to_io,
u16 base_qpn, int num_qps,
struct msix_entry *sq_msix_entries,
struct msix_entry *rq_msix_entries);
void hinic_io_destroy_qps(struct hinic_func_to_io *func_to_io,
int num_qps);
int hinic_io_init(struct hinic_func_to_io *func_to_io,
struct hinic_hwif *hwif, u16 max_qps, int num_ceqs,
struct msix_entry *ceq_msix_entries);
void hinic_io_free(struct hinic_func_to_io *func_to_io);
#endif
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#ifndef HINIC_HW_QP_H
#define HINIC_HW_QP_H
struct hinic_sq {
/* should be implemented */
};
struct hinic_rq {
/* should be implemented */
};
struct hinic_qp {
struct hinic_sq sq;
struct hinic_rq rq;
};
#endif
......@@ -31,8 +31,11 @@
#include <linux/delay.h>
#include <linux/err.h>
#include "hinic_hw_qp.h"
#include "hinic_hw_dev.h"
#include "hinic_port.h"
#include "hinic_tx.h"
#include "hinic_rx.h"
#include "hinic_dev.h"
MODULE_AUTHOR("Huawei Technologies CO., Ltd");
......@@ -57,17 +60,164 @@ MODULE_LICENSE("GPL");
static int change_mac_addr(struct net_device *netdev, const u8 *addr);
/**
* create_txqs - Create the Logical Tx Queues of specific NIC device
* @nic_dev: the specific NIC device
*
* Return 0 - Success, negative - Failure
**/
static int create_txqs(struct hinic_dev *nic_dev)
{
int err, i, j, num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev);
struct net_device *netdev = nic_dev->netdev;
size_t txq_size;
if (nic_dev->txqs)
return -EINVAL;
txq_size = num_txqs * sizeof(*nic_dev->txqs);
nic_dev->txqs = devm_kzalloc(&netdev->dev, txq_size, GFP_KERNEL);
if (!nic_dev->txqs)
return -ENOMEM;
for (i = 0; i < num_txqs; i++) {
struct hinic_sq *sq = hinic_hwdev_get_sq(nic_dev->hwdev, i);
err = hinic_init_txq(&nic_dev->txqs[i], sq, netdev);
if (err) {
netif_err(nic_dev, drv, netdev,
"Failed to init Txq\n");
goto err_init_txq;
}
}
return 0;
err_init_txq:
for (j = 0; j < i; j++)
hinic_clean_txq(&nic_dev->txqs[j]);
devm_kfree(&netdev->dev, nic_dev->txqs);
return err;
}
/**
* free_txqs - Free the Logical Tx Queues of specific NIC device
* @nic_dev: the specific NIC device
**/
static void free_txqs(struct hinic_dev *nic_dev)
{
int i, num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev);
struct net_device *netdev = nic_dev->netdev;
if (!nic_dev->txqs)
return;
for (i = 0; i < num_txqs; i++)
hinic_clean_txq(&nic_dev->txqs[i]);
devm_kfree(&netdev->dev, nic_dev->txqs);
nic_dev->txqs = NULL;
}
/**
* create_txqs - Create the Logical Rx Queues of specific NIC device
* @nic_dev: the specific NIC device
*
* Return 0 - Success, negative - Failure
**/
static int create_rxqs(struct hinic_dev *nic_dev)
{
int err, i, j, num_rxqs = hinic_hwdev_num_qps(nic_dev->hwdev);
struct net_device *netdev = nic_dev->netdev;
size_t rxq_size;
if (nic_dev->rxqs)
return -EINVAL;
rxq_size = num_rxqs * sizeof(*nic_dev->rxqs);
nic_dev->rxqs = devm_kzalloc(&netdev->dev, rxq_size, GFP_KERNEL);
if (!nic_dev->rxqs)
return -ENOMEM;
for (i = 0; i < num_rxqs; i++) {
struct hinic_rq *rq = hinic_hwdev_get_rq(nic_dev->hwdev, i);
err = hinic_init_rxq(&nic_dev->rxqs[i], rq, netdev);
if (err) {
netif_err(nic_dev, drv, netdev,
"Failed to init rxq\n");
goto err_init_rxq;
}
}
return 0;
err_init_rxq:
for (j = 0; j < i; j++)
hinic_clean_rxq(&nic_dev->rxqs[j]);
devm_kfree(&netdev->dev, nic_dev->rxqs);
return err;
}
/**
* free_txqs - Free the Logical Rx Queues of specific NIC device
* @nic_dev: the specific NIC device
**/
static void free_rxqs(struct hinic_dev *nic_dev)
{
int i, num_rxqs = hinic_hwdev_num_qps(nic_dev->hwdev);
struct net_device *netdev = nic_dev->netdev;
if (!nic_dev->rxqs)
return;
for (i = 0; i < num_rxqs; i++)
hinic_clean_rxq(&nic_dev->rxqs[i]);
devm_kfree(&netdev->dev, nic_dev->rxqs);
nic_dev->rxqs = NULL;
}
static int hinic_open(struct net_device *netdev)
{
struct hinic_dev *nic_dev = netdev_priv(netdev);
enum hinic_port_link_state link_state;
int err, ret;
int err, ret, num_qps;
if (!(nic_dev->flags & HINIC_INTF_UP)) {
err = hinic_hwdev_ifup(nic_dev->hwdev);
if (err) {
netif_err(nic_dev, drv, netdev,
"Failed - HW interface up\n");
return err;
}
}
err = create_txqs(nic_dev);
if (err) {
netif_err(nic_dev, drv, netdev,
"Failed to create Tx queues\n");
goto err_create_txqs;
}
err = create_rxqs(nic_dev);
if (err) {
netif_err(nic_dev, drv, netdev,
"Failed to create Rx queues\n");
goto err_create_rxqs;
}
num_qps = hinic_hwdev_num_qps(nic_dev->hwdev);
netif_set_real_num_tx_queues(netdev, num_qps);
netif_set_real_num_rx_queues(netdev, num_qps);
err = hinic_port_set_state(nic_dev, HINIC_PORT_ENABLE);
if (err) {
netif_err(nic_dev, drv, netdev,
"Failed to set port state\n");
return err;
goto err_port_state;
}
/* Wait up to 3 sec between port enable to link state */
......@@ -104,6 +254,16 @@ static int hinic_open(struct net_device *netdev)
if (ret)
netif_warn(nic_dev, drv, netdev,
"Failed to revert port state\n");
err_port_state:
free_rxqs(nic_dev);
err_create_rxqs:
free_txqs(nic_dev);
err_create_txqs:
if (!(nic_dev->flags & HINIC_INTF_UP))
hinic_hwdev_ifdown(nic_dev->hwdev);
return err;
}
......@@ -130,6 +290,12 @@ static int hinic_close(struct net_device *netdev)
return err;
}
free_rxqs(nic_dev);
free_txqs(nic_dev);
if (flags & HINIC_INTF_UP)
hinic_hwdev_ifdown(nic_dev->hwdev);
netif_info(nic_dev, drv, netdev, "HINIC_INTF is DOWN\n");
return 0;
}
......@@ -496,6 +662,8 @@ static int nic_dev_init(struct pci_dev *pdev)
nic_dev->hwdev = hwdev;
nic_dev->msg_enable = MSG_ENABLE_DEFAULT;
nic_dev->flags = 0;
nic_dev->txqs = NULL;
nic_dev->rxqs = NULL;
sema_init(&nic_dev->mgmt_lock, 1);
......
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#include <linux/netdevice.h>
#include <linux/u64_stats_sync.h>
#include "hinic_hw_qp.h"
#include "hinic_rx.h"
/**
* hinic_rxq_clean_stats - Clean the statistics of specific queue
* @rxq: Logical Rx Queue
**/
void hinic_rxq_clean_stats(struct hinic_rxq *rxq)
{
struct hinic_rxq_stats *rxq_stats = &rxq->rxq_stats;
u64_stats_update_begin(&rxq_stats->syncp);
rxq_stats->pkts = 0;
rxq_stats->bytes = 0;
u64_stats_update_end(&rxq_stats->syncp);
}
/**
* rxq_stats_init - Initialize the statistics of specific queue
* @rxq: Logical Rx Queue
**/
static void rxq_stats_init(struct hinic_rxq *rxq)
{
struct hinic_rxq_stats *rxq_stats = &rxq->rxq_stats;
u64_stats_init(&rxq_stats->syncp);
hinic_rxq_clean_stats(rxq);
}
/**
* hinic_init_rxq - Initialize the Rx Queue
* @rxq: Logical Rx Queue
* @rq: Hardware Rx Queue to connect the Logical queue with
* @netdev: network device to connect the Logical queue with
*
* Return 0 - Success, negative - Failure
**/
int hinic_init_rxq(struct hinic_rxq *rxq, struct hinic_rq *rq,
struct net_device *netdev)
{
rxq->netdev = netdev;
rxq->rq = rq;
rxq_stats_init(rxq);
return 0;
}
/**
* hinic_clean_rxq - Clean the Rx Queue
* @rxq: Logical Rx Queue
**/
void hinic_clean_rxq(struct hinic_rxq *rxq)
{
}
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#ifndef HINIC_RX_H
#define HINIC_RX_H
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/u64_stats_sync.h>
#include "hinic_hw_qp.h"
struct hinic_rxq_stats {
u64 pkts;
u64 bytes;
struct u64_stats_sync syncp;
};
struct hinic_rxq {
struct net_device *netdev;
struct hinic_rq *rq;
struct hinic_rxq_stats rxq_stats;
};
void hinic_rxq_clean_stats(struct hinic_rxq *rxq);
int hinic_init_rxq(struct hinic_rxq *rxq, struct hinic_rq *rq,
struct net_device *netdev);
void hinic_clean_rxq(struct hinic_rxq *rxq);
#endif
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#include <linux/netdevice.h>
#include <linux/u64_stats_sync.h>
#include "hinic_hw_qp.h"
#include "hinic_tx.h"
/**
* hinic_txq_clean_stats - Clean the statistics of specific queue
* @txq: Logical Tx Queue
**/
void hinic_txq_clean_stats(struct hinic_txq *txq)
{
struct hinic_txq_stats *txq_stats = &txq->txq_stats;
u64_stats_update_begin(&txq_stats->syncp);
txq_stats->pkts = 0;
txq_stats->bytes = 0;
txq_stats->tx_busy = 0;
txq_stats->tx_wake = 0;
txq_stats->tx_dropped = 0;
u64_stats_update_end(&txq_stats->syncp);
}
/**
* txq_stats_init - Initialize the statistics of specific queue
* @txq: Logical Tx Queue
**/
static void txq_stats_init(struct hinic_txq *txq)
{
struct hinic_txq_stats *txq_stats = &txq->txq_stats;
u64_stats_init(&txq_stats->syncp);
hinic_txq_clean_stats(txq);
}
/**
* hinic_init_txq - Initialize the Tx Queue
* @txq: Logical Tx Queue
* @sq: Hardware Tx Queue to connect the Logical queue with
* @netdev: network device to connect the Logical queue with
*
* Return 0 - Success, negative - Failure
**/
int hinic_init_txq(struct hinic_txq *txq, struct hinic_sq *sq,
struct net_device *netdev)
{
txq->netdev = netdev;
txq->sq = sq;
txq_stats_init(txq);
return 0;
}
/**
* hinic_clean_txq - Clean the Tx Queue
* @txq: Logical Tx Queue
**/
void hinic_clean_txq(struct hinic_txq *txq)
{
}
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#ifndef HINIC_TX_H
#define HINIC_TX_H
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/u64_stats_sync.h>
#include "hinic_hw_qp.h"
struct hinic_txq_stats {
u64 pkts;
u64 bytes;
u64 tx_busy;
u64 tx_wake;
u64 tx_dropped;
struct u64_stats_sync syncp;
};
struct hinic_txq {
struct net_device *netdev;
struct hinic_sq *sq;
struct hinic_txq_stats txq_stats;
};
void hinic_txq_clean_stats(struct hinic_txq *txq);
int hinic_init_txq(struct hinic_txq *txq, struct hinic_sq *sq,
struct net_device *netdev);
void hinic_clean_txq(struct hinic_txq *txq);
#endif
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