Skip to contentSkip to conversation

Huawei HiNIC Ethernet Driver

PATCH Superseded Aviad Krawczyk 6 participants 36 messages Jul 19, 2017 – Jul 30, 2017

Subsystems (4)

v2 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

v2 cover Huawei HiNIC Ethernet Driver

The patch-set contains the support of the HiNIC Ethernet driver for hinic family of PCIE Network Interface Cards.

The Huawei's PCIE HiNIC card is a new Ethernet card and hence there was a need of a new driver.

The current driver is meant to be used for the Physical Function and there would soon be a support for Virtual Function and more features once the basic PF driver has been accepted.

Changes v1 -> v2:
1. remove driver version - Andrew Lunn comment

	https://lkml.org/lkml/2017/7/12/372
2. replace kzalloc by devm_kzalloc for short clean - Andrew Lunn comment
	https://lkml.org/lkml/2017/7/12/372
3. replace pr_ functions by dev_ functions - Andrew Lunn comment
	https://lkml.org/lkml/2017/7/12/375
4. seperate last patch by moving ops to a new patch - Andrew Lunn comment
	https://lkml.org/lkml/2017/7/12/377

Aviad Krawczyk (21):
net-next/hinic: Initialize hw interface net-next/hinic: Initialize hw device components net-next/hinic: Initialize api cmd resources net-next/hinic: Initialize api cmd hw net-next/hinic: Add management messages net-next/hinic: Add api cmd commands net-next/hinic: Add aeqs
net-next/hinic: Add port management commands net-next/hinic: Add Rx mode and link event handler net-next/hinic: Add logical Txq and Rxq net-next/hinic: Add wq
net-next/hinic: Add qp resources net-next/hinic: Set qp context net-next/hinic: Initialize cmdq net-next/hinic: Add ceqs
net-next/hinic: Add cmdq commands net-next/hinic: Add cmdq completion handler net-next/hinic: Add Rx handler net-next/hinic: Add Tx operation net-next/hinic: Add ethtool and stats net-next/hinic: Add select_queue and netpoll

 Documentation/networking/hinic.txt                 |  125 +++
 MAINTAINERS                                        |    7 +
 drivers/net/ethernet/Kconfig                       |    1 +
 drivers/net/ethernet/Makefile                      |    1 +
 drivers/net/ethernet/huawei/Kconfig                |   19 +
 drivers/net/ethernet/huawei/Makefile               |    5 +
 drivers/net/ethernet/huawei/hinic/Kconfig          |   13 +
 drivers/net/ethernet/huawei/hinic/Makefile         |    6 +
 drivers/net/ethernet/huawei/hinic/hinic_common.c   |   80 ++
 drivers/net/ethernet/huawei/hinic/hinic_common.h   |   38 +
 drivers/net/ethernet/huawei/hinic/hinic_dev.h      |   64 ++
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c   |  978 +++++++++++++++++
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h   |  208 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c  |  940 ++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h  |  302 ++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h   |  149 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c   | 1058 ++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h   |  239 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c   |  877 +++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h   |  265 +++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c    |  353 ++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h    |  272 +++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c    |  537 +++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h    |   97 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c  |  599 ++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h  |  153 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c    |  864 +++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h    |  394 +++++++
 .../net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h   |  214 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c    |  885 +++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h    |  113 ++
 drivers/net/ethernet/huawei/hinic/hinic_main.c     | 1142 ++++++++++++++++++++
 .../net/ethernet/huawei/hinic/hinic_pci_id_tbl.h   |   27 +
 drivers/net/ethernet/huawei/hinic/hinic_port.c     |  403 +++++++
 drivers/net/ethernet/huawei/hinic/hinic_port.h     |  198 ++++
 drivers/net/ethernet/huawei/hinic/hinic_rx.c       |  518 +++++++++
 drivers/net/ethernet/huawei/hinic/hinic_rx.h       |   55 +
 drivers/net/ethernet/huawei/hinic/hinic_tx.c       |  516 +++++++++
 drivers/net/ethernet/huawei/hinic/hinic_tx.h       |   62 ++
 39 files changed, 12777 insertions(+)
 create mode 100644 Documentation/networking/hinic.txt
 create mode 100644 drivers/net/ethernet/huawei/Kconfig
 create mode 100644 drivers/net/ethernet/huawei/Makefile
 create mode 100644 drivers/net/ethernet/huawei/hinic/Kconfig
 create mode 100644 drivers/net/ethernet/huawei/hinic/Makefile
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_common.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_common.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_dev.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_main.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_port.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_port.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_rx.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_rx.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_tx.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_tx.h
Signature · 1 line
1.9.1
#1 lore raw

PATCH v2 1/21 net-next/hinic: Initialize hw interface

Initialize hw interface as part of the nic initialization for accessing hw.

---
 Documentation/networking/hinic.txt                 | 125 ++++++++++++
 drivers/net/ethernet/Kconfig                       |   1 +
 drivers/net/ethernet/Makefile                      |   1 +
 drivers/net/ethernet/huawei/Kconfig                |  19 ++
 drivers/net/ethernet/huawei/Makefile               |   5 +
 drivers/net/ethernet/huawei/hinic/Kconfig          |  13 ++
 drivers/net/ethernet/huawei/hinic/Makefile         |   3 +
 drivers/net/ethernet/huawei/hinic/hinic_dev.h      |  33 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h   |  36 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c   | 208 ++++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h   |  42 +++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c    | 208 ++++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h    | 160 ++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_main.c     | 209 +++++++++++++++++++++
 .../net/ethernet/huawei/hinic/hinic_pci_id_tbl.h   |  27 +++
 15 files changed, 1090 insertions(+)
 create mode 100644 Documentation/networking/hinic.txt
 create mode 100644 drivers/net/ethernet/huawei/Kconfig
 create mode 100644 drivers/net/ethernet/huawei/Makefile
 create mode 100644 drivers/net/ethernet/huawei/hinic/Kconfig
 create mode 100644 drivers/net/ethernet/huawei/hinic/Makefile
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_dev.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_main.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h
Documentation/networking/hinic.txt new file +125 -0
new file mode 100644
index 0000000..989366a
@@ -0,0 +1,125 @@
+Linux Kernel Driver for Huawei Intelligent NIC(HiNIC) family
+============================================================
+
+Overview:
+=========
+HiNIC is a network interface card for the Data Center Area.
+
+The driver supports a range of link-speed devices (10GbE, 25GbE, 40GbE, etc.).
+The driver supports also a negotiated and extendable feature set.
+
+Some HiNIC devices support SR-IOV. This driver is used for Physical Function
+(PF).
+
+HiNIC devices support MSI-X interrupt vector for each Tx/Rx queue and
+adaptive interrupt moderation.
+
+HiNIC devices support also various offload features such as checksum offload,
+TCP Transmit Segmentation Offload(TSO), Receive-Side Scaling(RSS) and
+LRO(Large Receive Offload).
+
+
+Supported PCI vendor ID/device IDs:
+===================================
+
+19e5:1822 - HiNIC PF
+
+
+Driver Architecture and Source Code:
+====================================
+
+hinic_dev - Implement a Logical Network device that is independent from
+specific HW details about HW data structure formats.
+
+hinic_hwdev - Implement the HW details of the device and include the components
+for accessing the PCI NIC.
+
+hinic_hwdev contains the following components:
+===============================================
+
+HW Interface:
+=============
+
+The interface for accessing the pci device (DMA memory and PCI BARs).
+(hinic_hw_if.c, hinic_hw_if.h)
+
+Configuration Status Registers Area that describes the HW Registers on the
+configuration and status BAR0. (hinic_hw_csr.h)
+
+MGMT components:
+================
+
+Asynchronous Event Queues(AEQs) - The event queues for receiving messages from
+the MGMT modules on the cards. (hinic_hw_eqs.c, hinic_hw_eqs.h)
+
+Application Programmable Interface commands(API CMD) - Interface for sending
+MGMT commands to the card. (hinic_hw_api_cmd.c, hinic_hw_api_cmd.h)
+
+Management (MGMT) - the PF to MGMT channel that uses API CMD for sending MGMT
+commands to the card and receives notifications from the MGMT modules on the
+card by AEQs. Also set the addresses of the IO CMDQs in HW.
+(hinic_hw_mgmt.c, hinic_hw_mgmt.h)
+
+IO components:
+==============
+
+Completion Event Queues(CEQs) - The completion Event Queues that describe IO
+tasks that are finished. (hinic_hw_eqs.c, hinic_hw_eqs.h)
+
+Work Queues(WQ) - Contain the memory and operations for use by CMD queues and
+the Queue Pairs. The WQ is a Memory Block in a Page. The Block contains
+pointers to Memory Areas that are the Memory for the Work Queue Elements(WQEs).
+(hinic_hw_wq.c, hinic_hw_wq.h)
+
+Command Queues(CMDQ) - The queues for sending commands for IO management and is
+used to set the QPs addresses in HW. The commands completion events are
+accumulated on the CEQ that is configured to receive the CMDQ completion events.
+(hinic_hw_cmdq.c, hinic_hw_cmdq.h)
+
+Queue Pairs(QPs) - The HW Receive and Send queues for Receiving and Transmitting
+Data. (hinic_hw_qp.c, hinic_hw_qp.h, hinic_hw_qp_ctxt.h)
+
+IO - de/constructs all the IO components. (hinic_hw_io.c, hinic_hw_io.h)
+
+HW device:
+==========
+
+HW device - de/constructs the HW Interface, the MGMT components on the
+initialization of the driver and the IO components on the case of Interface
+UP/DOWN Events. (hinic_hw_dev.c, hinic_hw_dev.h)
+
+
+hinic_dev contains the following components:
+===============================================
+
+PCI ID table - Contains the supported PCI Vendor/Device IDs.
+(hinic_pci_tbl.h)
+
+Port Commands - Send commands to the HW device for port management
+(MAC, Vlan, MTU, ...). (hinic_port.c, hinic_port.h)
+
+Tx Queues - Logical Tx Queues that use the HW Send Queues for transmit.
+The Logical Tx queue is not dependent on the format of the HW Send Queue.
+(hinic_tx.c, hinic_tx.h)
+
+Rx Queues - Logical Rx Queues that use the HW Receive Queues for receive.
+The Logical Rx queue is not dependent on the format of the HW Receive Queue.
+(hinic_rx.c, hinic_rx.h)
+
+hinic_dev - de/constructs the Logical Tx and Rx Queues.
+(hinic_main.c, hinic_dev.h)
+
+
+Miscellaneous:
+=============
+
+Common functions that are used by HW and Logical Device.
+(hinic_common.c, hinic_common.h)
+
+
+Support
+=======
+
+If an issue is identified with the released source code on the supported kernel
+with a supported adapter, email the specific information related to the issue to
[email protected].
drivers/net/ethernet/Kconfig +1 -0
index edae15ac..c604213 100644
@@ -78,6 +78,7 @@ source "drivers/net/ethernet/freescale/Kconfig"
 source "drivers/net/ethernet/fujitsu/Kconfig"
 source "drivers/net/ethernet/hisilicon/Kconfig"
 source "drivers/net/ethernet/hp/Kconfig"
+source "drivers/net/ethernet/huawei/Kconfig"
 source "drivers/net/ethernet/ibm/Kconfig"
 source "drivers/net/ethernet/intel/Kconfig"
 source "drivers/net/ethernet/i825xx/Kconfig"
drivers/net/ethernet/Makefile +1 -0
index bf7f450..a0a03d4 100644
@@ -41,6 +41,7 @@ obj-$(CONFIG_NET_VENDOR_FREESCALE) += freescale/
 obj-$(CONFIG_NET_VENDOR_FUJITSU) += fujitsu/
 obj-$(CONFIG_NET_VENDOR_HISILICON) += hisilicon/
 obj-$(CONFIG_NET_VENDOR_HP) += hp/
+obj-$(CONFIG_NET_VENDOR_HUAWEI) += huawei/
 obj-$(CONFIG_NET_VENDOR_IBM) += ibm/
 obj-$(CONFIG_NET_VENDOR_INTEL) += intel/
 obj-$(CONFIG_NET_VENDOR_I825XX) += i825xx/
drivers/net/ethernet/huawei/Kconfig new file +19 -0
new file mode 100644
index 0000000..c1a95ae
@@ -0,0 +1,19 @@
+#
+# Huawei driver configuration
+#
+
+config NET_VENDOR_HUAWEI
+	bool "Huawei devices"
+	default y
+	---help---
+	  If you have a network (Ethernet) card belonging to this class, say Y.
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about Huawei cards. If you say Y, you will be asked
+	  for your specific card in the following questions.
+
+if NET_VENDOR_HUAWEI
+
+source "drivers/net/ethernet/huawei/hinic/Kconfig"
+
+endif # NET_VENDOR_HUAWEI
drivers/net/ethernet/huawei/Makefile new file +5 -0
new file mode 100644
index 0000000..aa0eb3a
@@ -0,0 +1,5 @@
+#
+# Makefile for the Huawei device drivers.
+#
+
+obj-$(CONFIG_HINIC) += hinic/
\ No newline at end of file
drivers/net/ethernet/huawei/hinic/Kconfig new file +13 -0
new file mode 100644
index 0000000..69f2b1f
@@ -0,0 +1,13 @@
+#
+# Huawei driver configuration
+#
+
+config HINIC
+	tristate "Huawei Intelligent PCIE Network Interface Card"
+	depends on (PCI_MSI && X86)
+	default m
+	---help---
+	  This driver supports HiNIC PCIE Ethernet cards.
+	  To compile this driver as part of the kernel, choose Y here.
+	  If unsure, choose N.
+	  The default is compiled as module.
drivers/net/ethernet/huawei/hinic/Makefile new file +3 -0
new file mode 100644
index 0000000..353cee0
@@ -0,0 +1,3 @@
+obj-$(CONFIG_HINIC) += hinic.o
+
+hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_if.o
drivers/net/ethernet/huawei/hinic/hinic_dev.h new file +33 -0
new file mode 100644
index 0000000..f23e8af
@@ -0,0 +1,33 @@
+/*
+ * 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_DEV_H
+#define HINIC_DEV_H
+
+#include <linux/netdevice.h>
+#include <linux/types.h>
+
+#include "hinic_hw_dev.h"
+
+#define HINIC_DRV_NAME          "HiNIC"
+
+struct hinic_dev {
+	struct net_device               *netdev;
+	struct hinic_hwdev              *hwdev;
+
+	u32                             msg_enable;
+};
+
+#endif
drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h new file +36 -0
new file mode 100644
index 0000000..c3440a9
@@ -0,0 +1,36 @@
+/*
+ * 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_CSR_H
+#define HINIC_HW_CSR_H
+
+/* HW interface registers */
+#define HINIC_CSR_FUNC_ATTR0_ADDR                       0x0
+#define HINIC_CSR_FUNC_ATTR1_ADDR                       0x4
+
+#define HINIC_DMA_ATTR_BASE                             0xC80
+#define HINIC_ELECTION_BASE                             0x4200
+
+#define HINIC_DMA_ATTR_STRIDE                           0x4
+#define HINIC_CSR_DMA_ATTR_ADDR(idx)                    \
+	(HINIC_DMA_ATTR_BASE + (idx) * HINIC_DMA_ATTR_STRIDE)
+
+#define HINIC_PPF_ELECTION_STRIDE                       0x4
+#define HINIC_CSR_MAX_PORTS                             4
+
+#define HINIC_CSR_PPF_ELECTION_ADDR(idx)                \
+	(HINIC_ELECTION_BASE +  (idx) * HINIC_PPF_ELECTION_STRIDE)
+
+#endif
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +208 -0

208 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h new file +42 -0

42 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_if.c new file +208 -0

208 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_if.h new file +160 -0

160 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_main.c new file +209 -0

209 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h new file +27 -0
new file mode 100644
index 0000000..1d92617
@@ -0,0 +1,27 @@
+/*
+ * 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_PCI_ID_TBL_H
+#define HINIC_PCI_ID_TBL_H
+
+#ifndef PCI_VENDOR_ID_HUAWEI
+#define PCI_VENDOR_ID_HUAWEI            0x19e5
+#endif
+
+#ifndef PCI_DEVICE_ID_HI1822_PF
+#define PCI_DEVICE_ID_HI1822_PF         0x1822
+#endif
+
+#endif
Signature · 1 line
1.9.1
#2 lore raw

Re: [PATCH V2 net-next 01/21] net-next/hinic: Initialize hw interface

Aviad Krawczyk <[email protected]> :
[...]

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +0 -0
new file mode 100644
index 0000000..fbc9de4

[...]

Quoted 9 lines

+/**
+ * hinic_init_hwdev - Initialize the NIC HW
+ * @hwdev: the NIC HW device that is returned from the initialization
+ * @pdev: the NIC pci device
+ *
+ * Return 0 - Success, negative - Failure
+ *
+ * Initialize the NIC HW device and return a pointer to it in the first arg
+ **/

Return a pointer and use ERR_PTR / IS_ERR ?

Quoted 16 lines
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +16 -0
+int hinic_init_hwdev(struct hinic_hwdev **hwdev, struct pci_dev *pdev)
+{
+	struct hinic_pfhwdev *pfhwdev;
+	struct hinic_hwif *hwif;
+	int err;
+
+	hwif = devm_kzalloc(&pdev->dev, sizeof(*hwif), GFP_KERNEL);
+	if (!hwif)
+		return -ENOMEM;
+
+	err = hinic_init_hwif(hwif, pdev);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to init HW interface\n");
+		return err;
+	}
+

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c line 134

Quoted 10 lines
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +10 -0
+	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
+		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
+		err = -EFAULT;
+		goto func_type_err;
+	}
+
+	pfhwdev = devm_kzalloc(&pdev->dev, sizeof(*pfhwdev), GFP_KERNEL);
+	if (!pfhwdev) {
+		err = -ENOMEM;
+		goto pfhwdev_alloc_err;

Intel, Mellanox, Broadcom, Amazon and friends use "err_xyz" labels.

Please consider using the same style.

[...]

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c line 177

Quoted 10 lines
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +10 -0
+void hinic_free_hwdev(struct hinic_hwdev *hwdev)
+{
+	struct hinic_hwif *hwif = hwdev->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	struct hinic_pfhwdev *pfhwdev;
+
+	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
+		dev_err(&pdev->dev, "unsupported PCI Function type\n");
+		return;
+	}

If it succeeded in hinic_init_hwdev, how could it fail here ?

If it failed in hinic_init_hwdev, hinic_free_hwdev should not even be called.

-> remove ?

[...]

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c new file +0 -0
new file mode 100644
index 0000000..c61c769

[...]

drivers/net/ethernet/huawei/hinic/hinic_main.c line 167

Quoted 7 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c new file +7 -0
+static void hinic_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct hinic_dev *nic_dev;
+
+	if (!netdev)
+		return;

Your driver is flawed if this test can ever succeed.

[...]

drivers/net/ethernet/huawei/hinic/hinic_main.c line 206

Quoted 9 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c new file +9 -0
+static int __init hinic_init(void)
+{
+	return pci_register_driver(&hinic_driver);
+}
+
+static void __exit hinic_exit(void)
+{
+	pci_unregister_driver(&hinic_driver);
+}

Use module_pci_driver(hinic_driver).

Remove hinic_init() and hinic_exit().

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h new file +0 -0
new file mode 100644
index 0000000..1d92617

[...]

drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h line 21

Quoted 6 lines
drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h new file +6 -0
+#ifndef HINIC_PCI_ID_TBL_H
+#define HINIC_PCI_ID_TBL_H
+
+#ifndef PCI_VENDOR_ID_HUAWEI
+#define PCI_VENDOR_ID_HUAWEI            0x19e5
+#endif

Useless: it duplicates include/linux/pci_ids.h

drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h line 25

Quoted 4 lines
drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h new file +4 -0
+
+#ifndef PCI_DEVICE_ID_HI1822_PF
+#define PCI_DEVICE_ID_HI1822_PF         0x1822
+#endif

Please move it to the .c file where it is actually used.

Extra:

grep -E 'void\ \*' drivers/net/ethernet/huawei/hinic/* makes me nervous.

At some point one function will be fed with a wrong pointer and the compiler won't notice it.

For instance hinic_sq_read_wqe is only called with &skb. There's no reason to declare it using a 'void **' argument.

Signature · 1 line
Ueimor
#3 lore raw

Re: [PATCH V2 net-next 01/21] net-next/hinic: Initialize hw interface

Hi Francois,

ERR_PTR / IS ERR - we will change it

err_xyz labels - we will change it according to other companies style.

hinic_free_hwdev - It is there to mark us changes for VF code. We will remove it, it can't be failed.

hinic_remove - If insmod failed and someone calls rmmod, we will get a crash because the resource are already free. Therefore we test if the device exists, please tell me if you meant to something different

pci_id_tbl - will be moved to the .c file.

void* - usually void * is something to avoid.

The priv data is in type void * because the
caller can use any struct that it wants, like the priv data in Linux (netdev, irq, tasklet, work..) -

we can change it but if we will pass different struct
in the future, we will have to change the prototype of the functions.

According to the other void *:
The wq struct is used for cmdq, sq and rq. Therefore the wqe is in type void *. There are 4 operations get_wqe, write_wqe, read_wqe and put_wqe - there is no option that one function will be fed with a wrong pointer because the caller should use what it got in get_wqe function.

When something is used as multiple types, it can be used as void * or union. Usually, I would prefer union. But, in this case if we will use union, maybe there is a chance of using the wrong wqe type in the wrong work queue type.
Another option is to use a wrapper for each wq type operations, so only the basic wq ops will use void *.

Then, there will be cmdq, rq, sq operations with the correct wqe type and wq operations that will use void *.

I will be glad to hear your opinion about the preferred style and about hinic_remove issue you mentioned above.

Thanks for your time and review,
Aviad

Quoted 135 lines · Francois Romieu

Aviad Krawczyk <[email protected]> :
[...]

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +0 -0
new file mode 100644
index 0000000..fbc9de4

[...]

Quoted 9 lines

+/**
+ * hinic_init_hwdev - Initialize the NIC HW
+ * @hwdev: the NIC HW device that is returned from the initialization
+ * @pdev: the NIC pci device
+ *
+ * Return 0 - Success, negative - Failure
+ *
+ * Initialize the NIC HW device and return a pointer to it in the first arg
+ **/

Return a pointer and use ERR_PTR / IS_ERR ?

Quoted 16 lines
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +16 -0
+int hinic_init_hwdev(struct hinic_hwdev **hwdev, struct pci_dev *pdev)
+{
+	struct hinic_pfhwdev *pfhwdev;
+	struct hinic_hwif *hwif;
+	int err;
+
+	hwif = devm_kzalloc(&pdev->dev, sizeof(*hwif), GFP_KERNEL);
+	if (!hwif)
+		return -ENOMEM;
+
+	err = hinic_init_hwif(hwif, pdev);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to init HW interface\n");
+		return err;
+	}
+

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c line 134

Quoted 10 lines
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +10 -0
+	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
+		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
+		err = -EFAULT;
+		goto func_type_err;
+	}
+
+	pfhwdev = devm_kzalloc(&pdev->dev, sizeof(*pfhwdev), GFP_KERNEL);
+	if (!pfhwdev) {
+		err = -ENOMEM;
+		goto pfhwdev_alloc_err;

Intel, Mellanox, Broadcom, Amazon and friends use "err_xyz" labels.

Please consider using the same style.

[...]

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c line 177

Quoted 10 lines
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c new file +10 -0
+void hinic_free_hwdev(struct hinic_hwdev *hwdev)
+{
+	struct hinic_hwif *hwif = hwdev->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	struct hinic_pfhwdev *pfhwdev;
+
+	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
+		dev_err(&pdev->dev, "unsupported PCI Function type\n");
+		return;
+	}

If it succeeded in hinic_init_hwdev, how could it fail here ?

If it failed in hinic_init_hwdev, hinic_free_hwdev should not even be called.

-> remove ?

[...]

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c new file +0 -0
new file mode 100644
index 0000000..c61c769

[...]

drivers/net/ethernet/huawei/hinic/hinic_main.c line 167

Quoted 7 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c new file +7 -0
+static void hinic_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct hinic_dev *nic_dev;
+
+	if (!netdev)
+		return;

Your driver is flawed if this test can ever succeed.

[...]

drivers/net/ethernet/huawei/hinic/hinic_main.c line 206

Quoted 9 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c new file +9 -0
+static int __init hinic_init(void)
+{
+	return pci_register_driver(&hinic_driver);
+}
+
+static void __exit hinic_exit(void)
+{
+	pci_unregister_driver(&hinic_driver);
+}

Use module_pci_driver(hinic_driver).

Remove hinic_init() and hinic_exit().

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h new file +0 -0
new file mode 100644
index 0000000..1d92617

[...]

drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h line 21

Quoted 6 lines
drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h new file +6 -0
+#ifndef HINIC_PCI_ID_TBL_H
+#define HINIC_PCI_ID_TBL_H
+
+#ifndef PCI_VENDOR_ID_HUAWEI
+#define PCI_VENDOR_ID_HUAWEI            0x19e5
+#endif

Useless: it duplicates include/linux/pci_ids.h

drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h line 25

Quoted 4 lines
drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h new file +4 -0
+
+#ifndef PCI_DEVICE_ID_HI1822_PF
+#define PCI_DEVICE_ID_HI1822_PF         0x1822
+#endif

Please move it to the .c file where it is actually used.

Extra:

grep -E 'void\ \*' drivers/net/ethernet/huawei/hinic/* makes me nervous.

At some point one function will be fed with a wrong pointer and the compiler won't notice it.

For instance hinic_sq_read_wqe is only called with &skb. There's no reason to declare it using a 'void **' argument.

#4 lore raw

Re: [PATCH V2 net-next 01/21] net-next/hinic: Initialize hw interface

Aviad Krawczyk <[email protected]> :
[...]

Quoted 3 lines

hinic_remove - If insmod failed and someone calls rmmod, we will get a crash because the resource are already free. Therefore we test if the device exists, please tell me if you meant to something different

The module won't even proceed through the pci_driver remove method if the probe method failed. See drivers/pci/bus.c::pci_bus_add_device and track 'dev->is_added'. You don't need to believe me: try it.

I have no idea where your crash comes from but something does not look quite right.

(use module_pci_driver() to save some boilerplate code btw)

[...]

Quoted 3 lines

The priv data is in type void * because the
caller can use any struct that it wants, like the priv data in Linux (netdev, irq, tasklet, work..) -

I disagree. A driver is a piece of glue between hardware and software. It fills a kernel's contract. It is not supposed to introduce opaque data (even if it's hard to resist).

Quoted 2 lines

we can change it but if we will pass different struct
in the future, we will have to change the prototype of the functions.

It's fine. If I do something wrong - and at some point I will - I'd rather have it detected at compile time. Nobody wants to waste precious hardware lab testing time because of excess void *.

Quoted 9 lines

According to the other void *:
The wq struct is used for cmdq, sq and rq. Therefore the wqe is in type void *. There are 4 operations get_wqe, write_wqe, read_wqe and put_wqe - there is no option that one function will be fed with a wrong pointer because the caller should use what it got in get_wqe function.

When something is used as multiple types, it can be used as void * or union. Usually, I would prefer union. But, in this case if we will use union, maybe there is a chance of using the wrong wqe type in the wrong work queue type.

union * will at least catch being fed a wrong type. void * won't notice.

Let's take a practical example: hinic_sq_get_sges.

void hinic_sq_get_sges(void *wqe, struct hinic_sge *sges, int nr_sges)

                       ^^^^^^^^^
{
        struct hinic_sq_wqe *sq_wqe = (struct hinic_sq_wqe *)wqe;

static void free_all_tx_skbs(struct hinic_txq *txq)

{
        struct hinic_dev *nic_dev = netdev_priv(txq->netdev);
        struct hinic_sq *sq = txq->sq;
        struct hinic_sq_wqe *wqe;
[...]
                hinic_sq_get_sges(wqe, txq->free_sges, nr_sges);

static int free_tx_poll(struct napi_struct *napi, int budget) {
[...]

        struct hinic_sq_wqe *wqe;
[...]
                hinic_sq_get_sges(wqe, txq->free_sges, nr_sges);

Why is it:

void hinic_sq_get_sges(void *wqe, ...

instead of:

void hinic_sq_get_sges(struct hinic_sq_wqe *wqe, ...

Because of a future change ?

Signature · 1 line
Ueimor
#5 lore raw

Re: [PATCH V2 net-next 01/21] net-next/hinic: Initialize hw interface

Hi,

hinic_remove - you are right, it is over safe code. We can remove it without any crash. This case has never happened.

void * - I meant the problem is not in rq or sq, it can be in wq. But you confirmed that it is ok to use union instead of the void* in wq. So, we will use union in wq.c and in rq - rq_wqe and in sq - sq_wqe.

module_pci_driver - is not used in other drivers in the same segments, it is necessary?

Thanks,
Aviad

Quoted 78 lines · Francois Romieu

Aviad Krawczyk <[email protected]> :
[...]

Quoted 3 lines

hinic_remove - If insmod failed and someone calls rmmod, we will get a crash because the resource are already free. Therefore we test if the device exists, please tell me if you meant to something different

The module won't even proceed through the pci_driver remove method if the probe method failed. See drivers/pci/bus.c::pci_bus_add_device and track 'dev->is_added'. You don't need to believe me: try it.

I have no idea where your crash comes from but something does not look quite right.

(use module_pci_driver() to save some boilerplate code btw)

[...]

Quoted 3 lines

The priv data is in type void * because the
caller can use any struct that it wants, like the priv data in Linux (netdev, irq, tasklet, work..) -

I disagree. A driver is a piece of glue between hardware and software. It fills a kernel's contract. It is not supposed to introduce opaque data (even if it's hard to resist).

Quoted 2 lines

we can change it but if we will pass different struct
in the future, we will have to change the prototype of the functions.

It's fine. If I do something wrong - and at some point I will - I'd rather have it detected at compile time. Nobody wants to waste precious hardware lab testing time because of excess void *.

Quoted 9 lines

According to the other void *:
The wq struct is used for cmdq, sq and rq. Therefore the wqe is in type void *. There are 4 operations get_wqe, write_wqe, read_wqe and put_wqe - there is no option that one function will be fed with a wrong pointer because the caller should use what it got in get_wqe function.

When something is used as multiple types, it can be used as void * or union. Usually, I would prefer union. But, in this case if we will use union, maybe there is a chance of using the wrong wqe type in the wrong work queue type.

union * will at least catch being fed a wrong type. void * won't notice.

Let's take a practical example: hinic_sq_get_sges.

void hinic_sq_get_sges(void *wqe, struct hinic_sge *sges, int nr_sges)

                       ^^^^^^^^^
{
        struct hinic_sq_wqe *sq_wqe = (struct hinic_sq_wqe *)wqe;

static void free_all_tx_skbs(struct hinic_txq *txq)

{
        struct hinic_dev *nic_dev = netdev_priv(txq->netdev);
        struct hinic_sq *sq = txq->sq;
        struct hinic_sq_wqe *wqe;
[...]
                hinic_sq_get_sges(wqe, txq->free_sges, nr_sges);

static int free_tx_poll(struct napi_struct *napi, int budget) {
[...]

        struct hinic_sq_wqe *wqe;
[...]
                hinic_sq_get_sges(wqe, txq->free_sges, nr_sges);

Why is it:

void hinic_sq_get_sges(void *wqe, ...

instead of:

void hinic_sq_get_sges(struct hinic_sq_wqe *wqe, ...

Because of a future change ?

#6 lore raw

Re: [PATCH V2 net-next 01/21] net-next/hinic: Initialize hw interface

Aviad Krawczyk <[email protected]> :
[...]

Quoted 2 lines

module_pci_driver - is not used in other drivers in the same segments, it is necessary ?

/me checks... Ok, there seems to be some overenthusiastic copy'paste.

See drivers/net/ethernet/intel/ixgb/ixgb_main.c:
[...]
/**
* ixgb_init_module - Driver Registration Routine
*
* ixgb_init_module is the first routine called when the driver is
* loaded. All it does is register with the PCI subsystem. **/

static int __init
ixgb_init_module(void)

{
	pr_info("%s - version %s\n", ixgb_driver_string, ixgb_driver_version);
	pr_info("%s\n", ixgb_copyright);

	return pci_register_driver(&ixgb_driver);
}

module_init(ixgb_init_module);

/**
* ixgb_exit_module - Driver Exit Cleanup Routine
*
* ixgb_exit_module is called just before the driver is removed
* from memory.
**/

static void __exit
ixgb_exit_module(void)

{
	pci_unregister_driver(&ixgb_driver);
}

module_exit(ixgb_exit_module);

Driver version ought to be fed through ethtool, if ever. Copyright message mildly contributes to a better world. So the whole stuff above could be:

module_pci_driver(ixgb_driver);

Signature · 1 line
Ueimor
#7 lore raw

Re: [PATCH V2 net-next 01/21] net-next/hinic: Initialize hw interface

OK, we will use module_pci_driver although it is not very common in the same segment.

Quoted 47 lines · Francois Romieu

Aviad Krawczyk <[email protected]> :
[...]

Quoted 2 lines

module_pci_driver - is not used in other drivers in the same segments, it is necessary ?

/me checks... Ok, there seems to be some overenthusiastic copy'paste.

See drivers/net/ethernet/intel/ixgb/ixgb_main.c:
[...]
/**
* ixgb_init_module - Driver Registration Routine
*
* ixgb_init_module is the first routine called when the driver is
* loaded. All it does is register with the PCI subsystem. **/

static int __init
ixgb_init_module(void)

{
	pr_info("%s - version %s\n", ixgb_driver_string, ixgb_driver_version);
	pr_info("%s\n", ixgb_copyright);

	return pci_register_driver(&ixgb_driver);
}

module_init(ixgb_init_module);

/**
* ixgb_exit_module - Driver Exit Cleanup Routine
*
* ixgb_exit_module is called just before the driver is removed
* from memory.
**/

static void __exit
ixgb_exit_module(void)

{
	pci_unregister_driver(&ixgb_driver);
}

module_exit(ixgb_exit_module);

Driver version ought to be fed through ethtool, if ever. Copyright message mildly contributes to a better world. So the whole stuff above could be:

module_pci_driver(ixgb_driver);

#8 lore raw

PATCH v2 2/21 net-next/hinic: Initialize hw device components

In reply to Aviad Krawczyk

Initialize hw device by calling the initialization functions of aeqs and management channel.

---
 drivers/net/ethernet/huawei/hinic/Makefile        |   3 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c  | 176 ++++++++++++++++++++--
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h  |  14 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c  | 149 ++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h  | 107 +++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h   |   8 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c |  93 ++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h |  45 ++++++
 8 files changed, 580 insertions(+), 15 deletions(-)
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
drivers/net/ethernet/huawei/hinic/Makefile +2 -1
index 353cee0..d080dfb 100644
@@ -1,3 +1,4 @@
 obj-$(CONFIG_HINIC) += hinic.o
 
-hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_if.o
+hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_eqs.o \
+	   hinic_hw_if.o
\ No newline at end of file
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +163 -13

231 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +13 -1
index 3b57c67..5b4b686 100644
@@ -17,20 +17,32 @@
 #define HINIC_HW_DEV_H
 
 #include <linux/pci.h>
+#include <linux/types.h>
 
 #include "hinic_hw_if.h"
+#include "hinic_hw_eqs.h"
+#include "hinic_hw_mgmt.h"
 
 #define HINIC_MAX_QPS   32
 
+struct hinic_cap {
+	u16     max_qps;
+	u16     num_qps;
+};
+
 struct hinic_hwdev {
 	struct hinic_hwif               *hwif;
 	struct msix_entry               *msix_entries;
+
+	struct hinic_aeqs               aeqs;
+
+	struct hinic_cap                nic_cap;
 };
 
 struct hinic_pfhwdev {
 	struct hinic_hwdev              hwdev;
 
-	/* PF Extended components should be here */
+	struct hinic_pf_to_mgmt         pf_to_mgmt;
 };
 
 int hinic_init_hwdev(struct hinic_hwdev **hwdev, struct pci_dev *pdev);
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c new file +149 -0

149 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h new file +107 -0

107 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +8 -0
index 319da92..68e4bb9 100644
@@ -119,6 +119,14 @@ enum hinic_func_type {
 	HINIC_PPF       = 2,
 };
 
+enum hinic_mod_type {
+	HINIC_MOD_COMM  = 0,    /* HW communication module */
+	HINIC_MOD_L2NIC = 1,    /* L2NIC module */
+	HINIC_MOD_CFGM  = 7,    /* Configuration module */
+
+	HINIC_MOD_MAX   = 15
+};
+
 struct hinic_func_attr {
 	u16                     func_global_idx;
 	u8                      pf_idx;
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c new file +93 -0

93 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h new file +45 -0

45 lines not on this page · raw message

Signature · 1 line
1.9.1
#9 lore raw

PATCH v2 3/21 net-next/hinic: Initialize api cmd resources

In reply to Aviad Krawczyk

Initialize api cmd resources as part of management initialization.

---
 drivers/net/ethernet/huawei/hinic/Makefile         |   4 +-
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c   | 445 +++++++++++++++++++++
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h   | 102 +++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c  |  10 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h  |   3 +
 5 files changed, 562 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h
drivers/net/ethernet/huawei/hinic/Makefile +2 -2
index d080dfb..88223d0 100644
@@ -1,4 +1,4 @@
 obj-$(CONFIG_HINIC) += hinic.o
 
-hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_eqs.o \
-	   hinic_hw_if.o
\ No newline at end of file
+hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \
+	   hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c new file +445 -0

445 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h new file +102 -0

102 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c +10 -0
index 95edbc8..545ef3a 100644
@@ -19,6 +19,7 @@
 
 #include "hinic_hw_if.h"
 #include "hinic_hw_eqs.h"
+#include "hinic_hw_api_cmd.h"
 #include "hinic_hw_mgmt.h"
 #include "hinic_hw_dev.h"
 
@@ -70,9 +71,17 @@ int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
 {
 	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
 	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
+	struct pci_dev *pdev = hwif->pdev;
+	int err;
 
 	pf_to_mgmt->hwif = hwif;
 
+	err = hinic_api_cmd_init(hwif, pf_to_mgmt->cmd_chain);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
+		return err;
+	}
+
 	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,
 				 pf_to_mgmt,
 				 mgmt_msg_aeqe_handler);
@@ -90,4 +99,5 @@ void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
 	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
 
 	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
+	hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
 }
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h +3 -0
index b4b34b7..dff321c 100644
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 
 #include "hinic_hw_if.h"
+#include "hinic_hw_api_cmd.h"
 
 enum hinic_mgmt_msg_type {
 	HINIC_MGMT_MSG_SYNC = 1,
@@ -30,6 +31,8 @@ enum hinic_cfg_cmd {
 
 struct hinic_pf_to_mgmt {
 	struct hinic_hwif               *hwif;
+
+	struct hinic_api_cmd_chain      *cmd_chain[HINIC_API_CMD_MAX];
 };
 
 int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
Signature · 1 line
1.9.1
#10 lore raw

PATCH v2 4/21 net-next/hinic: Initialize api cmd hw

In reply to Aviad Krawczyk

Update the hardware about api cmd resources and initialize it.

---
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c   | 173 ++++++++++++++++++++-
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h   |  38 +++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h   |  25 +++
 3 files changed, 235 insertions(+), 1 deletion(-)
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +172 -1
index 352397c..c07b02c 100644
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
@@ -20,8 +21,12 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
 #include <asm/byteorder.h>
 
+#include "hinic_hw_csr.h"
 #include "hinic_hw_if.h"
 #include "hinic_hw_api_cmd.h"
 
@@ -34,8 +39,157 @@
 		(((cell_size) >= API_CMD_CELL_SIZE_MIN) ? \
 		 (1 << (fls(cell_size - 1))) : API_CMD_CELL_SIZE_MIN)
 
+#define API_CMD_CELL_SIZE_VAL(size)             \
+		ilog2((size) >> API_CMD_CELL_SIZE_SHIFT)
+
 #define API_CMD_BUF_SIZE                        2048
 
+#define API_CMD_TIMEOUT                 1000
+
+enum api_cmd_xor_chk_level {
+	XOR_CHK_DIS = 0,
+
+	XOR_CHK_ALL = 3,
+};
+
+/**
+ * api_cmd_hw_restart - restart the chain in the HW
+ * @chain: the API CMD specific chain to restart
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static int api_cmd_hw_restart(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	unsigned long end;
+	u32 reg_addr, val;
+	int err = -ETIMEDOUT;
+
+	/* Read Modify Write */
+	reg_addr = HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(chain->chain_type);
+	val = hinic_hwif_read_reg(hwif, reg_addr);
+
+	val = HINIC_API_CMD_CHAIN_REQ_CLEAR(val, RESTART);
+	val |= HINIC_API_CMD_CHAIN_REQ_SET(1, RESTART);
+
+	hinic_hwif_write_reg(hwif, reg_addr, val);
+
+	end = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT);
+	do {
+		val = hinic_hwif_read_reg(hwif, reg_addr);
+
+		if (!HINIC_API_CMD_CHAIN_REQ_GET(val, RESTART)) {
+			err = 0;
+			break;
+		}
+
+		msleep(20);
+	} while (time_before(jiffies, end));
+
+	return err;
+}
+
+/**
+ * api_cmd_ctrl_init - set the control register of a chain
+ * @chain: the API CMD specific chain to set control register for
+ **/
+static void api_cmd_ctrl_init(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	u32 reg_addr, ctrl;
+	u16 cell_size;
+
+	/* Read Modify Write */
+	reg_addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);
+
+	cell_size = API_CMD_CELL_SIZE_VAL(chain->cell_size);
+
+	ctrl = hinic_hwif_read_reg(hwif, reg_addr);
+
+	ctrl =  HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_WB_STAT) &
+		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR)   &
+		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN)   &
+		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) &
+		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);
+
+	ctrl |= HINIC_API_CMD_CHAIN_CTRL_SET(1, XOR_ERR) |
+		HINIC_API_CMD_CHAIN_CTRL_SET(XOR_CHK_ALL, XOR_CHK_EN) |
+		HINIC_API_CMD_CHAIN_CTRL_SET(cell_size, CELL_SIZE);
+
+	hinic_hwif_write_reg(hwif, reg_addr, ctrl);
+}
+
+/**
+ * api_cmd_set_status_addr - set the status address of a chain in the HW
+ * @chain: the API CMD specific chain to set in HW status address for
+ **/
+static void api_cmd_set_status_addr(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	u32 addr, val;
+
+	addr = HINIC_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type);
+	val = upper_32_bits(chain->wb_status_paddr);
+	hinic_hwif_write_reg(hwif, addr, val);
+
+	addr = HINIC_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type);
+	val = lower_32_bits(chain->wb_status_paddr);
+	hinic_hwif_write_reg(hwif, addr, val);
+}
+
+/**
+ * api_cmd_set_num_cells - set the number cells of a chain in the HW
+ * @chain: the API CMD specific chain to set in HW the number of cells for
+ **/
+static void api_cmd_set_num_cells(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	u32 addr, val;
+
+	addr = HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type);
+	val  = chain->num_cells;
+	hinic_hwif_write_reg(hwif, addr, val);
+}
+
+/**
+ * api_cmd_head_init - set the head of a chain in the HW
+ * @chain: the API CMD specific chain to set in HW the head for
+ **/
+static void api_cmd_head_init(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	u32 addr, val;
+
+	addr = HINIC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(chain->chain_type);
+	val = upper_32_bits(chain->head_cell_paddr);
+	hinic_hwif_write_reg(hwif, addr, val);
+
+	addr = HINIC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(chain->chain_type);
+	val = lower_32_bits(chain->head_cell_paddr);
+	hinic_hwif_write_reg(hwif, addr, val);
+}
+
+/**
+ * api_cmd_chain_hw_clean - clean the HW
+ * @chain: the API CMD specific chain
+ **/
+static void api_cmd_chain_hw_clean(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	u32 addr, ctrl;
+
+	addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);
+
+	ctrl = hinic_hwif_read_reg(hwif, addr);
+	ctrl = HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_WB_STAT) &
+		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR)   &
+		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN)   &
+		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) &
+		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);
+
+	hinic_hwif_write_reg(hwif, addr, ctrl);
+}
+
 /**
  * api_cmd_chain_hw_init - initialize the chain in the HW
  * @chain: the API CMD specific chain to initialize in HW
@@ -44,7 +198,23 @@
  **/
 static int api_cmd_chain_hw_init(struct hinic_api_cmd_chain *chain)
 {
-	/* should be implemented */
+	struct hinic_hwif *hwif = chain->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	int err;
+
+	api_cmd_chain_hw_clean(chain);
+
+	api_cmd_set_status_addr(chain);
+
+	err = api_cmd_hw_restart(chain);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to restart API CMD HW\n");
+		return err;
+	}
+
+	api_cmd_ctrl_init(chain);
+	api_cmd_set_num_cells(chain);
+	api_cmd_head_init(chain);
 	return 0;
 }
 
@@ -374,6 +544,7 @@ static int api_cmd_create_chain(struct hinic_api_cmd_chain **cmd_chain,
  **/
 static void api_cmd_destroy_chain(struct hinic_api_cmd_chain *chain)
 {
+	api_cmd_chain_hw_clean(chain);
 	api_cmd_destroy_cells(chain, chain->num_cells);
 	api_chain_free(chain);
 }
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h +38 -0
index a12df84..21c8c12 100644
@@ -20,6 +20,44 @@
 
 #include "hinic_hw_if.h"
 
+#define HINIC_API_CMD_CHAIN_REQ_RESTART_SHIFT                   1
+
+#define HINIC_API_CMD_CHAIN_REQ_RESTART_MASK                    0x1
+
+#define HINIC_API_CMD_CHAIN_REQ_SET(val, member)                \
+	(((u32)(val) & HINIC_API_CMD_CHAIN_REQ_##member##_MASK) << \
+	 HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT)
+
+#define HINIC_API_CMD_CHAIN_REQ_GET(val, member)                \
+	(((val) >> HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT) &  \
+	 HINIC_API_CMD_CHAIN_REQ_##member##_MASK)
+
+#define HINIC_API_CMD_CHAIN_REQ_CLEAR(val, member)              \
+	((val) & (~(HINIC_API_CMD_CHAIN_REQ_##member##_MASK     \
+	 << HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT)))
+
+#define HINIC_API_CMD_CHAIN_CTRL_RESTART_WB_STAT_SHIFT          1
+#define HINIC_API_CMD_CHAIN_CTRL_XOR_ERR_SHIFT                  2
+#define HINIC_API_CMD_CHAIN_CTRL_AEQE_EN_SHIFT                  4
+#define HINIC_API_CMD_CHAIN_CTRL_AEQ_ID_SHIFT                   8
+#define HINIC_API_CMD_CHAIN_CTRL_XOR_CHK_EN_SHIFT               28
+#define HINIC_API_CMD_CHAIN_CTRL_CELL_SIZE_SHIFT                30
+
+#define HINIC_API_CMD_CHAIN_CTRL_RESTART_WB_STAT_MASK           0x1
+#define HINIC_API_CMD_CHAIN_CTRL_XOR_ERR_MASK                   0x1
+#define HINIC_API_CMD_CHAIN_CTRL_AEQE_EN_MASK                   0x1
+#define HINIC_API_CMD_CHAIN_CTRL_AEQ_ID_MASK                    0x3
+#define HINIC_API_CMD_CHAIN_CTRL_XOR_CHK_EN_MASK                0x3
+#define HINIC_API_CMD_CHAIN_CTRL_CELL_SIZE_MASK                 0x3
+
+#define HINIC_API_CMD_CHAIN_CTRL_SET(val, member)               \
+	(((u32)(val) & HINIC_API_CMD_CHAIN_CTRL_##member##_MASK) << \
+	 HINIC_API_CMD_CHAIN_CTRL_##member##_SHIFT)
+
+#define HINIC_API_CMD_CHAIN_CTRL_CLEAR(val, member)             \
+	((val) & (~(HINIC_API_CMD_CHAIN_CTRL_##member##_MASK    \
+	 << HINIC_API_CMD_CHAIN_CTRL_##member##_SHIFT)))
+
 enum hinic_api_cmd_chain_type {
 	HINIC_API_CMD_WRITE_TO_MGMT_CPU = 2,
 
drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +25 -0
index c3440a9..0c100ee 100644
@@ -33,4 +33,29 @@
 #define HINIC_CSR_PPF_ELECTION_ADDR(idx)                \
 	(HINIC_ELECTION_BASE +  (idx) * HINIC_PPF_ELECTION_STRIDE)
 
+/* API CMD registers */
+#define HINIC_CSR_API_CMD_BASE                          0xF000
+
+#define HINIC_CSR_API_CMD_STRIDE                        0x100
+
+#define HINIC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(idx)       \
+	(HINIC_CSR_API_CMD_BASE + 0x0 + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
+#define HINIC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(idx)       \
+	(HINIC_CSR_API_CMD_BASE + 0x4 + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
+#define HINIC_CSR_API_CMD_STATUS_HI_ADDR(idx)           \
+	(HINIC_CSR_API_CMD_BASE + 0x8 + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
+#define HINIC_CSR_API_CMD_STATUS_LO_ADDR(idx)           \
+	(HINIC_CSR_API_CMD_BASE + 0xC + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
+#define HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(idx)     \
+	(HINIC_CSR_API_CMD_BASE + 0x10 + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
+#define HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(idx)          \
+	(HINIC_CSR_API_CMD_BASE + 0x14 + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
+#define HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(idx)           \
+	(HINIC_CSR_API_CMD_BASE + 0x20 + (idx) * HINIC_CSR_API_CMD_STRIDE)
 #endif
Signature · 1 line
1.9.1
#11 lore raw

PATCH v2 5/21 net-next/hinic: Add management messages

In reply to Aviad Krawczyk

Add the management messages for sending to api cmd and the asynchronous event handler for the completion of the messages.

---
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c   |  35 ++
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h   |   3 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h    |   5 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c  | 441 ++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h  |  59 +++
 5 files changed, 540 insertions(+), 3 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +35 -0
index c07b02c..eacb33b 100644
@@ -53,6 +53,41 @@ enum api_cmd_xor_chk_level {
 };
 
 /**
+ * api_cmd - API CMD command
+ * @chain: chain for the command
+ * @dest: destination node on the card that will receive the command
+ * @cmd: command data
+ * @size: the command size
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static int api_cmd(struct hinic_api_cmd_chain *chain,
+		   enum hinic_node_id dest, void *cmd, u16 cmd_size)
+{
+	/* should be implemented */
+	return -EINVAL;
+}
+
+/**
+ * hinic_api_cmd_write - Write API CMD command
+ * @chain: chain for write command
+ * @dest: destination node on the card that will receive the command
+ * @cmd: command data
+ * @size: the command size
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain,
+			enum hinic_node_id dest, void *cmd, u16 size)
+{
+	/* Verify the chain type */
+	if (chain->chain_type == HINIC_API_CMD_WRITE_TO_MGMT_CPU)
+		return api_cmd(chain, dest, cmd, size);
+
+	return -EINVAL;
+}
+
+/**
  * api_cmd_hw_restart - restart the chain in the HW
  * @chain: the API CMD specific chain to restart
  *
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h +3 -0
index 21c8c12..c2c8b5f 100644
@@ -132,6 +132,9 @@ struct hinic_api_cmd_chain {
 	struct hinic_api_cmd_cell       *curr_node;
 };
 
+int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain,
+			enum hinic_node_id dest, void *cmd, u16 size);
+
 int hinic_api_cmd_init(struct hinic_hwif *hwif,
 		       struct hinic_api_cmd_chain **chain);
 
drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +5 -0
index 68e4bb9..4cfe325 100644
@@ -93,6 +93,7 @@
 #define HINIC_HWIF_NUM_IRQS(hwif)       ((hwif)->attr.num_irqs)
 #define HINIC_HWIF_GLOB_IDX(hwif)       ((hwif)->attr.func_global_idx)
 #define HINIC_HWIF_PCI_INTF(hwif)       ((hwif)->attr.pci_intf_idx)
+#define HINIC_HWIF_PF_IDX(hwif)         ((hwif)->attr.pf_idx)
 
 #define HINIC_FUNC_TYPE(hwif)           ((hwif)->attr.func_type)
 #define HINIC_IS_PF(hwif)               (HINIC_FUNC_TYPE(hwif) == HINIC_PF)
@@ -127,6 +128,10 @@ enum hinic_mod_type {
 	HINIC_MOD_MAX   = 15
 };
 
+enum hinic_node_id {
+	HINIC_NODE_ID_MGMT = 21,
+};
+
 struct hinic_func_attr {
 	u16                     func_global_idx;
 	u8                      pf_idx;
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c +438 -3

474 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h +59 -0

78 lines not on this page · raw message

Signature · 1 line
1.9.1
#12 lore raw

PATCH v2 6/21 net-next/hinic: Add api cmd commands

In reply to Aviad Krawczyk

Add the api cmd commands for sending management messages to the nic.

---
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c   | 331 ++++++++++++++++++++-
 .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h   |  65 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h   |   7 +
 3 files changed, 401 insertions(+), 2 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +329 -2
index eacb33b..5627191 100644
@@ -24,7 +24,9 @@
 #include <linux/jiffies.h>
 #include <linux/delay.h>
 #include <linux/log2.h>
+#include <linux/semaphore.h>
 #include <asm/byteorder.h>
+#include <asm/barrier.h>
 
 #include "hinic_hw_csr.h"
 #include "hinic_hw_if.h"
@@ -44,14 +46,314 @@
 
 #define API_CMD_BUF_SIZE                        2048
 
+/* Sizes of the members in hinic_api_cmd_cell */
+#define API_CMD_CELL_DESC_SIZE          8
+#define API_CMD_CELL_DATA_ADDR_SIZE     8
+
+#define API_CMD_CELL_ALIGNMENT          8
+
 #define API_CMD_TIMEOUT                 1000
 
+#define MASKED_IDX(chain, idx)          ((idx) & ((chain)->num_cells - 1))
+
+#define SIZE_8BYTES(size)               (ALIGN((size), 8) >> 3)
+#define SIZE_4BYTES(size)               (ALIGN((size), 4) >> 2)
+
+#define RD_DMA_ATTR_DEFAULT             0
+#define WR_DMA_ATTR_DEFAULT             0
+
+enum api_cmd_data_format {
+	SGE_DATA = 1,           /* cell data is passed by hw address */
+};
+
+enum api_cmd_type {
+	API_CMD_WRITE = 0,
+};
+
+enum api_cmd_bypass {
+	NO_BYPASS       = 0,
+	BYPASS          = 1,
+};
+
 enum api_cmd_xor_chk_level {
 	XOR_CHK_DIS = 0,
 
 	XOR_CHK_ALL = 3,
 };
 
+static u8 xor_chksum_set(void *data)
+{
+	int idx;
+	u8 *val, checksum = 0;
+
+	val = data;
+
+	for (idx = 0; idx < 7; idx++)
+		checksum ^= val[idx];
+
+	return checksum;
+}
+
+static void set_prod_idx(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	enum hinic_api_cmd_chain_type chain_type = chain->chain_type;
+	u32 hw_prod_idx_addr = HINIC_CSR_API_CMD_CHAIN_PI_ADDR(chain_type);
+	u32 prod_idx;
+
+	prod_idx = hinic_hwif_read_reg(hwif, hw_prod_idx_addr);
+
+	prod_idx = HINIC_API_CMD_PI_CLEAR(prod_idx, IDX);
+
+	prod_idx |= HINIC_API_CMD_PI_SET(chain->prod_idx, IDX);
+
+	hinic_hwif_write_reg(hwif, hw_prod_idx_addr, prod_idx);
+}
+
+static u32 get_hw_cons_idx(struct hinic_api_cmd_chain *chain)
+{
+	u32 addr, val;
+
+	addr = HINIC_CSR_API_CMD_STATUS_ADDR(chain->chain_type);
+	val  = hinic_hwif_read_reg(chain->hwif, addr);
+
+	return HINIC_API_CMD_STATUS_GET(val, CONS_IDX);
+}
+
+/**
+ * chain_busy - check if the chain is still processing last requests
+ * @chain: chain to check
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static int chain_busy(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	u32 prod_idx;
+
+	switch (chain->chain_type) {
+	case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
+		chain->cons_idx = get_hw_cons_idx(chain);
+		prod_idx = chain->prod_idx;
+
+		/* check for a space for a new command */
+		if (chain->cons_idx == MASKED_IDX(chain, prod_idx + 1)) {
+			dev_err(&pdev->dev, "API CMD chain %d is busy\n",
+				chain->chain_type);
+			return -EBUSY;
+		}
+		break;
+
+	default:
+		dev_err(&pdev->dev, "Unknown API CMD Chain type\n");
+		break;
+	}
+
+	return 0;
+}
+
+/**
+ * get_cell_data_size - get the data size of a specific cell type
+ * @type: chain type
+ *
+ * Return the data(Desc + Address) size in the cell
+ **/
+static u8 get_cell_data_size(enum hinic_api_cmd_chain_type type)
+{
+	u8 cell_data_size = 0;
+
+	switch (type) {
+	case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
+		cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE +
+				       API_CMD_CELL_DATA_ADDR_SIZE,
+				       API_CMD_CELL_ALIGNMENT);
+		break;
+	default:
+		break;
+	}
+
+	return cell_data_size;
+}
+
+/**
+ * prepare_cell_ctrl - prepare the ctrl of the cell for the command
+ * @cell_ctrl: the control of the cell to set the control value into it
+ * @data_size: the size of the data in the cell
+ **/
+static void prepare_cell_ctrl(u64 *cell_ctrl, u16 data_size)
+{
+	u64 ctrl;
+	u8 chksum;
+
+	ctrl =  HINIC_API_CMD_CELL_CTRL_SET(SIZE_8BYTES(data_size), DATA_SZ) |
+		HINIC_API_CMD_CELL_CTRL_SET(RD_DMA_ATTR_DEFAULT, RD_DMA_ATTR) |
+		HINIC_API_CMD_CELL_CTRL_SET(WR_DMA_ATTR_DEFAULT, WR_DMA_ATTR);
+
+	chksum = xor_chksum_set(&ctrl);
+
+	ctrl |= HINIC_API_CMD_CELL_CTRL_SET(chksum, XOR_CHKSUM);
+
+	/* The data in the HW should be in Big Endian Format */
+	*cell_ctrl = cpu_to_be64(ctrl);
+}
+
+/**
+ * prepare_api_cmd - prepare API CMD command
+ * @chain: chain for the command
+ * @cell: the cell of the command
+ * @dest: destination node on the card that will receive the command
+ * @cmd: command data
+ * @cmd_size: the command size
+ **/
+static void prepare_api_cmd(struct hinic_api_cmd_chain *chain,
+			    struct hinic_api_cmd_cell *cell,
+			    enum hinic_node_id dest,
+			    void *cmd, u16 cmd_size)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	struct hinic_api_cmd_cell_ctxt *cell_ctxt;
+
+	cell_ctxt = &chain->cell_ctxt[chain->prod_idx];
+
+	switch (chain->chain_type) {
+	case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
+		cell->desc = HINIC_API_CMD_DESC_SET(SGE_DATA, API_TYPE) |
+			     HINIC_API_CMD_DESC_SET(API_CMD_WRITE, RD_WR) |
+			     HINIC_API_CMD_DESC_SET(NO_BYPASS, MGMT_BYPASS);
+		break;
+
+	default:
+		dev_err(&pdev->dev, "unknown Chain type\n");
+		return;
+	}
+
+	cell->desc |= HINIC_API_CMD_DESC_SET(dest, DEST)        |
+		      HINIC_API_CMD_DESC_SET(SIZE_4BYTES(cmd_size), SIZE);
+
+	cell->desc |= HINIC_API_CMD_DESC_SET(xor_chksum_set(&cell->desc),
+					     XOR_CHKSUM);
+
+	/* The data in the HW should be in Big Endian Format */
+	cell->desc = cpu_to_be64(cell->desc);
+
+	memcpy(cell_ctxt->api_cmd_vaddr, cmd, cmd_size);
+}
+
+/**
+ * prepare_cell - prepare cell ctrl and cmd in the current cell
+ * @chain: chain for the command
+ * @dest: destination node on the card that will receive the command
+ * @cmd: command data
+ * @cmd_size: the command size
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static void prepare_cell(struct hinic_api_cmd_chain *chain,
+			 enum  hinic_node_id dest,
+			 void *cmd, u16 cmd_size)
+{
+	struct hinic_api_cmd_cell *curr_node = chain->curr_node;
+	u16 data_size = get_cell_data_size(chain->chain_type);
+
+	prepare_cell_ctrl(&curr_node->ctrl, data_size);
+	prepare_api_cmd(chain, curr_node, dest, cmd, cmd_size);
+}
+
+static inline void cmd_chain_prod_idx_inc(struct hinic_api_cmd_chain *chain)
+{
+	chain->prod_idx = MASKED_IDX(chain, chain->prod_idx + 1);
+}
+
+/**
+ * api_cmd_status_update - update the status in the chain struct
+ * @chain: chain to update
+ **/
+static void api_cmd_status_update(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	struct hinic_api_cmd_status *wb_status;
+	enum hinic_api_cmd_chain_type chain_type;
+	u64     status_header;
+	u32     status;
+
+	wb_status = chain->wb_status;
+	status_header = be64_to_cpu(wb_status->header);
+
+	status = be32_to_cpu(wb_status->status);
+	if (HINIC_API_CMD_STATUS_GET(status, CHKSUM_ERR)) {
+		dev_err(&pdev->dev, "API CMD status: Xor check error\n");
+		return;
+	}
+
+	chain_type = HINIC_API_CMD_STATUS_HEADER_GET(status_header, CHAIN_ID);
+	if (chain_type >= HINIC_API_CMD_MAX) {
+		dev_err(&pdev->dev, "unknown API CMD Chain %d\n", chain_type);
+		return;
+	}
+
+	chain->cons_idx = HINIC_API_CMD_STATUS_GET(status, CONS_IDX);
+}
+
+/**
+ * wait_for_status_poll - wait for write to api cmd command to complete
+ * @chain: the chain of the command
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static int wait_for_status_poll(struct hinic_api_cmd_chain *chain)
+{
+	unsigned long end;
+	int err = -ETIMEDOUT;
+
+	end = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT);
+	do {
+		api_cmd_status_update(chain);
+
+		/* wait for CI to be updated - sign for completion */
+		if (chain->cons_idx == chain->prod_idx) {
+			err = 0;
+			break;
+		}
+
+		msleep(20);
+	} while (time_before(jiffies, end));
+
+	return err;
+}
+
+/**
+ * wait_for_api_cmd_completion - wait for command to complete
+ * @chain: chain for the command
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static int wait_for_api_cmd_completion(struct hinic_api_cmd_chain *chain)
+{
+	struct hinic_hwif *hwif = chain->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	int err;
+
+	switch (chain->chain_type) {
+	case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
+		err = wait_for_status_poll(chain);
+		if (err) {
+			dev_err(&pdev->dev, "API CMD Poll status timeout\n");
+			break;
+		}
+		break;
+
+	default:
+		dev_err(&pdev->dev, "unknown API CMD Chain type\n");
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
 /**
  * api_cmd - API CMD command
  * @chain: chain for the command
@@ -64,8 +366,31 @@ enum api_cmd_xor_chk_level {
 static int api_cmd(struct hinic_api_cmd_chain *chain,
 		   enum hinic_node_id dest, void *cmd, u16 cmd_size)
 {
-	/* should be implemented */
-	return -EINVAL;
+	struct hinic_api_cmd_cell_ctxt *ctxt;
+	int err;
+
+	down(&chain->sem);
+	if (chain_busy(chain)) {
+		up(&chain->sem);
+		return -EBUSY;
+	}
+
+	prepare_cell(chain, dest, cmd, cmd_size);
+	cmd_chain_prod_idx_inc(chain);
+
+	wmb();  /* inc pi before issue the command */
+
+	set_prod_idx(chain);    /* issue the command */
+
+	ctxt = &chain->cell_ctxt[chain->prod_idx];
+
+	chain->curr_node = ctxt->cell_vaddr;
+
+	err = wait_for_api_cmd_completion(chain);
+
+	up(&chain->sem);
+
+	return err;
 }
 
 /**
@@ -490,6 +815,8 @@ static int api_chain_init(struct hinic_api_cmd_chain *chain,
 	chain->prod_idx  = 0;
 	chain->cons_idx  = 0;
 
+	sema_init(&chain->sem, 1);
+
 	cell_ctxt_size = chain->num_cells * sizeof(*chain->cell_ctxt);
 	chain->cell_ctxt = devm_kzalloc(&pdev->dev, cell_ctxt_size, GFP_KERNEL);
 	if (!chain->cell_ctxt)
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h +65 -0

86 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +7 -0
index 0c100ee..ebbf054 100644
@@ -56,6 +56,13 @@
 #define HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(idx)          \
 	(HINIC_CSR_API_CMD_BASE + 0x14 + (idx) * HINIC_CSR_API_CMD_STRIDE)
 
+#define HINIC_CSR_API_CMD_CHAIN_PI_ADDR(idx)            \
+	(HINIC_CSR_API_CMD_BASE + 0x1C + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
 #define HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(idx)           \
 	(HINIC_CSR_API_CMD_BASE + 0x20 + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
+#define HINIC_CSR_API_CMD_STATUS_ADDR(idx)              \
+	(HINIC_CSR_API_CMD_BASE + 0x30 + (idx) * HINIC_CSR_API_CMD_STRIDE)
+
 #endif
Signature · 1 line
1.9.1
#13 lore raw

PATCH v2 7/21 net-next/hinic: Add aeqs

In reply to Aviad Krawczyk

Handle aeq elements that are accumulated on the aeq by calling the registered handler for the specific event.

---
 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h |  49 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 454 ++++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h |  81 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c  |  92 +++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h  |  58 ++-
 5 files changed, 726 insertions(+), 8 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +49 -0
index ebbf054..52eb89c 100644
@@ -65,4 +65,53 @@
 #define HINIC_CSR_API_CMD_STATUS_ADDR(idx)              \
 	(HINIC_CSR_API_CMD_BASE + 0x30 + (idx) * HINIC_CSR_API_CMD_STRIDE)
 
+/* MSI-X registers */
+#define HINIC_CSR_MSIX_CTRL_BASE                        0x2000
+#define HINIC_CSR_MSIX_CNT_BASE                         0x2004
+
+#define HINIC_CSR_MSIX_STRIDE                           0x8
+
+#define HINIC_CSR_MSIX_CTRL_ADDR(idx)                   \
+	(HINIC_CSR_MSIX_CTRL_BASE + (idx) * HINIC_CSR_MSIX_STRIDE)
+
+#define HINIC_CSR_MSIX_CNT_ADDR(idx)                    \
+	(HINIC_CSR_MSIX_CNT_BASE + (idx) * HINIC_CSR_MSIX_STRIDE)
+
+/* EQ registers */
+#define HINIC_AEQ_MTT_OFF_BASE_ADDR                     0x200
+
+#define HINIC_EQ_MTT_OFF_STRIDE                         0x40
+
+#define HINIC_CSR_AEQ_MTT_OFF(id)                       \
+	(HINIC_AEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE)
+
+#define HINIC_CSR_EQ_PAGE_OFF_STRIDE                    8
+
+#define HINIC_CSR_AEQ_HI_PHYS_ADDR_REG(q_id, pg_num)    \
+	(HINIC_CSR_AEQ_MTT_OFF(q_id) + \
+	 (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE)
+
+#define HINIC_CSR_AEQ_LO_PHYS_ADDR_REG(q_id, pg_num)    \
+	(HINIC_CSR_AEQ_MTT_OFF(q_id) + \
+	 (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4)
+
+#define HINIC_AEQ_CTRL_0_ADDR_BASE                      0xE00
+#define HINIC_AEQ_CTRL_1_ADDR_BASE                      0xE04
+#define HINIC_AEQ_CONS_IDX_ADDR_BASE                    0xE08
+#define HINIC_AEQ_PROD_IDX_ADDR_BASE                    0xE0C
+
+#define HINIC_EQ_OFF_STRIDE                             0x80
+
+#define HINIC_CSR_AEQ_CTRL_0_ADDR(idx)                  \
+	(HINIC_AEQ_CTRL_0_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
+
+#define HINIC_CSR_AEQ_CTRL_1_ADDR(idx)                  \
+	(HINIC_AEQ_CTRL_1_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
+
+#define HINIC_CSR_AEQ_CONS_IDX_ADDR(idx)                \
+	(HINIC_AEQ_CONS_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
+
+#define HINIC_CSR_AEQ_PROD_IDX_ADDR(idx)                \
+	(HINIC_AEQ_PROD_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
+
 #endif
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c +452 -2

490 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h +81 -0

95 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_if.c +92 -0

98 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +52 -6

83 lines not on this page · raw message

Signature · 1 line
1.9.1
#14 lore raw

PATCH v2 8/21 net-next/hinic: Add port management commands

In reply to Aviad Krawczyk

Add the port management commands that are sent as management messages. The port management commands are used for netdev operations.

---
 drivers/net/ethernet/huawei/hinic/Makefile       |   4 +-
 drivers/net/ethernet/huawei/hinic/hinic_dev.h    |   4 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c |  30 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h |  29 +++
 drivers/net/ethernet/huawei/hinic/hinic_main.c   | 201 ++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_port.c   | 241 +++++++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_port.h   |  68 +++++++
 7 files changed, 574 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_port.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_port.h
drivers/net/ethernet/huawei/hinic/Makefile +2 -2
index 88223d0..08951a6 100644
@@ -1,4 +1,4 @@
 obj-$(CONFIG_HINIC) += hinic.o
 
-hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \
-	   hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file
+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
\ No newline at end of file
drivers/net/ethernet/huawei/hinic/hinic_dev.h +4 -0
index f23e8af..dd540b4 100644
@@ -18,6 +18,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/types.h>
+#include <linux/semaphore.h>
 
 #include "hinic_hw_dev.h"
 
@@ -28,6 +29,9 @@ struct hinic_dev {
 	struct hinic_hwdev              *hwdev;
 
 	u32                             msg_enable;
+
+	struct semaphore                mgmt_lock;
+	unsigned long                   *vlan_bitmap;
 };
 
 #endif
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +30 -0
index c61ff10..52d9bb7 100644
@@ -202,6 +202,36 @@ static void disable_msix(struct hinic_hwdev *hwdev)
 }
 
 /**
+ * hinic_port_msg_cmd - send port msg to mgmt
+ * @hwdev: the NIC HW device
+ * @cmd: the port command
+ * @buf_in: input buffer
+ * @in_size: input size
+ * @buf_out: output buffer
+ * @out_size: returned output size
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+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)
+{
+	struct hinic_pfhwdev *pfhwdev;
+	struct hinic_hwif *hwif = hwdev->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+
+	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
+		dev_err(&pdev->dev, "unsupported PCI Function type\n");
+		return -EINVAL;
+	}
+
+	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
+
+	return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, cmd,
+				 buf_in, in_size, buf_out, out_size,
+				 HINIC_MGMT_MSG_SYNC);
+}
+
+/**
  * init_pfhwdev - Initialize the extended components of PF
  * @pfhwdev: the HW device for PF
  *
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +29 -0
index 5b4b686..b3325e7 100644
@@ -30,6 +30,31 @@ struct hinic_cap {
 	u16     num_qps;
 };
 
+enum hinic_port_cmd {
+	HINIC_PORT_CMD_CHANGE_MTU = 2,
+
+	HINIC_PORT_CMD_ADD_VLAN = 3,
+	HINIC_PORT_CMD_DEL_VLAN = 4,
+
+	HINIC_PORT_CMD_SET_MAC = 9,
+	HINIC_PORT_CMD_GET_MAC = 10,
+	HINIC_PORT_CMD_DEL_MAC = 11,
+
+	HINIC_PORT_CMD_SET_RX_MODE = 12,
+
+	HINIC_PORT_CMD_GET_LINK_STATE = 24,
+
+	HINIC_PORT_CMD_SET_PORT_STATE = 41,
+
+	HINIC_PORT_CMD_FWCTXT_INIT = 69,
+
+	HINIC_PORT_CMD_SET_FUNC_STATE = 93,
+
+	HINIC_PORT_CMD_GET_GLOBAL_QPN = 102,
+
+	HINIC_PORT_CMD_GET_CAP = 170,
+};
+
 struct hinic_hwdev {
 	struct hinic_hwif               *hwif;
 	struct msix_entry               *msix_entries;
@@ -45,6 +70,10 @@ struct hinic_pfhwdev {
 	struct hinic_pf_to_mgmt         pf_to_mgmt;
 };
 
+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_init_hwdev(struct hinic_hwdev **hwdev, struct pci_dev *pdev);
 
 void hinic_free_hwdev(struct hinic_hwdev *hwdev);
drivers/net/ethernet/huawei/hinic/hinic_main.c +200 -1

240 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_port.c new file +241 -0

241 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_port.h new file +68 -0

68 lines not on this page · raw message

Signature · 1 line
1.9.1
#15 lore raw

PATCH v2 9/21 net-next/hinic: Add Rx mode and link event handler

In reply to Aviad Krawczyk

Add port management message for setting Rx mode in the card, used for rx_mode netdev operation. The link event handler is used for getting a notification about the link state.

---
 drivers/net/ethernet/huawei/hinic/hinic_dev.h     |  17 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h  |   2 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c  | 120 +++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h  |  63 ++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c   |  17 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h   |  17 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c |  69 +++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h |  28 +++
 drivers/net/ethernet/huawei/hinic/hinic_main.c    | 285 +++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_port.c    | 101 ++++++++
 drivers/net/ethernet/huawei/hinic/hinic_port.h    |  66 +++++
 11 files changed, 767 insertions(+), 18 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_dev.h +17 -0
index dd540b4..91a3356 100644
@@ -19,19 +19,36 @@
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/semaphore.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
 
 #include "hinic_hw_dev.h"
 
 #define HINIC_DRV_NAME          "HiNIC"
 
+enum hinic_flags {
+	HINIC_LINK_UP = BIT(0),
+	HINIC_INTF_UP = BIT(1),
+};
+
+struct hinic_rx_mode_work {
+	struct work_struct      work;
+	u32                     rx_mode;
+};
+
 struct hinic_dev {
 	struct net_device               *netdev;
 	struct hinic_hwdev              *hwdev;
 
 	u32                             msg_enable;
 
+	unsigned int                    flags;
+
 	struct semaphore                mgmt_lock;
 	unsigned long                   *vlan_bitmap;
+
+	struct hinic_rx_mode_work       rx_mode_work;
+	struct workqueue_struct         *workq;
 };
 
 #endif
drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +2 -0
index 52eb89c..1f57301 100644
@@ -20,6 +20,8 @@
 #define HINIC_CSR_FUNC_ATTR0_ADDR                       0x0
 #define HINIC_CSR_FUNC_ATTR1_ADDR                       0x4
 
+#define HINIC_CSR_FUNC_ATTR5_ADDR                       0x14
+
 #define HINIC_DMA_ATTR_BASE                             0xC80
 #define HINIC_ELECTION_BASE                             0x4200
 
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +120 -0

138 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +50 -13

102 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_if.c +17 -0
index c5bc98d..9296758 100644
@@ -118,6 +118,23 @@ int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index)
 }
 
 /**
+ * hinic_set_pf_action - set action on pf channel
+ * @hwif: the HW interface of a pci function device
+ * @action: action on pf channel
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action)
+{
+	u32 attr5 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR);
+
+	attr5 = HINIC_FA5_CLEAR(attr5, PF_ACTION);
+	attr5 |= HINIC_FA5_SET(action, PF_ACTION);
+
+	hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR, attr5);
+}
+
+/**
  * hwif_ready - test if the HW is ready for use
  * @hwif: the HW interface of a pci function device
  *
drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +17 -0
index ccc6e23..88df3c0 100644
@@ -73,6 +73,15 @@
 #define HINIC_FA1_GET(val, member)                              \
 	(((val) >> HINIC_FA1_##member##_SHIFT) & HINIC_FA1_##member##_MASK)
 
+#define HINIC_FA5_PF_ACTION_SHIFT                               0
+#define HINIC_FA5_PF_ACTION_MASK                                0xFFFF
+
+#define HINIC_FA5_SET(val, member)                              \
+	(((u32)(val) & HINIC_FA5_##member##_MASK) << HINIC_FA5_##member##_SHIFT)
+
+#define HINIC_FA5_CLEAR(val, member)                            \
+	((val) & (~(HINIC_FA5_##member##_MASK << HINIC_FA5_##member##_SHIFT)))
+
 #define HINIC_PPF_ELECTION_IDX_SHIFT                            0
 #define HINIC_PPF_ELECTION_IDX_MASK                             0x1F
 
@@ -166,6 +175,12 @@ enum hinic_node_id {
 	HINIC_NODE_ID_MGMT = 21,
 };
 
+enum hinic_pf_action {
+	HINIC_PF_MGMT_INIT = 0x0,
+
+	HINIC_PF_MGMT_ACTIVE = 0x11,
+};
+
 struct hinic_func_attr {
 	u16                     func_global_idx;
 	u8                      pf_idx;
@@ -212,6 +227,8 @@ int hinic_msix_attr_get(struct hinic_hwif *hwif, u16 msix_index,
 
 int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index);
 
+void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action);
+
 int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev);
 
 void hinic_free_hwif(struct hinic_hwif *hwif);
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c +65 -4

90 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h +28 -0
index 7f08ea2..4f678c8 100644
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 #include <linux/semaphore.h>
 #include <linux/completion.h>
+#include <linux/bitops.h>
 
 #include "hinic_hw_if.h"
 #include "hinic_hw_api_cmd.h"
@@ -67,6 +68,11 @@ enum hinic_cfg_cmd {
 	HINIC_CFG_NIC_CAP = 0,
 };
 
+enum hinic_mgmt_cb_state {
+	HINIC_MGMT_CB_ENABLED = BIT(0),
+	HINIC_MGMT_CB_RUNNING = BIT(1),
+};
+
 struct hinic_recv_msg {
 	void                    *msg;
 	void                    *buf_out;
@@ -81,6 +87,15 @@ struct hinic_recv_msg {
 	u16                     msg_id;
 };
 
+struct hinic_mgmt_cb {
+	void    (*cb)(void *handle, u8 cmd,
+		      void *buf_in, u16 in_size,
+		      void *buf_out, u16 *out_size);
+
+	void            *handle;
+	unsigned long   state;
+};
+
 struct hinic_pf_to_mgmt {
 	struct hinic_hwif               *hwif;
 
@@ -92,8 +107,21 @@ struct hinic_pf_to_mgmt {
 	struct hinic_recv_msg           recv_msg_from_mgmt;
 
 	struct hinic_api_cmd_chain      *cmd_chain[HINIC_API_CMD_MAX];
+
+	struct hinic_mgmt_cb            mgmt_cb[HINIC_MOD_MAX];
 };
 
+void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
+				enum hinic_mod_type mod,
+				void *handle,
+				void (*callback)(void *handle,
+						 u8 cmd, void *buf_in,
+						 u16 in_size, void *buf_out,
+						 u16 *out_size));
+
+void hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
+				  enum hinic_mod_type mod);
+
 int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
 		      enum hinic_mod_type mod, u8 cmd,
 		      void *buf_in, u16 in_size, void *buf_out, u16 *out_size,
drivers/net/ethernet/huawei/hinic/hinic_main.c +284 -1

384 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_port.c +101 -0

104 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_port.h +66 -0

85 lines not on this page · raw message

Signature · 1 line
1.9.1
#16 lore raw

PATCH v2 10/21 net-next/hinic: Add logical Txq and Rxq

In reply to Aviad Krawczyk

Create the logical queues of the nic.

---
 drivers/net/ethernet/huawei/hinic/Makefile       |   5 +-
 drivers/net/ethernet/huawei/hinic/hinic_dev.h    |   5 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 133 ++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h |  20 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c  | 144 +++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h  |  46 ++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h  |  32 +++++
 drivers/net/ethernet/huawei/hinic/hinic_main.c   | 172 ++++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_rx.c     |  72 ++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_rx.h     |  46 ++++++
 drivers/net/ethernet/huawei/hinic/hinic_tx.c     |  75 ++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_tx.h     |  49 +++++++
 12 files changed, 795 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_rx.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_rx.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_tx.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_tx.h
drivers/net/ethernet/huawei/hinic/Makefile +3 -2
index 08951a6..ce0787c 100644
@@ -1,4 +1,5 @@
 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
\ No newline at end of file
+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
\ No newline at end of file
drivers/net/ethernet/huawei/hinic/hinic_dev.h +5 -0
index 91a3356..72bd5d0 100644
@@ -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
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +133 -0

148 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +20 -0
index 616b2da..8a6ec93 100644
@@ -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);
+
 int hinic_init_hwdev(struct hinic_hwdev **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
drivers/net/ethernet/huawei/hinic/hinic_hw_io.c new file +144 -0

144 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_io.h new file +46 -0

46 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h new file +32 -0
new file mode 100644
index 0000000..64330fb
@@ -0,0 +1,32 @@
+/*
+ * 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
drivers/net/ethernet/huawei/hinic/hinic_main.c +170 -2

218 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_rx.c new file +72 -0

72 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_rx.h new file +46 -0

46 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_tx.c new file +75 -0

75 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_tx.h new file +49 -0

49 lines not on this page · raw message

Signature · 1 line
1.9.1
#17 lore raw

PATCH v2 11/21 net-next/hinic: Add wq

In reply to Aviad Krawczyk

Create work queues for being used by the queue pairs.

---
 drivers/net/ethernet/huawei/hinic/Makefile      |   4 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c |  68 ++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h |   6 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h |  17 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 523 ++++++++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h |  86 ++++
 6 files changed, 699 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h
drivers/net/ethernet/huawei/hinic/Makefile +2 -2
index ce0787c..519382b 100644
@@ -1,5 +1,5 @@
 obj-$(CONFIG_HINIC) += hinic.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
\ No newline at end of file
+	   hinic_hw_io.o hinic_hw_wq.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \
+	   hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file
drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +65 -3

125 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_io.h +6 -0
index 7cdcffd..6cacb8e 100644
@@ -20,11 +20,17 @@
 #include <linux/pci.h>
 
 #include "hinic_hw_if.h"
+#include "hinic_hw_wq.h"
 #include "hinic_hw_qp.h"
 
 struct hinic_func_to_io {
 	struct hinic_hwif       *hwif;
 
+	struct hinic_wqs        wqs;
+
+	struct hinic_wq         *sq_wq;
+	struct hinic_wq         *rq_wq;
+
 	struct hinic_qp         *qps;
 	u16                     max_qps;
 };
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +17 -0
index 64330fb..e8417d4 100644
@@ -16,6 +16,21 @@
 #ifndef HINIC_HW_QP_H
 #define HINIC_HW_QP_H
 
+#include <linux/types.h>
+#include <linux/sizes.h>
+
+#define HINIC_SQ_WQEBB_SIZE                     64
+#define HINIC_RQ_WQEBB_SIZE                     32
+
+#define HINIC_SQ_PAGE_SIZE                      SZ_4K
+#define HINIC_RQ_PAGE_SIZE                      SZ_4K
+
+#define HINIC_SQ_DEPTH                          SZ_4K
+#define HINIC_RQ_DEPTH                          SZ_4K
+
+#define HINIC_SQ_WQE_MAX_SIZE                   320
+#define HINIC_RQ_WQE_SIZE                       32
+
 struct hinic_sq {
 	/* should be implemented */
 };
@@ -27,6 +42,8 @@ struct hinic_rq {
 struct hinic_qp {
 	struct hinic_sq         sq;
 	struct hinic_rq         rq;
+
+	u16     q_id;
 };
 
 #endif
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c new file +523 -0

523 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h new file +86 -0

86 lines not on this page · raw message

Signature · 1 line
1.9.1
#18 lore raw

PATCH v2 12/21 net-next/hinic: Add qp resources

In reply to Aviad Krawczyk

Create the resources for queue pair operations: doorbell area, consumer index address and producer index address.

---
 drivers/net/ethernet/huawei/hinic/Makefile      |   4 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h |   1 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 167 ++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h |  27 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c | 264 ++++++++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h |  60 +++++-
 6 files changed, 518 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c
drivers/net/ethernet/huawei/hinic/Makefile +2 -2
index 519382b..24728f0 100644
@@ -1,5 +1,5 @@
 obj-$(CONFIG_HINIC) += hinic.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_wq.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \
-	   hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file
+	   hinic_hw_io.o hinic_hw_qp.o hinic_hw_wq.o hinic_hw_mgmt.o \
+	   hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file
drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +1 -0
index 88df3c0..89f71e5 100644
@@ -137,6 +137,7 @@
 #define HINIC_IS_PPF(hwif)              (HINIC_FUNC_TYPE(hwif) == HINIC_PPF)
 
 #define HINIC_PCI_CFG_REGS_BAR          0
+#define HINIC_PCI_DB_BAR                4
 
 #define HINIC_PCIE_ST_DISABLE           0
 #define HINIC_PCIE_AT_DISABLE           0
drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +166 -1

245 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_io.h +27 -0
index 6cacb8e..2d85a38 100644
@@ -18,11 +18,30 @@
 
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/semaphore.h>
+#include <linux/sizes.h>
 
 #include "hinic_hw_if.h"
 #include "hinic_hw_wq.h"
 #include "hinic_hw_qp.h"
 
+#define HINIC_DB_PAGE_SIZE      SZ_4K
+#define HINIC_DB_SIZE           SZ_4M
+
+#define HINIC_DB_MAX_AREAS      (HINIC_DB_SIZE / HINIC_DB_PAGE_SIZE)
+
+struct hinic_free_db_area {
+	int             db_idx[HINIC_DB_MAX_AREAS];
+
+	int             alloc_pos;
+	int             return_pos;
+
+	int             num_free;
+
+	/* Lock for getting db area */
+	struct semaphore        idx_lock;
+};
+
 struct hinic_func_to_io {
 	struct hinic_hwif       *hwif;
 
@@ -33,6 +52,14 @@ struct hinic_func_to_io {
 
 	struct hinic_qp         *qps;
 	u16                     max_qps;
+
+	void __iomem            **sq_db;
+	void __iomem            *db_base;
+
+	void                    *ci_addr_base;
+	dma_addr_t              ci_dma_base;
+
+	struct hinic_free_db_area       free_db_area;
 };
 
 int hinic_io_create_qps(struct hinic_func_to_io *func_to_io,
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c new file +264 -0

264 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +58 -2

80 lines not on this page · raw message

Signature · 1 line
1.9.1
maintainer
#19 lore raw

Re: [PATCH V2 net-next 12/21] net-next/hinic: Add qp resources

From: Aviad Krawczyk <[email protected]>
Date: Wed, 19 Jul 2017 17:19:10 +0800

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/Makefile +0 -0
index 519382b..24728f0 100644

drivers/net/ethernet/huawei/hinic/Makefile line 5

Quoted 9 lines
drivers/net/ethernet/huawei/hinic/Makefile +2 -2
@@ -1,5 +1,5 @@
 obj-$(CONFIG_HINIC) += hinic.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_wq.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \
-	   hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file
+	   hinic_hw_io.o hinic_hw_qp.o hinic_hw_wq.o hinic_hw_mgmt.o \
+	   hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file

Please add the missing newline to the end of this Makefile so that these patches don't keep emitting this message.

#20 lore raw

Re: [PATCH V2 net-next 12/21] net-next/hinic: Add qp resources

Hi David,

Strange that checkpatch.pl --strict didn't warn about it. We will fix it.

Thanks for review,
Aviad

Quoted 23 lines · David Miller

From: Aviad Krawczyk <[email protected]>
Date: Wed, 19 Jul 2017 17:19:10 +0800

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/Makefile +0 -0
index 519382b..24728f0 100644

drivers/net/ethernet/huawei/hinic/Makefile line 5

Quoted 9 lines
drivers/net/ethernet/huawei/hinic/Makefile +2 -2
@@ -1,5 +1,5 @@
 obj-$(CONFIG_HINIC) += hinic.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_wq.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \
-	   hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file
+	   hinic_hw_io.o hinic_hw_qp.o hinic_hw_wq.o hinic_hw_mgmt.o \
+	   hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file

Please add the missing newline to the end of this Makefile so that these patches don't keep emitting this message.

.

#21 lore raw

PATCH v2 13/21 net-next/hinic: Set qp context

In reply to Aviad Krawczyk

Update the nic about the resources of the queue pairs.

---
 drivers/net/ethernet/huawei/hinic/Makefile         |   5 +-
 drivers/net/ethernet/huawei/hinic/hinic_common.c   |  55 ++++++
 drivers/net/ethernet/huawei/hinic/hinic_common.h   |  23 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c  |  87 +++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h  |  84 ++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c   |   4 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c    | 153 +++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h    |   5 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c    | 161 ++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h    |  11 ++
 .../net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h   | 214 +++++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h    |   9 +
 12 files changed, 809 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_common.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_common.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h
 create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h
drivers/net/ethernet/huawei/hinic/Makefile +3 -2
index 24728f0..82c1f68 100644
@@ -1,5 +1,6 @@
 obj-$(CONFIG_HINIC) += hinic.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_qp.o hinic_hw_wq.o hinic_hw_mgmt.o \
-	   hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o
\ No newline at end of file
+	   hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \
+	   hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \
+	   hinic_common.o
\ No newline at end of file
drivers/net/ethernet/huawei/hinic/hinic_common.c new file +55 -0

55 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_common.h new file +23 -0
new file mode 100644
index 0000000..21921ec
@@ -0,0 +1,23 @@
+/*
+ * 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_COMMON_H
+#define HINIC_COMMON_H
+
+void hinic_cpu_to_be32(void *data, int len);
+
+void hinic_be32_to_cpu(void *data, int len);
+
+#endif
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c new file +87 -0

87 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h new file +84 -0

84 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +4 -0
index 1568d0a..acfc906 100644
@@ -24,6 +24,7 @@
 #include "hinic_hw_if.h"
 #include "hinic_hw_eqs.h"
 #include "hinic_hw_mgmt.h"
+#include "hinic_hw_qp_ctxt.h"
 #include "hinic_hw_qp.h"
 #include "hinic_hw_io.h"
 #include "hinic_hw_dev.h"
@@ -76,6 +77,9 @@ static int get_capability(struct hinic_hwdev *hwdev,
 	/* Each QP has its own (SQ + RQ) interrupts */
 	num_qps = (num_irqs - (num_aeqs + num_ceqs)) / 2;
 
+	if (num_qps > HINIC_Q_CTXT_MAX)
+		num_qps = HINIC_Q_CTXT_MAX;
+
 	/* num_qps must be power of 2 */
 	num_qps = BIT(fls(num_qps) - 1);
 
drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +153 -0

199 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_io.h +5 -0
index 2d85a38..60d77b34 100644
@@ -23,6 +23,7 @@
 
 #include "hinic_hw_if.h"
 #include "hinic_hw_wq.h"
+#include "hinic_hw_cmdq.h"
 #include "hinic_hw_qp.h"
 
 #define HINIC_DB_PAGE_SIZE      SZ_4K
@@ -60,6 +61,10 @@ struct hinic_func_to_io {
 	dma_addr_t              ci_dma_base;
 
 	struct hinic_free_db_area       free_db_area;
+
+	void __iomem                    *cmdq_db_area[HINIC_MAX_CMDQ_TYPES];
+
+	struct hinic_cmdqs              cmdqs;
 };
 
 int hinic_io_create_qps(struct hinic_func_to_io *func_to_io,
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +161 -0

174 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +11 -0
index 0da85e3..a4b3987 100644
@@ -22,6 +22,7 @@
 
 #include "hinic_hw_if.h"
 #include "hinic_hw_wq.h"
+#include "hinic_hw_qp_ctxt.h"
 
 #define HINIC_SQ_WQEBB_SIZE                     64
 #define HINIC_RQ_WQEBB_SIZE                     32
@@ -91,6 +92,16 @@ struct hinic_qp {
 	u16     q_id;
 };
 
+void hinic_qp_prepare_header(struct hinic_qp_ctxt_header *qp_ctxt_hdr,
+			     enum hinic_qp_ctxt_type ctxt_type,
+			     int num_queues, int max_queues);
+
+void hinic_sq_prepare_ctxt(struct hinic_sq *sq, u16 global_qid,
+			   struct hinic_sq_ctxt *sq_ctxt);
+
+void hinic_rq_prepare_ctxt(struct hinic_rq *rq, u16 global_qid,
+			   struct hinic_rq_ctxt *rq_ctxt);
+
 int hinic_init_sq(struct hinic_sq *sq, struct hinic_hwif *hwif,
 		  struct hinic_wq *wq, struct msix_entry *entry, void *ci_addr,
 		  dma_addr_t ci_dma_addr, void __iomem *db_base);
drivers/net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h new file +214 -0

214 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h +9 -0
index 7c114da..8ce259a 100644
@@ -72,6 +72,15 @@ struct hinic_wqs {
 	struct semaphore        alloc_blocks_lock;
 };
 
+struct hinic_cmdq_pages {
+	/* The addresses are 64 bit in the HW */
+	u64                     page_paddr;
+	u64                     *page_vaddr;
+	void                    **shadow_page_vaddr;
+
+	struct hinic_hwif       *hwif;
+};
+
 int hinic_wqs_alloc(struct hinic_wqs *wqs, int num_wqs,
 		    struct hinic_hwif *hwif);
 
Signature · 1 line
1.9.1
#22 lore raw

PATCH v2 14/21 net-next/hinic: Initialize cmdq

In reply to Aviad Krawczyk

Create the work queues for cmdq and update the nic about the work queue contexts. cmdq commands are used for updating the the nic about the qp contexts.

---
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 284 +++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h |  53 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h  |   2 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h |   5 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c   | 157 ++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h   |   8 +
 6 files changed, 503 insertions(+), 6 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +278 -6
index 2fd3924..f3a6e24 100644
@@ -13,11 +13,49 @@
  *
  */
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/spinlock.h>
+#include <linux/sizes.h>
+#include <linux/atomic.h>
+#include <linux/log2.h>
+#include <asm/byteorder.h>
 
 #include "hinic_hw_if.h"
+#include "hinic_hw_mgmt.h"
+#include "hinic_hw_wq.h"
 #include "hinic_hw_cmdq.h"
+#include "hinic_hw_io.h"
+#include "hinic_hw_dev.h"
+
+#define CMDQ_DB_OFF                     SZ_2K
+
+#define CMDQ_WQEBB_SIZE                 64
+#define CMDQ_DEPTH                      SZ_4K
+
+#define CMDQ_WQ_PAGE_SIZE               SZ_4K
+
+#define WQE_LCMD_SIZE                   64
+#define WQE_SCMD_SIZE                   64
+
+#define CMDQ_PFN(addr, page_size)       ((addr) >> (ilog2(page_size)))
+
+#define cmdq_to_cmdqs(cmdq)     container_of((cmdq) - (cmdq)->cmdq_type, \
+					     struct hinic_cmdqs, cmdq[0])
+
+#define cmdqs_to_func_to_io(cmdqs)      container_of(cmdqs, \
+						     struct hinic_func_to_io, \
+						     cmdqs)
+
+enum cmdq_wqe_type {
+	WQE_LCMD_TYPE,
+	WQE_SCMD_TYPE,
+};
 
 /**
  * hinic_alloc_cmdq_buf - alloc buffer for sending command
@@ -29,8 +67,17 @@
 int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs,
 			 struct hinic_cmdq_buf *cmdq_buf)
 {
-	/* should be implemented */
-	return -ENOMEM;
+	struct hinic_hwif *hwif = cmdqs->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+
+	cmdq_buf->buf = pci_pool_alloc(cmdqs->cmdq_buf_pool, GFP_KERNEL,
+				       &cmdq_buf->dma_addr);
+	if (!cmdq_buf->buf) {
+		dev_err(&pdev->dev, "Failed to allocate cmd from the pool\n");
+		return -ENOMEM;
+	}
+
+	return 0;
 }
 
 /**
@@ -41,7 +88,7 @@ int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs,
 void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs,
 			 struct hinic_cmdq_buf *cmdq_buf)
 {
-	/* should be implemented */
+	pci_pool_free(cmdqs->cmdq_buf_pool, cmdq_buf->buf, cmdq_buf->dma_addr);
 }
 
 /**
@@ -63,6 +110,172 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs,
 }
 
 /**
+ * cmdq_init_queue_ctxt - init the queue ctxt of a cmdq
+ * @cmdq: the cmdq
+ * @cmdq_pages: the memory of the queue
+ * @cmdq_ctxt: returned cmdq ctxt
+ **/
+static void cmdq_init_queue_ctxt(struct hinic_cmdq *cmdq,
+				 struct hinic_cmdq_pages *cmdq_pages,
+				 struct hinic_cmdq_ctxt *cmdq_ctxt)
+{
+	struct hinic_cmdqs *cmdqs = cmdq_to_cmdqs(cmdq);
+	struct hinic_hwif *hwif = cmdqs->hwif;
+	struct hinic_wq *wq = cmdq->wq;
+	struct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info;
+	u16 start_ci = atomic_read(&wq->cons_idx);
+	u64 wq_first_page_paddr, cmdq_first_block_paddr, pfn;
+
+	/* The data in the HW is in Big Endian Format */
+	wq_first_page_paddr = be64_to_cpu(*wq->block_vaddr);
+
+	pfn = CMDQ_PFN(wq_first_page_paddr, wq->wq_page_size);
+
+	ctxt_info->curr_wqe_page_pfn =
+		HINIC_CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN)   |
+		HINIC_CMDQ_CTXT_PAGE_INFO_SET(HINIC_CEQ_ID_CMDQ, EQ_ID) |
+		HINIC_CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_ARM)       |
+		HINIC_CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_EN)        |
+		HINIC_CMDQ_CTXT_PAGE_INFO_SET(cmdq->wrapped, WRAPPED);
+
+	/* block PFN - Read Modify Write */
+	cmdq_first_block_paddr = cmdq_pages->page_paddr;
+
+	pfn = CMDQ_PFN(cmdq_first_block_paddr, wq->wq_page_size);
+
+	ctxt_info->wq_block_pfn =
+		HINIC_CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN) |
+		HINIC_CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI);
+
+	cmdq_ctxt->func_idx = HINIC_HWIF_GLOB_IDX(hwif);
+	cmdq_ctxt->cmdq_type  = cmdq->cmdq_type;
+}
+
+/**
+ * init_cmdq - initialize cmdq
+ * @cmdq: the cmdq
+ * @wq: the wq attaced to the cmdq
+ * @q_type: the cmdq type of the cmdq
+ * @db_area: doorbell area for the cmdq
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static int init_cmdq(struct hinic_cmdq *cmdq, struct hinic_wq *wq,
+		     enum hinic_cmdq_type q_type, void __iomem *db_area)
+{
+	int err;
+
+	cmdq->wq = wq;
+	cmdq->cmdq_type = q_type;
+	cmdq->wrapped = 1;
+
+	spin_lock_init(&cmdq->cmdq_lock);
+
+	cmdq->done = vzalloc(wq->q_depth * sizeof(*cmdq->done));
+	if (!cmdq->done)
+		return -ENOMEM;
+
+	cmdq->errcode = vzalloc(wq->q_depth * sizeof(*cmdq->errcode));
+	if (!cmdq->errcode) {
+		err = -ENOMEM;
+		goto errcode_err;
+	}
+
+	cmdq->db_base = db_area + CMDQ_DB_OFF;
+	return 0;
+
+errcode_err:
+	vfree(cmdq->done);
+	return err;
+}
+
+/**
+ * free_cmdq - Free cmdq
+ * @cmdq: the cmdq to free
+ **/
+static void free_cmdq(struct hinic_cmdq *cmdq)
+{
+	vfree(cmdq->errcode);
+	vfree(cmdq->done);
+}
+
+/**
+ * init_cmdqs_ctxt - write the cmdq ctxt to HW after init all cmdq
+ * @hwdev: the NIC HW device
+ * @cmdqs: cmdqs to write the ctxts for
+ * &db_area: db_area for all the cmdqs
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static int init_cmdqs_ctxt(struct hinic_hwdev *hwdev,
+			   struct hinic_cmdqs *cmdqs, void __iomem **db_area)
+{
+	struct hinic_hwif *hwif = hwdev->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	struct hinic_pfhwdev *pfhwdev;
+	struct hinic_cmdq_ctxt *cmdq_ctxts;
+	enum hinic_cmdq_type type, cmdq_type;
+	size_t cmdq_ctxts_size;
+	int err;
+
+	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
+		dev_err(&pdev->dev, "Unsupported PCI function type\n");
+		return -EINVAL;
+	}
+
+	cmdq_ctxts_size = HINIC_MAX_CMDQ_TYPES * sizeof(*cmdq_ctxts);
+	cmdq_ctxts = devm_kzalloc(&pdev->dev, cmdq_ctxts_size, GFP_KERNEL);
+	if (!cmdq_ctxts)
+		return -ENOMEM;
+
+	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
+
+	cmdq_type = HINIC_CMDQ_SYNC;
+	for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
+		err = init_cmdq(&cmdqs->cmdq[cmdq_type],
+				&cmdqs->saved_wqs[cmdq_type], cmdq_type,
+				db_area[cmdq_type]);
+		if (err) {
+			dev_err(&pdev->dev, "Failed to initialize cmdq\n");
+			devm_kfree(&pdev->dev, cmdq_ctxts);
+			goto init_cmdq_err;
+		}
+
+		cmdq_init_queue_ctxt(&cmdqs->cmdq[cmdq_type],
+				     &cmdqs->cmdq_pages,
+				     &cmdq_ctxts[cmdq_type]);
+	}
+
+	/* Write the CMDQ ctxts */
+	cmdq_type = HINIC_CMDQ_SYNC;
+	for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
+		err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
+					HINIC_COMM_CMD_CMDQ_CTXT_SET,
+					&cmdq_ctxts[cmdq_type],
+					sizeof(cmdq_ctxts[cmdq_type]),
+					NULL, NULL, HINIC_MGMT_MSG_SYNC);
+		if (err) {
+			dev_err(&pdev->dev, "Failed to set CMDQ CTXT type = %d\n",
+				cmdq_type);
+			devm_kfree(&pdev->dev, cmdq_ctxts);
+			goto write_cmdq_ctxt_err;
+		}
+	}
+
+	devm_kfree(&pdev->dev, cmdq_ctxts);
+	return 0;
+
+write_cmdq_ctxt_err:
+	cmdq_type = HINIC_MAX_CMDQ_TYPES;
+
+init_cmdq_err:
+	for (type = HINIC_CMDQ_SYNC; type < cmdq_type; type++)
+		free_cmdq(&cmdqs->cmdq[type]);
+
+	return err;
+}
+
+/**
  * hinic_init_cmdqs - init all cmdqs
  * @cmdqs: cmdqs to init
  * @hwif: HW interface for accessing cmdqs
@@ -73,8 +286,54 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs,
 int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif,
 		     void __iomem **db_area)
 {
-	/* should be implemented */
-	return -EINVAL;
+	struct hinic_func_to_io *func_to_io = cmdqs_to_func_to_io(cmdqs);
+	struct hinic_hwdev *hwdev = container_of(func_to_io, struct hinic_hwdev,
+						 func_to_io);
+	struct pci_dev *pdev = hwif->pdev;
+	size_t saved_wqs_size, max_wqe_size;
+	int err;
+
+	cmdqs->hwif = hwif;
+	cmdqs->cmdq_buf_pool = pci_pool_create("hinic_cmdq", pdev,
+					       HINIC_CMDQ_BUF_SIZE,
+					       HINIC_CMDQ_BUF_SIZE, 0);
+	if (!cmdqs->cmdq_buf_pool)
+		return -ENOMEM;
+
+	saved_wqs_size = HINIC_MAX_CMDQ_TYPES * sizeof(struct hinic_wq);
+	cmdqs->saved_wqs = devm_kzalloc(&pdev->dev, saved_wqs_size, GFP_KERNEL);
+	if (!cmdqs->saved_wqs) {
+		err = -ENOMEM;
+		goto saved_wqs_err;
+	}
+
+	max_wqe_size = WQE_LCMD_SIZE;
+	err = hinic_wqs_cmdq_alloc(&cmdqs->cmdq_pages, cmdqs->saved_wqs, hwif,
+				   HINIC_MAX_CMDQ_TYPES, CMDQ_WQEBB_SIZE,
+				   CMDQ_WQ_PAGE_SIZE, CMDQ_DEPTH, max_wqe_size);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to allocate CMDQ wqs\n");
+		goto cmdq_wqs_error;
+	}
+
+	err = init_cmdqs_ctxt(hwdev, cmdqs, db_area);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to write cmdq ctxt\n");
+		goto cmdq_ctxt_err;
+	}
+
+	return 0;
+
+cmdq_ctxt_err:
+	hinic_wqs_cmdq_free(&cmdqs->cmdq_pages, cmdqs->saved_wqs,
+			    HINIC_MAX_CMDQ_TYPES);
+
+cmdq_wqs_error:
+	devm_kfree(&pdev->dev, cmdqs->saved_wqs);
+
+saved_wqs_err:
+	pci_pool_destroy(cmdqs->cmdq_buf_pool);
+	return err;
 }
 
 /**
@@ -83,5 +342,18 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif,
  **/
 void hinic_free_cmdqs(struct hinic_cmdqs *cmdqs)
 {
-	/* should be implemented */
+	struct hinic_hwif *hwif = cmdqs->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	enum hinic_cmdq_type cmdq_type;
+
+	cmdq_type = HINIC_CMDQ_SYNC;
+	for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++)
+		free_cmdq(&cmdqs->cmdq[cmdq_type]);
+
+	hinic_wqs_cmdq_free(&cmdqs->cmdq_pages, cmdqs->saved_wqs,
+			    HINIC_MAX_CMDQ_TYPES);
+
+	devm_kfree(&pdev->dev, cmdqs->saved_wqs);
+
+	pci_pool_destroy(cmdqs->cmdq_buf_pool);
 }
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h +53 -0

65 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h +2 -0
index b406360..f8f06d2 100644
@@ -106,6 +106,8 @@
 
 #define HINIC_EQ_PAGE_SIZE              SZ_4K
 
+#define HINIC_CEQ_ID_CMDQ               0
+
 enum hinic_eq_type {
 	HINIC_AEQ,
 };
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h +5 -0
index 4f678c8..4a849f1 100644
@@ -68,6 +68,11 @@ enum hinic_cfg_cmd {
 	HINIC_CFG_NIC_CAP = 0,
 };
 
+enum hinic_comm_cmd {
+	HINIC_COMM_CMD_CMDQ_CTXT_SET = 0x10,
+	HINIC_COMM_CMD_CMDQ_CTXT_GET = 0x11,
+};
+
 enum hinic_mgmt_cb_state {
 	HINIC_MGMT_CB_ENABLED = BIT(0),
 	HINIC_MGMT_CB_RUNNING = BIT(1),
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c +157 -0

184 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h +8 -0
index 8ce259a..a3c4469 100644
@@ -81,6 +81,14 @@ struct hinic_cmdq_pages {
 	struct hinic_hwif       *hwif;
 };
 
+int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages,
+			 struct hinic_wq *wq, struct hinic_hwif *hwif,
+			 int cmdq_blocks, u16 wqebb_size, u16 wq_page_size,
+			 u16 q_depth, u16 max_wqe_size);
+
+void hinic_wqs_cmdq_free(struct hinic_cmdq_pages *cmdq_pages,
+			 struct hinic_wq *wq, int cmdq_blocks);
+
 int hinic_wqs_alloc(struct hinic_wqs *wqs, int num_wqs,
 		    struct hinic_hwif *hwif);
 
Signature · 1 line
1.9.1
#23 lore raw

PATCH v2 15/21 net-next/hinic: Add ceqs

In reply to Aviad Krawczyk

Initialize the completion event queues and handle ceq events by calling the registered handlers. Used for cmdq command completion.

---
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c |  17 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h  |  29 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c  |   7 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c  | 290 +++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h  |  75 ++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c   |  15 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h   |   3 +
 7 files changed, 428 insertions(+), 8 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +17 -0
index f3a6e24..7099341 100644
@@ -27,6 +27,7 @@
 #include <asm/byteorder.h>
 
 #include "hinic_hw_if.h"
+#include "hinic_hw_eqs.h"
 #include "hinic_hw_mgmt.h"
 #include "hinic_hw_wq.h"
 #include "hinic_hw_cmdq.h"
@@ -110,6 +111,16 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs,
 }
 
 /**
+ * cmdq_ceq_handler - cmdq completion event handler
+ * @handle: private data for the handler(cmdqs)
+ * @ceqe_data: ceq element data
+ **/
+static void cmdq_ceq_handler(void *handle, u32 ceqe_data)
+{
+	/* should be implemented */
+}
+
+/**
  * cmdq_init_queue_ctxt - init the queue ctxt of a cmdq
  * @cmdq: the cmdq
  * @cmdq_pages: the memory of the queue
@@ -322,6 +333,9 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif,
 		goto cmdq_ctxt_err;
 	}
 
+	hinic_ceq_register_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ, cmdqs,
+			      cmdq_ceq_handler);
+
 	return 0;
 
 cmdq_ctxt_err:
@@ -342,10 +356,13 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif,
  **/
 void hinic_free_cmdqs(struct hinic_cmdqs *cmdqs)
 {
+	struct hinic_func_to_io *func_to_io = cmdqs_to_func_to_io(cmdqs);
 	struct hinic_hwif *hwif = cmdqs->hwif;
 	struct pci_dev *pdev = hwif->pdev;
 	enum hinic_cmdq_type cmdq_type;
 
+	hinic_ceq_unregister_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ);
+
 	cmdq_type = HINIC_CMDQ_SYNC;
 	for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++)
 		free_cmdq(&cmdqs->cmdq[cmdq_type]);
drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +29 -0
index 1f57301..10b8c7b 100644
@@ -81,27 +81,44 @@
 
 /* EQ registers */
 #define HINIC_AEQ_MTT_OFF_BASE_ADDR                     0x200
+#define HINIC_CEQ_MTT_OFF_BASE_ADDR                     0x400
 
 #define HINIC_EQ_MTT_OFF_STRIDE                         0x40
 
 #define HINIC_CSR_AEQ_MTT_OFF(id)                       \
 	(HINIC_AEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE)
 
+#define HINIC_CSR_CEQ_MTT_OFF(id)                       \
+	(HINIC_CEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE)
+
 #define HINIC_CSR_EQ_PAGE_OFF_STRIDE                    8
 
 #define HINIC_CSR_AEQ_HI_PHYS_ADDR_REG(q_id, pg_num)    \
 	(HINIC_CSR_AEQ_MTT_OFF(q_id) + \
 	 (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE)
 
+#define HINIC_CSR_CEQ_HI_PHYS_ADDR_REG(q_id, pg_num)    \
+	(HINIC_CSR_CEQ_MTT_OFF(q_id) +          \
+	 (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE)
+
 #define HINIC_CSR_AEQ_LO_PHYS_ADDR_REG(q_id, pg_num)    \
 	(HINIC_CSR_AEQ_MTT_OFF(q_id) + \
 	 (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4)
 
+#define HINIC_CSR_CEQ_LO_PHYS_ADDR_REG(q_id, pg_num)    \
+	(HINIC_CSR_CEQ_MTT_OFF(q_id) +  \
+	 (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4)
+
 #define HINIC_AEQ_CTRL_0_ADDR_BASE                      0xE00
 #define HINIC_AEQ_CTRL_1_ADDR_BASE                      0xE04
 #define HINIC_AEQ_CONS_IDX_ADDR_BASE                    0xE08
 #define HINIC_AEQ_PROD_IDX_ADDR_BASE                    0xE0C
 
+#define HINIC_CEQ_CTRL_0_ADDR_BASE                      0x1000
+#define HINIC_CEQ_CTRL_1_ADDR_BASE                      0x1004
+#define HINIC_CEQ_CONS_IDX_ADDR_BASE                    0x1008
+#define HINIC_CEQ_PROD_IDX_ADDR_BASE                    0x100C
+
 #define HINIC_EQ_OFF_STRIDE                             0x80
 
 #define HINIC_CSR_AEQ_CTRL_0_ADDR(idx)                  \
@@ -116,4 +133,16 @@
 #define HINIC_CSR_AEQ_PROD_IDX_ADDR(idx)                \
 	(HINIC_AEQ_PROD_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
 
+#define HINIC_CSR_CEQ_CTRL_0_ADDR(idx)                  \
+	(HINIC_CEQ_CTRL_0_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
+
+#define HINIC_CSR_CEQ_CTRL_1_ADDR(idx)                  \
+	(HINIC_CEQ_CTRL_1_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
+
+#define HINIC_CSR_CEQ_CONS_IDX_ADDR(idx)                \
+	(HINIC_CEQ_CONS_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
+
+#define HINIC_CSR_CEQ_PROD_IDX_ADDR(idx)                \
+	(HINIC_CEQ_PROD_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
+
 #endif
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +6 -1
index acfc906..8c21b3a 100644
@@ -281,6 +281,7 @@ int hinic_hwdev_ifup(struct hinic_hwdev *hwdev)
 	struct pci_dev *pdev = hwif->pdev;
 	int num_qps = nic_cap->num_qps;
 	int max_qps = nic_cap->max_qps;
+	struct msix_entry *ceq_msix_entries;
 	struct msix_entry *sq_msix_entries;
 	struct msix_entry *rq_msix_entries;
 	u16 base_qpn;
@@ -294,7 +295,11 @@ int hinic_hwdev_ifup(struct hinic_hwdev *hwdev)
 
 	num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
 	num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);
-	err = hinic_io_init(func_to_io, hwif, max_qps, 0, NULL);
+
+	ceq_msix_entries = &hwdev->msix_entries[num_aeqs];
+
+	err = hinic_io_init(func_to_io, hwif, max_qps, num_ceqs,
+			    ceq_msix_entries);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to init IO channel\n");
 		return err;
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c +284 -6

394 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h +75 -0

135 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +14 -1
index f40346e..e9c8c4b 100644
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 
 #include "hinic_hw_if.h"
+#include "hinic_hw_eqs.h"
 #include "hinic_hw_wq.h"
 #include "hinic_hw_cmdq.h"
 #include "hinic_hw_qp_ctxt.h"
@@ -462,10 +463,18 @@ int hinic_io_init(struct hinic_func_to_io *func_to_io,
 	func_to_io->qps = NULL;
 	func_to_io->max_qps = max_qps;
 
+	err = hinic_ceqs_init(&func_to_io->ceqs, hwif, num_ceqs,
+			      HINIC_DEFAULT_CEQ_LEN, HINIC_EQ_PAGE_SIZE,
+			      ceq_msix_entries);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to init CEQs\n");
+		return err;
+	}
+
 	err = hinic_wqs_alloc(&func_to_io->wqs, 2 * max_qps, hwif);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to allocate WQS for IO\n");
-		return err;
+		goto wqs_alloc_err;
 	}
 
 	func_to_io->db_base = pci_ioremap_bar(pdev, HINIC_PCI_DB_BAR);
@@ -503,6 +512,9 @@ int hinic_io_init(struct hinic_func_to_io *func_to_io,
 
 db_ioremap_err:
 	hinic_wqs_free(&func_to_io->wqs);
+
+wqs_alloc_err:
+	hinic_ceqs_free(&func_to_io->ceqs);
 	return err;
 }
 
@@ -521,4 +533,5 @@ void hinic_io_free(struct hinic_func_to_io *func_to_io)
 
 	iounmap(func_to_io->db_base);
 	hinic_wqs_free(&func_to_io->wqs);
+	hinic_ceqs_free(&func_to_io->ceqs);
 }
drivers/net/ethernet/huawei/hinic/hinic_hw_io.h +3 -0
index 60d77b34..cfc21ba 100644
@@ -22,6 +22,7 @@
 #include <linux/sizes.h>
 
 #include "hinic_hw_if.h"
+#include "hinic_hw_eqs.h"
 #include "hinic_hw_wq.h"
 #include "hinic_hw_cmdq.h"
 #include "hinic_hw_qp.h"
@@ -46,6 +47,8 @@ struct hinic_free_db_area {
 struct hinic_func_to_io {
 	struct hinic_hwif       *hwif;
 
+	struct hinic_ceqs       ceqs;
+
 	struct hinic_wqs        wqs;
 
 	struct hinic_wq         *sq_wq;
Signature · 1 line
1.9.1
#24 lore raw

PATCH v2 16/21 net-next/hinic: Add cmdq commands

In reply to Aviad Krawczyk

Add cmdq commands for setting queue pair contexts in the nic.

---
 drivers/net/ethernet/huawei/hinic/hinic_common.c  |  25 ++
 drivers/net/ethernet/huawei/hinic/hinic_common.h  |  15 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 284 +++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 153 ++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h   |   9 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c   | 193 +++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h   |   8 +
 7 files changed, 685 insertions(+), 2 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_common.c +25 -0
index 3b439e9..07d264c 100644
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
 
@@ -53,3 +54,27 @@ void hinic_be32_to_cpu(void *data, int len)
 		mem++;
 	}
 }
+
+/**
+ * hinic_set_sge - set dma area in scatter gather entry
+ * @sge: scatter gather entry
+ * @addr: dma address
+ * @len: length of relevant data in the dma address
+ **/
+void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, int len)
+{
+	sge->hi_addr = upper_32_bits(addr);
+	sge->lo_addr = lower_32_bits(addr);
+	sge->len  = len;
+}
+
+/**
+ * hinic_sge_to_dma - get dma address from scatter gather entry
+ * @sge: scatter gather entry
+ *
+ * Return dma address of sg entry
+ **/
+dma_addr_t hinic_sge_to_dma(struct hinic_sge *sge)
+{
+	return (dma_addr_t)((((u64)sge->hi_addr) << 32) | sge->lo_addr);
+}
drivers/net/ethernet/huawei/hinic/hinic_common.h +15 -0
index 21921ec..2c06b76 100644
@@ -16,8 +16,23 @@
 #ifndef HINIC_COMMON_H
 #define HINIC_COMMON_H
 
+#include <linux/types.h>
+
+#define UPPER_8_BITS(data)      (((data) >> 8) & 0xFF)
+#define LOWER_8_BITS(data)      ((data) & 0xFF)
+
+struct hinic_sge {
+	u32             hi_addr;
+	u32             lo_addr;
+	u32             len;
+};
+
 void hinic_cpu_to_be32(void *data, int len);
 
 void hinic_be32_to_cpu(void *data, int len);
 
+void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, int len);
+
+dma_addr_t hinic_sge_to_dma(struct hinic_sge *sge);
+
 #endif
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +282 -2

325 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h +153 -0

179 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_io.h +9 -0
index cfc21ba..6f40e6a 100644
@@ -32,6 +32,15 @@
 
 #define HINIC_DB_MAX_AREAS      (HINIC_DB_SIZE / HINIC_DB_PAGE_SIZE)
 
+enum hinic_db_type {
+	HINIC_DB_CMDQ_TYPE,
+	HINIC_DB_SQ_TYPE,
+};
+
+enum hinic_io_path {
+	HINIC_CTRL_PATH,
+};
+
 struct hinic_free_db_area {
 	int             db_idx[HINIC_DB_MAX_AREAS];
 
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c +193 -0

202 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h +8 -0
index a3c4469..da66848 100644
@@ -100,4 +100,12 @@ int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq,
 
 void hinic_wq_free(struct hinic_wqs *wqs, struct hinic_wq *wq);
 
+void *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size, u16 *prod_idx);
+
+void hinic_put_wqe(struct hinic_wq *wq, unsigned int wqe_size);
+
+void *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size, u16 *cons_idx);
+
+void hinic_write_wqe(struct hinic_wq *wq, void *wqe, unsigned int wqe_size);
+
 #endif
Signature · 1 line
1.9.1
#25 lore raw

PATCH v2 17/21 net-next/hinic: Add cmdq completion handler

In reply to Aviad Krawczyk

Add cmdq completion handler for getting a notification about the completion of cmdq commands.

---
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 286 +++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h |  12 +
 2 files changed, 297 insertions(+), 1 deletion(-)
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +285 -1
index 1bc51d7..5761e74 100644
@@ -38,12 +38,31 @@
 #include "hinic_hw_io.h"
 #include "hinic_hw_dev.h"
 
+#define CMDQ_CEQE_TYPE_SHIFT                    0
+
+#define CMDQ_CEQE_TYPE_MASK                     0x7
+
+#define CMDQ_CEQE_GET(val, member)              \
+			(((val) >> CMDQ_CEQE_##member##_SHIFT) \
+			 & CMDQ_CEQE_##member##_MASK)
+
+#define CMDQ_WQE_ERRCODE_VAL_SHIFT              20
+
+#define CMDQ_WQE_ERRCODE_VAL_MASK               0xF
+
+#define CMDQ_WQE_ERRCODE_GET(val, member)       \
+			(((val) >> CMDQ_WQE_ERRCODE_##member##_SHIFT) \
+			 & CMDQ_WQE_ERRCODE_##member##_MASK)
+
 #define CMDQ_DB_PI_OFF(pi)              (((u16)LOWER_8_BITS(pi)) << 3)
 
 #define CMDQ_DB_ADDR(db_base, pi)       ((db_base) + CMDQ_DB_PI_OFF(pi))
 
 #define CMDQ_WQE_HEADER(wqe)            ((struct hinic_cmdq_header *)(wqe))
 
+#define CMDQ_WQE_COMPLETED(ctrl_info)   \
+			HINIC_CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT)
+
 #define FIRST_DATA_TO_WRITE_LAST        sizeof(u64)
 
 #define CMDQ_DB_OFF                     SZ_2K
@@ -109,6 +128,9 @@ enum completion_request {
 	CEQ_SET,
 };
 
+static void clear_wqe_complete_bit(struct hinic_cmdq *cmdq,
+				   struct hinic_cmdq_wqe *wqe);
+
 /**
  * hinic_alloc_cmdq_buf - alloc buffer for sending command
  * @cmdqs: the cmdqs
@@ -143,6 +165,22 @@ void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs,
 	pci_pool_free(cmdqs->cmdq_buf_pool, cmdq_buf->buf, cmdq_buf->dma_addr);
 }
 
+static int cmdq_wqe_size_from_bdlen(enum bufdesc_len len)
+{
+	int wqe_size = 0;
+
+	switch (len) {
+	case BUFDESC_LCMD_LEN:
+		wqe_size = WQE_LCMD_SIZE;
+		break;
+	case BUFDESC_SCMD_LEN:
+		wqe_size = WQE_SCMD_SIZE;
+		break;
+	}
+
+	return wqe_size;
+}
+
 static void cmdq_set_sge_completion(struct hinic_cmdq_completion *completion,
 				    struct hinic_cmdq_buf *buf_out)
 {
@@ -209,6 +247,15 @@ static void cmdq_set_lcmd_bufdesc(struct hinic_cmdq_wqe_lcmd *wqe_lcmd,
 	hinic_set_sge(&wqe_lcmd->buf_desc.sge, buf_in->dma_addr, buf_in->size);
 }
 
+static void cmdq_set_direct_wqe_data(struct hinic_cmdq_direct_wqe *wqe,
+				     void *buf_in, u32 in_size)
+{
+	struct hinic_cmdq_wqe_scmd *wqe_scmd = &wqe->wqe_scmd;
+
+	wqe_scmd->buf_desc.buf_len = in_size;
+	memcpy(wqe_scmd->buf_desc.data, buf_in, in_size);
+}
+
 static void cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe *wqe,
 			      enum cmdq_cmd_type cmd_type,
 			      struct hinic_cmdq_buf *buf_in,
@@ -237,6 +284,34 @@ static void cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe *wqe,
 	cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in);
 }
 
+static void cmdq_set_direct_wqe(struct hinic_cmdq_wqe *wqe,
+				enum cmdq_cmd_type cmd_type,
+				void *buf_in, u16 in_size,
+				struct hinic_cmdq_buf *buf_out, int wrapped,
+				enum hinic_cmd_ack_type ack_type,
+				enum hinic_mod_type mod, u8 cmd, u16 prod_idx)
+{
+	struct hinic_cmdq_direct_wqe *direct_wqe = &wqe->direct_wqe;
+	struct hinic_cmdq_wqe_scmd *wqe_scmd = &direct_wqe->wqe_scmd;
+	enum completion_format complete_format;
+
+	switch (cmd_type) {
+	case CMDQ_CMD_SYNC_SGE_RESP:
+		complete_format = COMPLETE_SGE;
+		cmdq_set_sge_completion(&wqe_scmd->completion, buf_out);
+		break;
+	case CMDQ_CMD_SYNC_DIRECT_RESP:
+		complete_format = COMPLETE_DIRECT;
+		wqe_scmd->completion.direct_resp = 0;
+		break;
+	}
+
+	cmdq_prepare_wqe_ctrl(wqe, wrapped, ack_type, mod, cmd, prod_idx,
+			      complete_format, DATA_DIRECT, BUFDESC_SCMD_LEN);
+
+	cmdq_set_direct_wqe_data(direct_wqe, buf_in, in_size);
+}
+
 static void cmdq_wqe_fill(void *dst, void *src)
 {
 	memcpy(dst + FIRST_DATA_TO_WRITE_LAST, src + FIRST_DATA_TO_WRITE_LAST,
@@ -355,6 +430,50 @@ static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq,
 	return 0;
 }
 
+static int cmdq_set_arm_bit(struct hinic_cmdq *cmdq, void *buf_in,
+			    u16 in_size)
+{
+	struct hinic_wq *wq = cmdq->wq;
+	struct hinic_cmdq_wqe *curr_wqe, wqe;
+	u16 curr_prod_idx, next_prod_idx;
+	int wrapped, num_wqebbs;
+
+	/* Keep doorbell index correct */
+	spin_lock(&cmdq->cmdq_lock);
+
+	/* WQE_SIZE = WQEBB_SIZE, we will get the wq element and not shadow*/
+	curr_wqe = hinic_get_wqe(wq, WQE_SCMD_SIZE, &curr_prod_idx);
+	if (!curr_wqe) {
+		spin_unlock(&cmdq->cmdq_lock);
+		return -EBUSY;
+	}
+
+	wrapped = cmdq->wrapped;
+
+	num_wqebbs = ALIGN(WQE_SCMD_SIZE, wq->wqebb_size) / wq->wqebb_size;
+	next_prod_idx = curr_prod_idx + num_wqebbs;
+	if (next_prod_idx >= wq->q_depth) {
+		cmdq->wrapped = !cmdq->wrapped;
+		next_prod_idx -= wq->q_depth;
+	}
+
+	cmdq_set_direct_wqe(&wqe, CMDQ_CMD_SYNC_DIRECT_RESP, buf_in, in_size,
+			    NULL, wrapped, HINIC_CMD_ACK_TYPE_CMDQ,
+			    HINIC_MOD_COMM, CMDQ_SET_ARM_CMD, curr_prod_idx);
+
+	/* The data that is written to HW should be in Big Endian Format */
+	hinic_cpu_to_be32(&wqe, WQE_SCMD_SIZE);
+
+	/* cmdq wqe is not shadow, therefore wqe will be written to wq */
+	cmdq_wqe_fill(curr_wqe, &wqe);
+
+	cmdq_set_db(cmdq, HINIC_CMDQ_SYNC, next_prod_idx);
+
+	spin_unlock(&cmdq->cmdq_lock);
+
+	return 0;
+}
+
 static int cmdq_params_valid(struct hinic_cmdq_buf *buf_in)
 {
 	if (buf_in->size > HINIC_CMDQ_MAX_DATA_SIZE)
@@ -391,13 +510,178 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs,
 }
 
 /**
+ * hinic_set_arm_bit - set arm bit for enable interrupt again
+ * @cmdqs: the cmdqs
+ * @q_type: type of queue to set the arm bit for
+ * @q_id: the queue number
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+int hinic_set_arm_bit(struct hinic_cmdqs *cmdqs,
+		      enum hinic_set_arm_qtype q_type, u32 q_id)
+{
+	struct hinic_cmdq *cmdq = &cmdqs->cmdq[HINIC_CMDQ_SYNC];
+	struct hinic_hwif *hwif = cmdqs->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	struct hinic_cmdq_arm_bit arm_bit;
+	int err;
+
+	arm_bit.q_type = q_type;
+	arm_bit.q_id   = q_id;
+
+	err = cmdq_set_arm_bit(cmdq, &arm_bit, sizeof(arm_bit));
+	if (err) {
+		dev_err(&pdev->dev, "Failed to set arm for qid %d\n", q_id);
+		return err;
+	}
+
+	return 0;
+}
+
+static void clear_wqe_complete_bit(struct hinic_cmdq *cmdq,
+				   struct hinic_cmdq_wqe *wqe)
+{
+	u32 header_info = be32_to_cpu(CMDQ_WQE_HEADER(wqe)->header_info);
+	int bufdesc_len = HINIC_CMDQ_WQE_HEADER_GET(header_info, BUFDESC_LEN);
+	int wqe_size = cmdq_wqe_size_from_bdlen(bufdesc_len);
+	struct hinic_cmdq_wqe_lcmd *wqe_lcmd;
+	struct hinic_cmdq_direct_wqe *direct_wqe;
+	struct hinic_cmdq_wqe_scmd *wqe_scmd;
+	struct hinic_ctrl *ctrl;
+
+	if (wqe_size == WQE_LCMD_SIZE) {
+		wqe_lcmd = &wqe->wqe_lcmd;
+		ctrl = &wqe_lcmd->ctrl;
+	} else {
+		direct_wqe = &wqe->direct_wqe;
+		wqe_scmd = &direct_wqe->wqe_scmd;
+		ctrl = &wqe_scmd->ctrl;
+	}
+
+	/* clear HW busy bit */
+	ctrl->ctrl_info = 0;
+
+	wmb();  /* verify wqe is clear */
+}
+
+/**
+ * cmdq_arm_ceq_handler - cmdq completion event handler for arm command
+ * @cmdq: the cmdq of the arm command
+ * @wqe: the wqe of the arm command
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+static int cmdq_arm_ceq_handler(struct hinic_cmdq *cmdq,
+				struct hinic_cmdq_wqe *wqe)
+{
+	struct hinic_cmdq_direct_wqe *direct_wqe = &wqe->direct_wqe;
+	struct hinic_cmdq_wqe_scmd *wqe_scmd = &direct_wqe->wqe_scmd;
+	struct hinic_ctrl *ctrl = &wqe_scmd->ctrl;
+	u32 ctrl_info = be32_to_cpu(ctrl->ctrl_info);
+
+	/* HW should toggle the HW BUSY BIT */
+	if (!CMDQ_WQE_COMPLETED(ctrl_info))
+		return -EBUSY;
+
+	clear_wqe_complete_bit(cmdq, wqe);
+
+	hinic_put_wqe(cmdq->wq, WQE_SCMD_SIZE);
+	return 0;
+}
+
+static void cmdq_update_errcode(struct hinic_cmdq *cmdq, u16 prod_idx,
+				int errcode)
+{
+	if (cmdq->errcode[prod_idx])
+		*cmdq->errcode[prod_idx] = errcode;
+}
+
+/**
+ * cmdq_arm_ceq_handler - cmdq completion event handler for sync command
+ * @cmdq: the cmdq of the command
+ * @cons_idx: the consumer index to update the error code for
+ * @errcode: the error code
+ **/
+static void cmdq_sync_cmd_handler(struct hinic_cmdq *cmdq, u16 cons_idx,
+				  int errcode)
+{
+	u16 prod_idx = cons_idx;
+
+	spin_lock(&cmdq->cmdq_lock);
+	cmdq_update_errcode(cmdq, prod_idx, errcode);
+
+	wmb();  /* write all before update for the command request */
+
+	if (cmdq->done[prod_idx])
+		complete(cmdq->done[prod_idx]);
+
+	spin_unlock(&cmdq->cmdq_lock);
+}
+
+/**
  * cmdq_ceq_handler - cmdq completion event handler
  * @handle: private data for the handler(cmdqs)
  * @ceqe_data: ceq element data
  **/
 static void cmdq_ceq_handler(void *handle, u32 ceqe_data)
 {
-	/* should be implemented */
+	struct hinic_cmdqs *cmdqs = (struct hinic_cmdqs *)handle;
+	struct hinic_hwif *hwif = cmdqs->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	enum hinic_cmdq_type cmdq_type = CMDQ_CEQE_GET(ceqe_data, TYPE);
+	struct hinic_cmdq *cmdq = &cmdqs->cmdq[cmdq_type];
+	struct hinic_cmdq_wqe *wqe;
+	struct hinic_cmdq_wqe_lcmd *wqe_lcmd;
+	struct hinic_ctrl *ctrl;
+	struct hinic_status *status;
+	int err, errcode, set_arm = 0;
+	u32 status_info, ctrl_info, saved_data;
+	u16 ci;
+
+	/* Read the smallest wqe size for getting wqe size */
+	while ((wqe = hinic_read_wqe(cmdq->wq, WQE_SCMD_SIZE, &ci))) {
+		saved_data = be32_to_cpu(CMDQ_WQE_HEADER(wqe)->saved_data);
+
+		if (HINIC_SAVED_DATA_GET(saved_data, ARM)) {
+			/* arm_bit was set until here */
+			set_arm = 0;
+
+			if (cmdq_arm_ceq_handler(cmdq, wqe))
+				break;
+		} else {
+			set_arm = 1;
+
+			wqe = hinic_read_wqe(cmdq->wq, WQE_LCMD_SIZE, &ci);
+			if (!wqe)
+				break;
+
+			/* only arm bit cmd is using scmd wqe,
+			 * the wqe is lcmd
+			 */
+			wqe_lcmd = &wqe->wqe_lcmd;
+			ctrl = &wqe_lcmd->ctrl;
+			ctrl_info = be32_to_cpu(ctrl->ctrl_info);
+
+			if (!CMDQ_WQE_COMPLETED(ctrl_info))
+				break;
+
+			status = &wqe_lcmd->status;
+			status_info = be32_to_cpu(status->status_info);
+
+			errcode = CMDQ_WQE_ERRCODE_GET(status_info, VAL);
+
+			cmdq_sync_cmd_handler(cmdq, ci, errcode);
+
+			clear_wqe_complete_bit(cmdq, wqe);
+			hinic_put_wqe(cmdq->wq, WQE_LCMD_SIZE);
+		}
+	}
+
+	if (set_arm) {
+		err = hinic_set_arm_bit(cmdqs, HINIC_SET_ARM_CMDQ, cmdq_type);
+		if (err)
+			dev_err(&pdev->dev, "Failed to set arm for CMDQ\n");
+	}
 }
 
 /**
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h +12 -0
index bbdad66..9dbb59d 100644
@@ -147,6 +147,10 @@ enum hinic_cmdq_type {
 	HINIC_MAX_CMDQ_TYPES,
 };
 
+enum hinic_set_arm_qtype {
+	HINIC_SET_ARM_CMDQ,
+};
+
 enum hinic_cmd_ack_type {
 	HINIC_CMD_ACK_TYPE_CMDQ,
 };
@@ -225,6 +229,11 @@ struct hinic_cmdq_wqe {
 	};
 };
 
+struct hinic_cmdq_arm_bit {
+	u32     q_type;
+	u32     q_id;
+};
+
 struct hinic_cmdq_ctxt_info {
 	u64     curr_wqe_page_pfn;
 	u64     wq_block_pfn;
@@ -282,6 +291,9 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs,
 			   enum hinic_mod_type mod, u8 cmd,
 			   struct hinic_cmdq_buf *buf_in, u64 *out_param);
 
+int hinic_set_arm_bit(struct hinic_cmdqs *cmdqs,
+		      enum hinic_set_arm_qtype q_type, u32 q_id);
+
 int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif,
 		     void __iomem **db_area);
 
Signature · 1 line
1.9.1
#26 lore raw

PATCH v2 18/21 net-next/hinic: Add Rx handler

In reply to Aviad Krawczyk

Set the io resources in the nic and handle rx events by qp operations.

---
 drivers/net/ethernet/huawei/hinic/hinic_dev.h     |   1 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h  |   1 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c  | 361 ++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h  |  77 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c   |  36 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h   |  35 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h |  15 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c   | 195 ++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h   |  81 ++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c   |  12 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h   |   2 +
 drivers/net/ethernet/huawei/hinic/hinic_main.c    |  24 ++
 drivers/net/ethernet/huawei/hinic/hinic_port.c    |  32 ++
 drivers/net/ethernet/huawei/hinic/hinic_port.h    |  19 +
 drivers/net/ethernet/huawei/hinic/hinic_rx.c      | 427 ++++++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_rx.h      |   7 +
 16 files changed, 1323 insertions(+), 2 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_dev.h +1 -0
index 72bd5d0..5fcde35 100644
@@ -43,6 +43,7 @@ struct hinic_dev {
 	struct hinic_hwdev              *hwdev;
 
 	u32                             msg_enable;
+	unsigned int                    rx_weight;
 
 	unsigned int                    flags;
 
drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +1 -0
index 10b8c7b..f39b184 100644
@@ -20,6 +20,7 @@
 #define HINIC_CSR_FUNC_ATTR0_ADDR                       0x0
 #define HINIC_CSR_FUNC_ATTR1_ADDR                       0x4
 
+#define HINIC_CSR_FUNC_ATTR4_ADDR                       0x10
 #define HINIC_CSR_FUNC_ATTR5_ADDR                       0x14
 
 #define HINIC_DMA_ATTR_BASE                             0xC80
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +361 -0

428 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +77 -0

87 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_if.c +36 -0
index 9296758..f65bb12 100644
@@ -134,6 +134,42 @@ void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action)
 	hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR, attr5);
 }
 
+enum hinic_outbound_state hinic_outbound_state_get(struct hinic_hwif *hwif)
+{
+	u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
+
+	return HINIC_FA4_GET(attr4, OUTBOUND_STATE);
+}
+
+void hinic_outbound_state_set(struct hinic_hwif *hwif,
+			      enum hinic_outbound_state outbound_state)
+{
+	u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
+
+	attr4 = HINIC_FA4_CLEAR(attr4, OUTBOUND_STATE);
+	attr4 |= HINIC_FA4_SET(outbound_state, OUTBOUND_STATE);
+
+	hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4);
+}
+
+enum hinic_db_state hinic_db_state_get(struct hinic_hwif *hwif)
+{
+	u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
+
+	return HINIC_FA4_GET(attr4, DB_STATE);
+}
+
+void hinic_db_state_set(struct hinic_hwif *hwif,
+			enum hinic_db_state db_state)
+{
+	u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
+
+	attr4 = HINIC_FA4_CLEAR(attr4, DB_STATE);
+	attr4 |= HINIC_FA4_SET(db_state, DB_STATE);
+
+	hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4);
+}
+
 /**
  * hwif_ready - test if the HW is ready for use
  * @hwif: the HW interface of a pci function device
drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +35 -0
index 89f71e5..5d37df8 100644
@@ -73,6 +73,21 @@
 #define HINIC_FA1_GET(val, member)                              \
 	(((val) >> HINIC_FA1_##member##_SHIFT) & HINIC_FA1_##member##_MASK)
 
+#define HINIC_FA4_OUTBOUND_STATE_SHIFT                          0
+#define HINIC_FA4_DB_STATE_SHIFT                                1
+
+#define HINIC_FA4_OUTBOUND_STATE_MASK                           0x1
+#define HINIC_FA4_DB_STATE_MASK                                 0x1
+
+#define HINIC_FA4_GET(val, member)                              \
+	(((val) >> HINIC_FA4_##member##_SHIFT) & HINIC_FA4_##member##_MASK)
+
+#define HINIC_FA4_SET(val, member)                              \
+	((((u32)val) & HINIC_FA4_##member##_MASK) << HINIC_FA4_##member##_SHIFT)
+
+#define HINIC_FA4_CLEAR(val, member)                            \
+	((val) & (~(HINIC_FA4_##member##_MASK << HINIC_FA4_##member##_SHIFT)))
+
 #define HINIC_FA5_PF_ACTION_SHIFT                               0
 #define HINIC_FA5_PF_ACTION_MASK                                0xFFFF
 
@@ -182,6 +197,16 @@ enum hinic_pf_action {
 	HINIC_PF_MGMT_ACTIVE = 0x11,
 };
 
+enum hinic_outbound_state {
+	HINIC_OUTBOUND_ENABLE  = 0,
+	HINIC_OUTBOUND_DISABLE = 1,
+};
+
+enum hinic_db_state {
+	HINIC_DB_ENABLE  = 0,
+	HINIC_DB_DISABLE = 1,
+};
+
 struct hinic_func_attr {
 	u16                     func_global_idx;
 	u8                      pf_idx;
@@ -230,6 +255,16 @@ int hinic_msix_attr_get(struct hinic_hwif *hwif, u16 msix_index,
 
 void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action);
 
+enum hinic_outbound_state hinic_outbound_state_get(struct hinic_hwif *hwif);
+
+void hinic_outbound_state_set(struct hinic_hwif *hwif,
+			      enum hinic_outbound_state outbound_state);
+
+enum hinic_db_state hinic_db_state_get(struct hinic_hwif *hwif);
+
+void hinic_db_state_set(struct hinic_hwif *hwif,
+			enum hinic_db_state db_state);
+
 int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev);
 
 void hinic_free_hwif(struct hinic_hwif *hwif);
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h +13 -2
index 4a849f1..6cf5061 100644
@@ -69,8 +69,19 @@ enum hinic_cfg_cmd {
 };
 
 enum hinic_comm_cmd {
-	HINIC_COMM_CMD_CMDQ_CTXT_SET = 0x10,
-	HINIC_COMM_CMD_CMDQ_CTXT_GET = 0x11,
+	HINIC_COMM_CMD_IO_STATUS_GET    = 0x3,
+
+	HINIC_COMM_CMD_CMDQ_CTXT_SET    = 0x10,
+	HINIC_COMM_CMD_CMDQ_CTXT_GET    = 0x11,
+
+	HINIC_COMM_CMD_HWCTXT_SET       = 0x12,
+	HINIC_COMM_CMD_HWCTXT_GET       = 0x13,
+
+	HINIC_COMM_CMD_RES_STATE_SET    = 0x24,
+
+	HINIC_COMM_CMD_IO_RES_CLEAR     = 0x29,
+
+	HINIC_COMM_CMD_MAX              = 0x32,
 };
 
 enum hinic_mgmt_cb_state {
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +195 -0

210 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +81 -0

101 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c +12 -0
index 887d729..3626b71 100644
@@ -833,6 +833,18 @@ void *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size, u16 *cons_idx)
 }
 
 /**
+ * hinic_read_wqe_direct - read wqe directly from ci position
+ * @wq: wq
+ * @cons_idx: ci position
+ *
+ * Return wqe
+ **/
+void *hinic_read_wqe_direct(struct hinic_wq *wq, u16 cons_idx)
+{
+	return WQ_PAGE_ADDR(wq, cons_idx) + WQE_PAGE_OFF(wq, cons_idx);
+}
+
+/**
  * wqe_shadow - check if a wqe is shadow
  * @wq: wq of the wqe
  * @wqe: the wqe for shadow checking
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h +2 -0
index da66848..c2d7483 100644
@@ -106,6 +106,8 @@ int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq,
 
 void *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size, u16 *cons_idx);
 
+void *hinic_read_wqe_direct(struct hinic_wq *wq, u16 cons_idx);
+
 void hinic_write_wqe(struct hinic_wq *wq, void *wqe, unsigned int wqe_size);
 
 #endif
drivers/net/ethernet/huawei/hinic/hinic_main.c +24 -0
index aefc664..8aceaa0 100644
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/device.h>
 #include <linux/errno.h>
@@ -42,6 +43,10 @@
 MODULE_DESCRIPTION("Huawei Intelligent NIC driver");
 MODULE_LICENSE("GPL");
 
+static unsigned int rx_weight = 64;
+module_param(rx_weight, uint, 0644);
+MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)");
+
 #define HINIC_WQ_NAME                   "hinic_dev"
 
 #define MSG_ENABLE_DEFAULT              (NETIF_MSG_DRV | NETIF_MSG_PROBE | \
@@ -216,6 +221,12 @@ static int hinic_open(struct net_device *netdev)
 		goto port_state_err;
 	}
 
+	err = hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_ENABLE);
+	if (err) {
+		dev_err(&netdev->dev, "Failed to set func port state\n");
+		goto func_port_state_err;
+	}
+
 	/* Wait up to 3 sec between port enable to link state */
 	msleep(3000);
 
@@ -247,6 +258,11 @@ static int hinic_open(struct net_device *netdev)
 
 port_link_err:
 	up(&nic_dev->mgmt_lock);
+	ret = hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE);
+	if (ret)
+		dev_warn(&netdev->dev, "Failed to revert func port state\n");
+
+func_port_state_err:
 	ret = hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE);
 	if (ret)
 		dev_warn(&netdev->dev, "Failed to revert port state\n");
@@ -280,6 +296,13 @@ static int hinic_close(struct net_device *netdev)
 
 	up(&nic_dev->mgmt_lock);
 
+	err = hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE);
+	if (err) {
+		dev_err(&netdev->dev, "Failed to set func port state\n");
+		nic_dev->flags |= (flags & HINIC_INTF_UP);
+		return err;
+	}
+
 	err = hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE);
 	if (err) {
 		dev_err(&netdev->dev, "Failed to set port state\n");
@@ -667,6 +690,7 @@ static int nic_dev_init(struct pci_dev *pdev)
 	nic_dev->flags = 0;
 	nic_dev->txqs = NULL;
 	nic_dev->rxqs = NULL;
+	nic_dev->rx_weight = rx_weight;
 
 	sema_init(&nic_dev->mgmt_lock, 1);
 
drivers/net/ethernet/huawei/hinic/hinic_port.c +32 -0
index fdf5483..79d75bc 100644
@@ -340,3 +340,35 @@ int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
 
 	return 0;
 }
+
+/**
+ * hinic_port_set_func_state- set func device state
+ * @nic_dev: nic device
+ * @state: the state to set
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+int hinic_port_set_func_state(struct hinic_dev *nic_dev,
+			      enum hinic_func_port_state state)
+{
+	struct hinic_hwdev *hwdev = nic_dev->hwdev;
+	struct hinic_hwif *hwif = hwdev->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	struct hinic_port_func_state_cmd func_state;
+	u16 out_size;
+	int err;
+
+	func_state.func_idx = HINIC_HWIF_GLOB_IDX(hwif);
+	func_state.state = state;
+
+	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE,
+				 &func_state, sizeof(func_state),
+				 &func_state, &out_size);
+	if (err || (out_size != sizeof(func_state)) || func_state.status) {
+		dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
+			func_state.status);
+		return -EFAULT;
+	}
+
+	return 0;
+}
drivers/net/ethernet/huawei/hinic/hinic_port.h +19 -0
index 95fa29f..77e243b 100644
@@ -40,6 +40,11 @@ enum hinic_port_state {
 	HINIC_PORT_ENABLE       = 3,
 };
 
+enum hinic_func_port_state {
+	HINIC_FUNC_PORT_DISABLE = 0,
+	HINIC_FUNC_PORT_ENABLE  = 2,
+};
+
 struct hinic_port_mac_cmd {
 	u8              status;
 	u8              version;
@@ -109,6 +114,17 @@ struct hinic_port_link_status {
 	u8      rsvd2;
 };
 
+struct hinic_port_func_state_cmd {
+	u8      status;
+	u8      version;
+	u8      rsvd0[6];
+
+	u16     func_idx;
+	u16     rsvd1;
+	u8      state;
+	u8      rsvd2[3];
+};
+
 int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
 		       u16 vlan_id);
 
@@ -131,4 +147,7 @@ int hinic_port_link_state(struct hinic_dev *nic_dev,
 int hinic_port_set_state(struct hinic_dev *nic_dev,
 			 enum hinic_port_state state);
 
+int hinic_port_set_func_state(struct hinic_dev *nic_dev,
+			      enum hinic_func_port_state state);
+
 #endif
drivers/net/ethernet/huawei/hinic/hinic_rx.c +427 -0

459 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_rx.h +7 -0
index fbd0246..538c886 100644
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 #include <linux/netdevice.h>
 #include <linux/u64_stats_sync.h>
+#include <linux/interrupt.h>
 
 #include "hinic_hw_qp.h"
 
@@ -34,6 +35,12 @@ struct hinic_rxq {
 	struct hinic_rq         *rq;
 
 	struct hinic_rxq_stats  rxq_stats;
+
+	char                    *irq_name;
+
+	struct tasklet_struct   rx_task;
+
+	struct napi_struct      napi;
 };
 
 void hinic_rxq_clean_stats(struct hinic_rxq *rxq);
Signature · 1 line
1.9.1
#27 lore raw

PATCH v2 19/21 net-next/hinic: Add Tx operation

In reply to Aviad Krawczyk

Add transmit operation for sending data by qp operations.

---
 drivers/net/ethernet/huawei/hinic/hinic_dev.h     |   1 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c  |  47 +++
 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h  |  22 ++
 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h   |   1 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h |   2 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c   | 244 +++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h   | 197 ++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_main.c    |  12 +-
 drivers/net/ethernet/huawei/hinic/hinic_tx.c      | 419 ++++++++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_tx.h      |  11 +
 10 files changed, 954 insertions(+), 2 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_dev.h +1 -0
index 5fcde35..d798bab 100644
@@ -43,6 +43,7 @@ struct hinic_dev {
 	struct hinic_hwdev              *hwdev;
 
 	u32                             msg_enable;
+	unsigned int                    tx_weight;
 	unsigned int                    rx_weight;
 
 	unsigned int                    flags;
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +47 -0

56 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +22 -0
index 147d5b7..056a458 100644
@@ -153,6 +153,25 @@ struct hinic_cmd_base_qpn {
 	u16     qpn;
 };
 
+struct hinic_cmd_hw_ci {
+	u8      status;
+	u8      version;
+	u8      rsvd0[6];
+
+	u16     func_idx;
+
+	u8      dma_attr_off;
+	u8      pending_limit;
+	u8      coalesc_timer;
+
+	u8      msix_en;
+	u16     msix_entry_idx;
+
+	u32     sq_id;
+	u32     rsvd1;
+	u64     ci_addr;
+};
+
 struct hinic_hwdev {
 	struct hinic_hwif               *hwif;
 	struct msix_entry               *msix_entries;
@@ -214,4 +233,7 @@ int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index,
 			 u8 lli_timer_cfg, u8 lli_credit_limit,
 			 u8 resend_timer);
 
+int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq,
+			       u8 pending_limit, u8 coalesc_timer);
+
 #endif
drivers/net/ethernet/huawei/hinic/hinic_hw_io.h +1 -0
index 6f40e6a..adb6417 100644
@@ -39,6 +39,7 @@ enum hinic_db_type {
 
 enum hinic_io_path {
 	HINIC_CTRL_PATH,
+	HINIC_DATA_PATH,
 };
 
 struct hinic_free_db_area {
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h +2 -0
index 6cf5061..56e646c 100644
@@ -77,6 +77,8 @@ enum hinic_comm_cmd {
 	HINIC_COMM_CMD_HWCTXT_SET       = 0x12,
 	HINIC_COMM_CMD_HWCTXT_GET       = 0x13,
 
+	HINIC_COMM_CMD_SQ_HI_CI_SET     = 0x14,
+
 	HINIC_COMM_CMD_RES_STATE_SET    = 0x24,
 
 	HINIC_COMM_CMD_IO_RES_CLEAR     = 0x29,
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +244 -0

276 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +197 -0

229 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_main.c +10 -2
index 8aceaa0..ef40c7d 100644
@@ -43,6 +43,10 @@
 MODULE_DESCRIPTION("Huawei Intelligent NIC driver");
 MODULE_LICENSE("GPL");
 
+static unsigned int tx_weight = 64;
+module_param(tx_weight, uint, 0644);
+MODULE_PARM_DESC(tx_weight, "Number Tx packets for NAPI budget (default=64)");
+
 static unsigned int rx_weight = 64;
 module_param(rx_weight, uint, 0644);
 MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)");
@@ -568,9 +572,11 @@ static void hinic_set_rx_mode(struct net_device *netdev)
 	queue_work(nic_dev->workq, &rx_mode_work->work);
 }
 
-netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+static void hinic_tx_timeout(struct net_device *netdev)
 {
-	return NETDEV_TX_BUSY;
+	struct hinic_dev *nic_dev = netdev_priv(netdev);
+
+	netif_err(nic_dev, drv, netdev, "Tx timeout\n");
 }
 
 static const struct net_device_ops hinic_netdev_ops = {
@@ -583,6 +589,7 @@ netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 	.ndo_vlan_rx_kill_vid = hinic_vlan_rx_kill_vid,
 	.ndo_set_rx_mode = hinic_set_rx_mode,
 	.ndo_start_xmit = hinic_xmit_frame,
+	.ndo_tx_timeout = hinic_tx_timeout,
 	/* more operations should be filled */
 };
 
@@ -690,6 +697,7 @@ static int nic_dev_init(struct pci_dev *pdev)
 	nic_dev->flags = 0;
 	nic_dev->txqs = NULL;
 	nic_dev->rxqs = NULL;
+	nic_dev->tx_weight = tx_weight;
 	nic_dev->rx_weight = rx_weight;
 
 	sema_init(&nic_dev->mgmt_lock, 1);
drivers/net/ethernet/huawei/hinic/hinic_tx.c +419 -0

452 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_tx.h +11 -0
index bbdb4b6..7123c7f 100644
@@ -18,8 +18,10 @@
 
 #include <linux/types.h>
 #include <linux/netdevice.h>
+#include <linux/skbuff.h>
 #include <linux/u64_stats_sync.h>
 
+#include "hinic_common.h"
 #include "hinic_hw_qp.h"
 
 struct hinic_txq_stats {
@@ -37,10 +39,19 @@ struct hinic_txq {
 	struct hinic_sq         *sq;
 
 	struct hinic_txq_stats  txq_stats;
+
+	int                     max_sges;
+	struct hinic_sge        *sges;
+	struct hinic_sge        *free_sges;
+
+	char                    *irq_name;
+	struct napi_struct      napi;
 };
 
 void hinic_txq_clean_stats(struct hinic_txq *txq);
 
+netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+
 int hinic_init_txq(struct hinic_txq *txq, struct hinic_sq *sq,
 		   struct net_device *netdev);
 
Signature · 1 line
1.9.1
#28 lore raw

PATCH v2 20/21 net-next/hinic: Add ethtool and stats

In reply to Aviad Krawczyk

Add ethtool operations and statistics operations.

---
 drivers/net/ethernet/huawei/hinic/hinic_dev.h  |   3 +
 drivers/net/ethernet/huawei/hinic/hinic_main.c | 218 ++++++++++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_port.c |  29 ++++
 drivers/net/ethernet/huawei/hinic/hinic_port.h |  45 +++++
 drivers/net/ethernet/huawei/hinic/hinic_rx.c   |  19 +++
 drivers/net/ethernet/huawei/hinic/hinic_rx.h   |   2 +
 drivers/net/ethernet/huawei/hinic/hinic_tx.c   |  22 +++
 drivers/net/ethernet/huawei/hinic/hinic_tx.h   |   2 +
 8 files changed, 339 insertions(+), 1 deletion(-)
drivers/net/ethernet/huawei/hinic/hinic_dev.h +3 -0
index d798bab..4dc1b09 100644
@@ -56,6 +56,9 @@ struct hinic_dev {
 
 	struct hinic_txq                *txqs;
 	struct hinic_rxq                *rxqs;
+
+	struct hinic_txq_stats          tx_stats;
+	struct hinic_rxq_stats          rx_stats;
 };
 
 #endif
drivers/net/ethernet/huawei/hinic/hinic_main.c +217 -1

260 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_port.c +29 -0
index 79d75bc..a7ec2fa 100644
@@ -372,3 +372,32 @@ int hinic_port_set_func_state(struct hinic_dev *nic_dev,
 
 	return 0;
 }
+
+/**
+ * hinic_port_get_cap - get port capabilities
+ * @nic_dev: nic device
+ * @port_cap: returned port capabilities
+ *
+ * Return 0 - Success, negative - Failure
+ **/
+int hinic_port_get_cap(struct hinic_dev *nic_dev,
+		       struct hinic_port_cap *port_cap)
+{
+	struct hinic_hwdev *hwdev = nic_dev->hwdev;
+	struct hinic_hwif *hwif = hwdev->hwif;
+	struct pci_dev *pdev = hwif->pdev;
+	u16 out_size;
+	int err;
+
+	port_cap->func_idx = HINIC_HWIF_GLOB_IDX(hwif);
+
+	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP,
+				 port_cap, sizeof(*port_cap),
+				 port_cap, &out_size);
+	if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
+		dev_err(&pdev->dev, "Failed to get port capabilities\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
drivers/net/ethernet/huawei/hinic/hinic_port.h +45 -0

61 lines not on this page · raw message

drivers/net/ethernet/huawei/hinic/hinic_rx.c +19 -0
index 85bab8e..43d1814 100644
@@ -57,6 +57,25 @@ void hinic_rxq_clean_stats(struct hinic_rxq *rxq)
 }
 
 /**
+ * hinic_rxq_get_stats - get statistics of Rx Queue
+ * @rxq: Logical Rx Queue
+ * @stats: return updated stats here
+ **/
+void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats)
+{
+	struct hinic_rxq_stats *rxq_stats = &rxq->rxq_stats;
+	unsigned int start;
+
+	u64_stats_update_begin(&stats->syncp);
+	do {
+		start = u64_stats_fetch_begin(&rxq_stats->syncp);
+		stats->pkts = rxq_stats->pkts;
+		stats->bytes = rxq_stats->bytes;
+	} while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+	u64_stats_update_end(&stats->syncp);
+}
+
+/**
  * rxq_stats_init - Initialize the statistics of specific queue
  * @rxq: Logical Rx Queue
  **/
drivers/net/ethernet/huawei/hinic/hinic_rx.h +2 -0
index 538c886..27c9af4 100644
@@ -45,6 +45,8 @@ struct hinic_rxq {
 
 void hinic_rxq_clean_stats(struct hinic_rxq *rxq);
 
+void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats);
+
 int hinic_init_rxq(struct hinic_rxq *rxq, struct hinic_rq *rq,
 		   struct net_device *netdev);
 
drivers/net/ethernet/huawei/hinic/hinic_tx.c +22 -0
index a0dfaaf..8889bf4 100644
@@ -66,6 +66,28 @@ void hinic_txq_clean_stats(struct hinic_txq *txq)
 }
 
 /**
+ * hinic_txq_get_stats - get statistics of Tx Queue
+ * @txq: Logical Tx Queue
+ * @stats: return updated stats here
+ **/
+void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats)
+{
+	struct hinic_txq_stats *txq_stats = &txq->txq_stats;
+	unsigned int start;
+
+	u64_stats_update_begin(&stats->syncp);
+	do {
+		start = u64_stats_fetch_begin(&txq_stats->syncp);
+		stats->pkts = txq_stats->pkts;
+		stats->bytes = txq_stats->bytes;
+		stats->tx_busy = txq_stats->tx_busy;
+		stats->tx_wake = txq_stats->tx_wake;
+		stats->tx_dropped = txq_stats->tx_dropped;
+	} while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+	u64_stats_update_end(&stats->syncp);
+}
+
+/**
  * txq_stats_init - Initialize the statistics of specific queue
  * @txq: Logical Tx Queue
  **/
drivers/net/ethernet/huawei/hinic/hinic_tx.h +2 -0
index 7123c7f..1fa55dc 100644
@@ -50,6 +50,8 @@ struct hinic_txq {
 
 void hinic_txq_clean_stats(struct hinic_txq *txq);
 
+void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats);
+
 netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 
 int hinic_init_txq(struct hinic_txq *txq, struct hinic_sq *sq,
Signature · 1 line
1.9.1
#29 lore raw

Re: [PATCH V2 net-next 20/21] net-next/hinic: Add ethtool and stats

Quoted 1 line · Aviad Krawczyk

Add ethtool operations and statistics operations.

series trivia:

drivers/net/ethernet/huawei/hinic/hinic_main.c

Quoted 1 line
drivers/net/ethernet/huawei/hinic/hinic_main.c +0 -0

[]

drivers/net/ethernet/huawei/hinic/hinic_main.c

Quoted 1 line
drivers/net/ethernet/huawei/hinic/hinic_main.c +0 -0
@@ -67,6 +67,178 @@

[]

drivers/net/ethernet/huawei/hinic/hinic_main.c line 73

Quoted 4 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c +4 -0
+static int hinic_get_link_ksettings(struct net_device *netdev,
+				    struct ethtool_link_ksettings
+				    *link_ksettings)
+{

[]

drivers/net/ethernet/huawei/hinic/hinic_main.c line 93

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c +5 -0
+	err = hinic_port_get_cap(nic_dev, &port_cap);
+	if (err) {
+		dev_err(&netdev->dev, "Failed to get port capabilities\n");
+		return err;
+	}

it looks like a lot of these dev_<level> calls
should be converted to netdev_<level>

from:

		dev_err(&netdev->dev, ...);
to:
		netdev_err(netdev, ...);

etc...

#30 lore raw

Re: [PATCH V2 net-next 20/21] net-next/hinic: Add ethtool and stats

Hi Joe,

I tried to be consistent with the comments before, that requested that we will use dev_err exclude some special cases for use netif.

We will replace the dev_err(&netdev->dev,.. to netdev_err in the next fix.

Thanks for review,
Aviad

Quoted 33 lines · Joe Perches
Quoted 1 line · Aviad Krawczyk

Add ethtool operations and statistics operations.

series trivia:

drivers/net/ethernet/huawei/hinic/hinic_main.c

Quoted 1 line
drivers/net/ethernet/huawei/hinic/hinic_main.c +0 -0

[]

drivers/net/ethernet/huawei/hinic/hinic_main.c

Quoted 1 line
drivers/net/ethernet/huawei/hinic/hinic_main.c +0 -0
@@ -67,6 +67,178 @@

[]

drivers/net/ethernet/huawei/hinic/hinic_main.c line 73

Quoted 4 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c +4 -0
+static int hinic_get_link_ksettings(struct net_device *netdev,
+				    struct ethtool_link_ksettings
+				    *link_ksettings)
+{

[]

drivers/net/ethernet/huawei/hinic/hinic_main.c line 93

Quoted 5 lines
drivers/net/ethernet/huawei/hinic/hinic_main.c +5 -0
+	err = hinic_port_get_cap(nic_dev, &port_cap);
+	if (err) {
+		dev_err(&netdev->dev, "Failed to get port capabilities\n");
+		return err;
+	}

it looks like a lot of these dev_<level> calls
should be converted to netdev_<level>

from:

		dev_err(&netdev->dev, ...);
to:
		netdev_err(netdev, ...);

etc...

.

#31 lore raw

Re: [PATCH V2 net-next 20/21] net-next/hinic: Add ethtool and stats

Quoted 7 lines · Aviad Krawczyk

Hi Joe,

I tried to be consistent with the comments before, that requested that we will use dev_err exclude some special cases for use netif.

We will replace the dev_err(&netdev->dev,.. to netdev_err in the next fix.

netdev_err() should be used when possible. You just have to be careful in the probe() function, before netdev exists and you get "(NULL net_device):" or before it is registered and you get "(unnamed net_device)" instead of "eth42" etc.

Andrew

#32 lore raw

Re: [PATCH V2 net-next 20/21] net-next/hinic: Add ethtool and stats

Hi,

I saw that netif_err is more common in code, is it preferred on netdev_err? What is the preferred style, netif_ or netdev_?

Best Regards,
Aviad

Quoted 18 lines · Andrew Lunn
Quoted 7 lines · Aviad Krawczyk

Hi Joe,

I tried to be consistent with the comments before, that requested that we will use dev_err exclude some special cases for use netif.

We will replace the dev_err(&netdev->dev,.. to netdev_err in the next fix.

netdev_err() should be used when possible. You just have to be careful in the probe() function, before netdev exists and you get "(NULL net_device):" or before it is registered and you get "(unnamed net_device)" instead of "eth42" etc.

Andrew

.

#33 lore raw

PATCH v2 21/21 net-next/hinic: Add select_queue and netpoll

In reply to Aviad Krawczyk

Add more netdev operations.

---
 MAINTAINERS                                    |  7 ++++++
 drivers/net/ethernet/huawei/hinic/hinic_main.c | 35 ++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)
MAINTAINERS +7 -0
index 1347726..5c85602 100644
@@ -6269,6 +6269,13 @@ L:	[email protected]
 S:	Maintained
 F:	drivers/input/touchscreen/htcpen.c
 
+HUAWEI ETHERNET DRIVER
+M:	Aviad Krawczyk <[email protected]>
+L:	[email protected]
+S:	Supported
+F:	Documentation/networking/hinic.txt
+F:	drivers/net/ethernet/huawei/*
+
 HUGETLB FILESYSTEM
 M:	Nadia Yvette Chambers <[email protected]>
 S:	Maintained
drivers/net/ethernet/huawei/hinic/hinic_main.c +35 -0
index d0f8b9e..9e464cf 100644
@@ -786,6 +786,37 @@ static void hinic_get_stats64(struct net_device *netdev,
 	stats->tx_errors = nic_tx_stats->tx_dropped;
 }
 
+static u16 hinic_select_queue(struct net_device *netdev, struct sk_buff *skb,
+			      void *accel_priv,
+			      select_queue_fallback_t fallback)
+{
+	u16 qid;
+
+	if (skb_rx_queue_recorded(skb))
+		qid = skb_get_rx_queue(skb);
+	else
+		qid = fallback(netdev, skb);
+
+	return qid;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void hinic_netpoll(struct net_device *netdev)
+{
+	struct hinic_dev *nic_dev = netdev_priv(netdev);
+	struct hinic_hwdev *hwdev = nic_dev->hwdev;
+	int i, num_qps = hinic_hwdev_num_qps(hwdev);
+
+	for (i = 0; i < num_qps; i++) {
+		struct hinic_txq *txq = &nic_dev->txqs[i];
+		struct hinic_rxq *rxq = &nic_dev->rxqs[i];
+
+		napi_schedule(&txq->napi);
+		napi_schedule(&rxq->napi);
+	}
+}
+#endif
+
 static const struct net_device_ops hinic_netdev_ops = {
 	.ndo_open = hinic_open,
 	.ndo_stop = hinic_close,
@@ -798,6 +829,10 @@ static void hinic_get_stats64(struct net_device *netdev,
 	.ndo_start_xmit = hinic_xmit_frame,
 	.ndo_tx_timeout = hinic_tx_timeout,
 	.ndo_get_stats64 = hinic_get_stats64,
+	.ndo_select_queue = hinic_select_queue,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller = hinic_netpoll,
+#endif
 };
 
 static void netdev_features_init(struct net_device *netdev)
Signature · 1 line
1.9.1
#34 lore raw

Re: [PATCH V2 net-next 21/21] net-next/hinic: Add select_queue and netpoll

Quoted 14 lines · Aviad Krawczyk

Add more netdev operations.

---
  MAINTAINERS                                    |  7 ++++++
  drivers/net/ethernet/huawei/hinic/hinic_main.c | 35 ++++++++++++++++++++++++++
  2 files changed, 42 insertions(+)
MAINTAINERS +0 -0
index 1347726..5c85602 100644

MAINTAINERS L: [email protected] · line 6277

Quoted 9 lines
MAINTAINERS +6 -0
@@ -6269,6 +6269,13 @@ L:	[email protected]
  S:	Maintained
  F:	drivers/input/touchscreen/htcpen.c
 
+HUAWEI ETHERNET DRIVER
+M:	Aviad Krawczyk <[email protected]>
+L:	[email protected]
+S:	Supported
+F:	Documentation/networking/hinic.txt
+F:	drivers/net/ethernet/huawei/*

This means that subdirs there are not maintained, did you really mean it?

[...]

MNR, Sergei

#35 lore raw

Re: [PATCH V2 net-next 21/21] net-next/hinic: Add select_queue and netpoll

Hi Sergei,

I meant that drivers/net/ethernet/huawei/* is all the dir under huawei dir. (I saw this style of '*' is used in the maintainers file)
I will change it to drivers/net/ethernet/huawei/hinic/ in the next fix.

Thanks for review,
Aviad

Quoted 33 lines · Sergei Shtylyov
Quoted 14 lines · Aviad Krawczyk

Add more netdev operations.

---
  MAINTAINERS                                    |  7 ++++++
  drivers/net/ethernet/huawei/hinic/hinic_main.c | 35 ++++++++++++++++++++++++++
  2 files changed, 42 insertions(+)
MAINTAINERS +0 -0
index 1347726..5c85602 100644

MAINTAINERS L: [email protected] · line 6276

Quoted 8 lines
MAINTAINERS +5 -0
@@ -6269,6 +6269,13 @@ L:    [email protected]
  S:    Maintained
  F:    drivers/input/touchscreen/htcpen.c
  +HUAWEI ETHERNET DRIVER
+M:    Aviad Krawczyk <[email protected]>
+L:    [email protected]
+S:    Supported
+F:    Documentation/networking/hinic.txt
+F:    drivers/net/ethernet/huawei/*

This means that subdirs there are not maintained, did you really mean it?

[...]

MNR, Sergei

.