Commit 06552f8e authored by David S. Miller's avatar David S. Miller

Merge branch 'Huawei-HiNIC-Ethernet-Driver'

Aviad Krawczyk says:

====================
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 V7 -> V8:
1. Remove unnecessary cast from void * - Stephen Hemminger comment
	https://lkml.org/lkml/2017/8/17/1008

Changes V6 -> V7:
1. Separate netpoll and MAINTAINERS patch - Sergei Shtylyov comment
	https://lkml.org/lkml/2017/8/17/479

Changes V5 -> V6:
1. Fix cover letter Message-Id

Changes V4 -> V5:
1. Remove select_queue NOP - David Miller comment
        https://lkml.org/lkml/2017/8/16/625

Changes V3 -> V4:
1. Reverse christmas tree order - David Miller comment
        https://lkml.org/lkml/2017/8/3/862

Changes V2 -> V3:
1. Replace dev_ functions by netif_ functions - Joe Perches comment
        https://lkml.org/lkml/2017/7/19/424
2. Fix the driver directory in MAINTAINERS file - Sergei Shtylyov comment
        https://lkml.org/lkml/2017/7/19/615
3. Add a newline at the end of Makefile - David Miller comment
        https://lkml.org/lkml/2017/7/19/1345
4. Return a pointer as a val instead of in arg - Francois Romieu comment
        https://lkml.org/lkml/2017/7/19/1319
5. Change the error labels to err_xyz - Francois Romieu comment
        https://lkml.org/lkml/2017/7/19/1319
6. Remove check of Func Type in free function - Francois Romieu comment
        https://lkml.org/lkml/2017/7/19/1319
7. Remove !netdev check in remove function - Francois Romieu comment
        https://lkml.org/lkml/2017/7/19/1319
8. Use module_pci_driver - Francois Romieu comment
        https://lkml.org/lkml/2017/7/19/1319
9. Move the PCI device ID to the .c file - Francois Romieu comment
        https://lkml.org/lkml/2017/7/19/1319
10. Remove void * to avoid passing wrong ptr - Francois Romieu comment
        https://lkml.org/lkml/2017/7/19/1319

Changes V1 -> V2:
1. remove driver verstion - 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
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 89c9c163 4d3b6327
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
aviad.krawczyk@huawei.com.
......@@ -6240,6 +6240,13 @@ L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/touchscreen/htcpen.c
HUAWEI ETHERNET DRIVER
M: Aviad Krawczyk <aviad.krawczyk@huawei.com>
L: netdev@vger.kernel.org
S: Supported
F: Documentation/networking/hinic.txt
F: drivers/net/ethernet/huawei/hinic/
HUGETLB FILESYSTEM
M: Nadia Yvette Chambers <nyc@holomorphy.com>
S: Maintained
......
......@@ -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"
......
......@@ -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/
......
#
# 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
#
# Makefile for the Huawei device drivers.
#
obj-$(CONFIG_HINIC) += hinic/
#
# 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.
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_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
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/byteorder.h>
#include "hinic_common.h"
/**
* hinic_cpu_to_be32 - convert data to big endian 32 bit format
* @data: the data to convert
* @len: length of data to convert
**/
void hinic_cpu_to_be32(void *data, int len)
{
u32 *mem = data;
int i;
len = len / sizeof(u32);
for (i = 0; i < len; i++) {
*mem = cpu_to_be32(*mem);
mem++;
}
}
/**
* hinic_be32_to_cpu - convert data from big endian 32 bit format
* @data: the data to convert
* @len: length of data to convert
**/
void hinic_be32_to_cpu(void *data, int len)
{
u32 *mem = data;
int i;
len = len / sizeof(u32);
for (i = 0; i < len; i++) {
*mem = be32_to_cpu(*mem);
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);
}
/*
* 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
#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
/*
* 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 <linux/semaphore.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include "hinic_hw_dev.h"
#include "hinic_tx.h"
#include "hinic_rx.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 tx_weight;
unsigned int rx_weight;
unsigned int flags;
struct semaphore mgmt_lock;
unsigned long *vlan_bitmap;
struct hinic_rx_mode_work rx_mode_work;
struct workqueue_struct *workq;
struct hinic_txq *txqs;
struct hinic_rxq *rxqs;
struct hinic_txq_stats tx_stats;
struct hinic_rxq_stats rx_stats;
};
#endif
This diff is collapsed.
/*
* 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_API_CMD_H
#define HINIC_HW_API_CMD_H
#include <linux/types.h>
#include <linux/semaphore.h>
#include "hinic_hw_if.h"
#define HINIC_API_CMD_PI_IDX_SHIFT 0
#define HINIC_API_CMD_PI_IDX_MASK 0xFFFFFF
#define HINIC_API_CMD_PI_SET(val, member) \
(((u32)(val) & HINIC_API_CMD_PI_##member##_MASK) << \
HINIC_API_CMD_PI_##member##_SHIFT)
#define HINIC_API_CMD_PI_CLEAR(val, member) \
((val) & (~(HINIC_API_CMD_PI_##member##_MASK \
<< HINIC_API_CMD_PI_##member##_SHIFT)))
#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)))
#define HINIC_API_CMD_CELL_CTRL_DATA_SZ_SHIFT 0
#define HINIC_API_CMD_CELL_CTRL_RD_DMA_ATTR_SHIFT 16
#define HINIC_API_CMD_CELL_CTRL_WR_DMA_ATTR_SHIFT 24
#define HINIC_API_CMD_CELL_CTRL_XOR_CHKSUM_SHIFT 56
#define HINIC_API_CMD_CELL_CTRL_DATA_SZ_MASK 0x3F
#define HINIC_API_CMD_CELL_CTRL_RD_DMA_ATTR_MASK 0x3F
#define HINIC_API_CMD_CELL_CTRL_WR_DMA_ATTR_MASK 0x3F
#define HINIC_API_CMD_CELL_CTRL_XOR_CHKSUM_MASK 0xFF
#define HINIC_API_CMD_CELL_CTRL_SET(val, member) \
((((u64)val) & HINIC_API_CMD_CELL_CTRL_##member##_MASK) << \
HINIC_API_CMD_CELL_CTRL_##member##_SHIFT)
#define HINIC_API_CMD_DESC_API_TYPE_SHIFT 0
#define HINIC_API_CMD_DESC_RD_WR_SHIFT 1
#define HINIC_API_CMD_DESC_MGMT_BYPASS_SHIFT 2
#define HINIC_API_CMD_DESC_DEST_SHIFT 32
#define HINIC_API_CMD_DESC_SIZE_SHIFT 40
#define HINIC_API_CMD_DESC_XOR_CHKSUM_SHIFT 56
#define HINIC_API_CMD_DESC_API_TYPE_MASK 0x1
#define HINIC_API_CMD_DESC_RD_WR_MASK 0x1
#define HINIC_API_CMD_DESC_MGMT_BYPASS_MASK 0x1
#define HINIC_API_CMD_DESC_DEST_MASK 0x1F
#define HINIC_API_CMD_DESC_SIZE_MASK 0x7FF
#define HINIC_API_CMD_DESC_XOR_CHKSUM_MASK 0xFF
#define HINIC_API_CMD_DESC_SET(val, member) \
((((u64)val) & HINIC_API_CMD_DESC_##member##_MASK) << \
HINIC_API_CMD_DESC_##member##_SHIFT)
#define HINIC_API_CMD_STATUS_HEADER_CHAIN_ID_SHIFT 16
#define HINIC_API_CMD_STATUS_HEADER_CHAIN_ID_MASK 0xFF
#define HINIC_API_CMD_STATUS_HEADER_GET(val, member) \
(((val) >> HINIC_API_CMD_STATUS_HEADER_##member##_SHIFT) & \
HINIC_API_CMD_STATUS_HEADER_##member##_MASK)
#define HINIC_API_CMD_STATUS_CONS_IDX_SHIFT 0
#define HINIC_API_CMD_STATUS_CHKSUM_ERR_SHIFT 28
#define HINIC_API_CMD_STATUS_CONS_IDX_MASK 0xFFFFFF
#define HINIC_API_CMD_STATUS_CHKSUM_ERR_MASK 0x3
#define HINIC_API_CMD_STATUS_GET(val, member) \
(((val) >> HINIC_API_CMD_STATUS_##member##_SHIFT) & \
HINIC_API_CMD_STATUS_##member##_MASK)
enum hinic_api_cmd_chain_type {
HINIC_API_CMD_WRITE_TO_MGMT_CPU = 2,
HINIC_API_CMD_MAX,
};
struct hinic_api_cmd_chain_attr {
struct hinic_hwif *hwif;
enum hinic_api_cmd_chain_type chain_type;
u32 num_cells;
u16 cell_size;
};
struct hinic_api_cmd_status {
u64 header;
u32 status;
u32 rsvd0;
u32 rsvd1;
u32 rsvd2;
u64 rsvd3;
};
/* HW struct */
struct hinic_api_cmd_cell {
u64 ctrl;
/* address is 64 bit in HW struct */
u64 next_cell_paddr;
u64 desc;
/* HW struct */
union {
struct {
u64 hw_cmd_paddr;
} write;
struct {
u64 hw_wb_resp_paddr;
u64 hw_cmd_paddr;
} read;
};
};
struct hinic_api_cmd_cell_ctxt {
dma_addr_t cell_paddr;
struct hinic_api_cmd_cell *cell_vaddr;
dma_addr_t api_cmd_paddr;
u8 *api_cmd_vaddr;
};
struct hinic_api_cmd_chain {
struct hinic_hwif *hwif;
enum hinic_api_cmd_chain_type chain_type;
u32 num_cells;
u16 cell_size;
/* HW members in 24 bit format */
u32 prod_idx;
u32 cons_idx;
struct semaphore sem;
struct hinic_api_cmd_cell_ctxt *cell_ctxt;
dma_addr_t wb_status_paddr;
struct hinic_api_cmd_status *wb_status;
dma_addr_t head_cell_paddr;
struct hinic_api_cmd_cell *head_node;
struct hinic_api_cmd_cell *curr_node;
};
int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain,
enum hinic_node_id dest, u8 *cmd, u16 size);
int hinic_api_cmd_init(struct hinic_api_cmd_chain **chain,
struct hinic_hwif *hwif);
void hinic_api_cmd_free(struct hinic_api_cmd_chain **chain);
#endif
This diff is collapsed.
/*
* 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_CMDQ_H
#define HINIC_CMDQ_H
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/pci.h>
#include "hinic_hw_if.h"
#include "hinic_hw_wq.h"
#define HINIC_CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT 0
#define HINIC_CMDQ_CTXT_EQ_ID_SHIFT 56
#define HINIC_CMDQ_CTXT_CEQ_ARM_SHIFT 61
#define HINIC_CMDQ_CTXT_CEQ_EN_SHIFT 62
#define HINIC_CMDQ_CTXT_WRAPPED_SHIFT 63
#define HINIC_CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK 0xFFFFFFFFFFFFF
#define HINIC_CMDQ_CTXT_EQ_ID_MASK 0x1F
#define HINIC_CMDQ_CTXT_CEQ_ARM_MASK 0x1
#define HINIC_CMDQ_CTXT_CEQ_EN_MASK 0x1
#define HINIC_CMDQ_CTXT_WRAPPED_MASK 0x1
#define HINIC_CMDQ_CTXT_PAGE_INFO_SET(val, member) \
(((u64)(val) & HINIC_CMDQ_CTXT_##member##_MASK) \
<< HINIC_CMDQ_CTXT_##member##_SHIFT)
#define HINIC_CMDQ_CTXT_PAGE_INFO_CLEAR(val, member) \
((val) & (~((u64)HINIC_CMDQ_CTXT_##member##_MASK \
<< HINIC_CMDQ_CTXT_##member##_SHIFT)))
#define HINIC_CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT 0
#define HINIC_CMDQ_CTXT_CI_SHIFT 52
#define HINIC_CMDQ_CTXT_WQ_BLOCK_PFN_MASK 0xFFFFFFFFFFFFF
#define HINIC_CMDQ_CTXT_CI_MASK 0xFFF
#define HINIC_CMDQ_CTXT_BLOCK_INFO_SET(val, member) \
(((u64)(val) & HINIC_CMDQ_CTXT_##member##_MASK) \
<< HINIC_CMDQ_CTXT_##member##_SHIFT)
#define HINIC_CMDQ_CTXT_BLOCK_INFO_CLEAR(val, member) \
((val) & (~((u64)HINIC_CMDQ_CTXT_##member##_MASK \
<< HINIC_CMDQ_CTXT_##member##_SHIFT)))
#define HINIC_SAVED_DATA_ARM_SHIFT 31
#define HINIC_SAVED_DATA_ARM_MASK 0x1
#define HINIC_SAVED_DATA_SET(val, member) \
(((u32)(val) & HINIC_SAVED_DATA_##member##_MASK) \
<< HINIC_SAVED_DATA_##member##_SHIFT)
#define HINIC_SAVED_DATA_GET(val, member) \
(((val) >> HINIC_SAVED_DATA_##member##_SHIFT) \
& HINIC_SAVED_DATA_##member##_MASK)
#define HINIC_SAVED_DATA_CLEAR(val, member) \
((val) & (~(HINIC_SAVED_DATA_##member##_MASK \
<< HINIC_SAVED_DATA_##member##_SHIFT)))
#define HINIC_CMDQ_DB_INFO_HI_PROD_IDX_SHIFT 0
#define HINIC_CMDQ_DB_INFO_PATH_SHIFT 23
#define HINIC_CMDQ_DB_INFO_CMDQ_TYPE_SHIFT 24
#define HINIC_CMDQ_DB_INFO_DB_TYPE_SHIFT 27
#define HINIC_CMDQ_DB_INFO_HI_PROD_IDX_MASK 0xFF
#define HINIC_CMDQ_DB_INFO_PATH_MASK 0x1
#define HINIC_CMDQ_DB_INFO_CMDQ_TYPE_MASK 0x7
#define HINIC_CMDQ_DB_INFO_DB_TYPE_MASK 0x1F
#define HINIC_CMDQ_DB_INFO_SET(val, member) \
(((u32)(val) & HINIC_CMDQ_DB_INFO_##member##_MASK) \
<< HINIC_CMDQ_DB_INFO_##member##_SHIFT)
#define HINIC_CMDQ_BUF_SIZE 2048
#define HINIC_CMDQ_BUF_HW_RSVD 8
#define HINIC_CMDQ_MAX_DATA_SIZE (HINIC_CMDQ_BUF_SIZE - \
HINIC_CMDQ_BUF_HW_RSVD)
enum hinic_cmdq_type {
HINIC_CMDQ_SYNC,
HINIC_MAX_CMDQ_TYPES,
};
enum hinic_set_arm_qtype {
HINIC_SET_ARM_CMDQ,
};
enum hinic_cmd_ack_type {
HINIC_CMD_ACK_TYPE_CMDQ,
};
struct hinic_cmdq_buf {
void *buf;
dma_addr_t dma_addr;
size_t size;
};
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;
};
struct hinic_cmdq_ctxt {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
u8 cmdq_type;
u8 rsvd1[1];
u8 rsvd2[4];
struct hinic_cmdq_ctxt_info ctxt_info;
};
struct hinic_cmdq {
struct hinic_wq *wq;
enum hinic_cmdq_type cmdq_type;
int wrapped;
/* Lock for keeping the doorbell order */
spinlock_t cmdq_lock;
struct completion **done;
int **errcode;
/* doorbell area */
void __iomem *db_base;
};
struct hinic_cmdqs {
struct hinic_hwif *hwif;
struct pci_pool *cmdq_buf_pool;
struct hinic_wq *saved_wqs;
struct hinic_cmdq_pages cmdq_pages;
struct hinic_cmdq cmdq[HINIC_MAX_CMDQ_TYPES];
};
int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs,
struct hinic_cmdq_buf *cmdq_buf);
void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs,
struct hinic_cmdq_buf *cmdq_buf);
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);
void hinic_free_cmdqs(struct hinic_cmdqs *cmdqs);
#endif
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#ifndef HINIC_HW_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_CSR_FUNC_ATTR4_ADDR 0x10
#define HINIC_CSR_FUNC_ATTR5_ADDR 0x14
#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)
/* 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_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)
/* 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_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) \
(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)
#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
This diff is collapsed.
/*
* 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_DEV_H
#define HINIC_HW_DEV_H
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/bitops.h>
#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
#define HINIC_MGMT_NUM_MSG_CMD (HINIC_MGMT_MSG_CMD_MAX - \
HINIC_MGMT_MSG_CMD_BASE)
struct hinic_cap {
u16 max_qps;
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,
};
enum hinic_mgmt_msg_cmd {
HINIC_MGMT_MSG_CMD_BASE = 160,
HINIC_MGMT_MSG_CMD_LINK_STATUS = 160,
HINIC_MGMT_MSG_CMD_MAX,
};
enum hinic_cb_state {
HINIC_CB_ENABLED = BIT(0),
HINIC_CB_RUNNING = BIT(1),
};
enum hinic_res_state {
HINIC_RES_CLEAN = 0,
HINIC_RES_ACTIVE = 1,
};
struct hinic_cmd_fw_ctxt {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
u16 rx_buf_sz;
u32 rsvd1;
};
struct hinic_cmd_hw_ioctxt {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
u16 rsvd1;
u8 set_cmdq_depth;
u8 cmdq_depth;
u8 rsvd2;
u8 rsvd3;
u8 rsvd4;
u8 rsvd5;
u16 rq_depth;
u16 rx_buf_sz_idx;
u16 sq_depth;
};
struct hinic_cmd_io_status {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
u8 rsvd1;
u8 rsvd2;
u32 io_status;
};
struct hinic_cmd_clear_io_res {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
u8 rsvd1;
u8 rsvd2;
};
struct hinic_cmd_set_res_state {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
u8 state;
u8 rsvd1;
u32 rsvd2;
};
struct hinic_cmd_base_qpn {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
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;
struct hinic_aeqs aeqs;
struct hinic_func_to_io func_to_io;
struct hinic_cap nic_cap;
};
struct hinic_nic_cb {
void (*handler)(void *handle, void *buf_in,
u16 in_size, void *buf_out,
u16 *out_size);
void *handle;
unsigned long cb_state;
};
struct hinic_pfhwdev {
struct hinic_hwdev hwdev;
struct hinic_pf_to_mgmt pf_to_mgmt;
struct hinic_nic_cb nic_cb[HINIC_MGMT_NUM_MSG_CMD];
};
void hinic_hwdev_cb_register(struct hinic_hwdev *hwdev,
enum hinic_mgmt_msg_cmd cmd, void *handle,
void (*handler)(void *handle, void *buf_in,
u16 in_size, void *buf_out,
u16 *out_size));
void hinic_hwdev_cb_unregister(struct hinic_hwdev *hwdev,
enum hinic_mgmt_msg_cmd cmd);
int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
void *buf_in, u16 in_size, void *buf_out,
u16 *out_size);
int hinic_hwdev_ifup(struct hinic_hwdev *hwdev);
void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev);
struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev);
void hinic_free_hwdev(struct hinic_hwdev *hwdev);
int hinic_hwdev_num_qps(struct hinic_hwdev *hwdev);
struct hinic_sq *hinic_hwdev_get_sq(struct hinic_hwdev *hwdev, int i);
struct hinic_rq *hinic_hwdev_get_rq(struct hinic_hwdev *hwdev, int i);
int hinic_hwdev_msix_cnt_set(struct hinic_hwdev *hwdev, u16 msix_index);
int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index,
u8 pending_limit, u8 coalesc_timer,
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
This diff is collapsed.
/*
* 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_EQS_H
#define HINIC_HW_EQS_H
#include <linux/types.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/sizes.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include "hinic_hw_if.h"
#define HINIC_AEQ_CTRL_0_INT_IDX_SHIFT 0
#define HINIC_AEQ_CTRL_0_DMA_ATTR_SHIFT 12
#define HINIC_AEQ_CTRL_0_PCI_INTF_IDX_SHIFT 20
#define HINIC_AEQ_CTRL_0_INT_MODE_SHIFT 31
#define HINIC_AEQ_CTRL_0_INT_IDX_MASK 0x3FF
#define HINIC_AEQ_CTRL_0_DMA_ATTR_MASK 0x3F
#define HINIC_AEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3
#define HINIC_AEQ_CTRL_0_INT_MODE_MASK 0x1
#define HINIC_AEQ_CTRL_0_SET(val, member) \
(((u32)(val) & HINIC_AEQ_CTRL_0_##member##_MASK) << \
HINIC_AEQ_CTRL_0_##member##_SHIFT)
#define HINIC_AEQ_CTRL_0_CLEAR(val, member) \
((val) & (~(HINIC_AEQ_CTRL_0_##member##_MASK \
<< HINIC_AEQ_CTRL_0_##member##_SHIFT)))
#define HINIC_AEQ_CTRL_1_LEN_SHIFT 0
#define HINIC_AEQ_CTRL_1_ELEM_SIZE_SHIFT 24
#define HINIC_AEQ_CTRL_1_PAGE_SIZE_SHIFT 28
#define HINIC_AEQ_CTRL_1_LEN_MASK 0x1FFFFF
#define HINIC_AEQ_CTRL_1_ELEM_SIZE_MASK 0x3
#define HINIC_AEQ_CTRL_1_PAGE_SIZE_MASK 0xF
#define HINIC_AEQ_CTRL_1_SET(val, member) \
(((u32)(val) & HINIC_AEQ_CTRL_1_##member##_MASK) << \
HINIC_AEQ_CTRL_1_##member##_SHIFT)
#define HINIC_AEQ_CTRL_1_CLEAR(val, member) \
((val) & (~(HINIC_AEQ_CTRL_1_##member##_MASK \
<< HINIC_AEQ_CTRL_1_##member##_SHIFT)))
#define HINIC_CEQ_CTRL_0_INTR_IDX_SHIFT 0
#define HINIC_CEQ_CTRL_0_DMA_ATTR_SHIFT 12
#define HINIC_CEQ_CTRL_0_KICK_THRESH_SHIFT 20
#define HINIC_CEQ_CTRL_0_PCI_INTF_IDX_SHIFT 24
#define HINIC_CEQ_CTRL_0_INTR_MODE_SHIFT 31
#define HINIC_CEQ_CTRL_0_INTR_IDX_MASK 0x3FF
#define HINIC_CEQ_CTRL_0_DMA_ATTR_MASK 0x3F
#define HINIC_CEQ_CTRL_0_KICK_THRESH_MASK 0xF
#define HINIC_CEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3
#define HINIC_CEQ_CTRL_0_INTR_MODE_MASK 0x1
#define HINIC_CEQ_CTRL_0_SET(val, member) \
(((u32)(val) & HINIC_CEQ_CTRL_0_##member##_MASK) << \
HINIC_CEQ_CTRL_0_##member##_SHIFT)
#define HINIC_CEQ_CTRL_0_CLEAR(val, member) \
((val) & (~(HINIC_CEQ_CTRL_0_##member##_MASK \
<< HINIC_CEQ_CTRL_0_##member##_SHIFT)))
#define HINIC_CEQ_CTRL_1_LEN_SHIFT 0
#define HINIC_CEQ_CTRL_1_PAGE_SIZE_SHIFT 28
#define HINIC_CEQ_CTRL_1_LEN_MASK 0x1FFFFF
#define HINIC_CEQ_CTRL_1_PAGE_SIZE_MASK 0xF
#define HINIC_CEQ_CTRL_1_SET(val, member) \
(((u32)(val) & HINIC_CEQ_CTRL_1_##member##_MASK) << \
HINIC_CEQ_CTRL_1_##member##_SHIFT)
#define HINIC_CEQ_CTRL_1_CLEAR(val, member) \
((val) & (~(HINIC_CEQ_CTRL_1_##member##_MASK \
<< HINIC_CEQ_CTRL_1_##member##_SHIFT)))
#define HINIC_EQ_ELEM_DESC_TYPE_SHIFT 0
#define HINIC_EQ_ELEM_DESC_SRC_SHIFT 7
#define HINIC_EQ_ELEM_DESC_SIZE_SHIFT 8
#define HINIC_EQ_ELEM_DESC_WRAPPED_SHIFT 31
#define HINIC_EQ_ELEM_DESC_TYPE_MASK 0x7F
#define HINIC_EQ_ELEM_DESC_SRC_MASK 0x1
#define HINIC_EQ_ELEM_DESC_SIZE_MASK 0xFF
#define HINIC_EQ_ELEM_DESC_WRAPPED_MASK 0x1
#define HINIC_EQ_ELEM_DESC_SET(val, member) \
(((u32)(val) & HINIC_EQ_ELEM_DESC_##member##_MASK) << \
HINIC_EQ_ELEM_DESC_##member##_SHIFT)
#define HINIC_EQ_ELEM_DESC_GET(val, member) \
(((val) >> HINIC_EQ_ELEM_DESC_##member##_SHIFT) & \
HINIC_EQ_ELEM_DESC_##member##_MASK)
#define HINIC_EQ_CI_IDX_SHIFT 0
#define HINIC_EQ_CI_WRAPPED_SHIFT 20
#define HINIC_EQ_CI_XOR_CHKSUM_SHIFT 24
#define HINIC_EQ_CI_INT_ARMED_SHIFT 31
#define HINIC_EQ_CI_IDX_MASK 0xFFFFF
#define HINIC_EQ_CI_WRAPPED_MASK 0x1
#define HINIC_EQ_CI_XOR_CHKSUM_MASK 0xF
#define HINIC_EQ_CI_INT_ARMED_MASK 0x1
#define HINIC_EQ_CI_SET(val, member) \
(((u32)(val) & HINIC_EQ_CI_##member##_MASK) << \
HINIC_EQ_CI_##member##_SHIFT)
#define HINIC_EQ_CI_CLEAR(val, member) \
((val) & (~(HINIC_EQ_CI_##member##_MASK \
<< HINIC_EQ_CI_##member##_SHIFT)))
#define HINIC_MAX_AEQS 4
#define HINIC_MAX_CEQS 32
#define HINIC_AEQE_SIZE 64
#define HINIC_CEQE_SIZE 4
#define HINIC_AEQE_DESC_SIZE 4
#define HINIC_AEQE_DATA_SIZE \
(HINIC_AEQE_SIZE - HINIC_AEQE_DESC_SIZE)
#define HINIC_DEFAULT_AEQ_LEN 64
#define HINIC_DEFAULT_CEQ_LEN 1024
#define HINIC_EQ_PAGE_SIZE SZ_4K
#define HINIC_CEQ_ID_CMDQ 0
enum hinic_eq_type {
HINIC_AEQ,
HINIC_CEQ,
};
enum hinic_aeq_type {
HINIC_MSG_FROM_MGMT_CPU = 2,
HINIC_MAX_AEQ_EVENTS,
};
enum hinic_ceq_type {
HINIC_CEQ_CMDQ = 3,
HINIC_MAX_CEQ_EVENTS,
};
enum hinic_eqe_state {
HINIC_EQE_ENABLED = BIT(0),
HINIC_EQE_RUNNING = BIT(1),
};
struct hinic_aeq_elem {
u8 data[HINIC_AEQE_DATA_SIZE];
u32 desc;
};
struct hinic_eq_work {
struct work_struct work;
void *data;
};
struct hinic_eq {
struct hinic_hwif *hwif;
enum hinic_eq_type type;
int q_id;
u32 q_len;
u32 page_size;
u32 cons_idx;
int wrapped;
size_t elem_size;
int num_pages;
int num_elem_in_pg;
struct msix_entry msix_entry;
dma_addr_t *dma_addr;
void **virt_addr;
struct hinic_eq_work aeq_work;
struct tasklet_struct ceq_tasklet;
};
struct hinic_hw_event_cb {
void (*hwe_handler)(void *handle, void *data, u8 size);
void *handle;
unsigned long hwe_state;
};
struct hinic_aeqs {
struct hinic_hwif *hwif;
struct hinic_eq aeq[HINIC_MAX_AEQS];
int num_aeqs;
struct hinic_hw_event_cb hwe_cb[HINIC_MAX_AEQ_EVENTS];
struct workqueue_struct *workq;
};
struct hinic_ceq_cb {
void (*handler)(void *handle, u32 ceqe_data);
void *handle;
enum hinic_eqe_state ceqe_state;
};
struct hinic_ceqs {
struct hinic_hwif *hwif;
struct hinic_eq ceq[HINIC_MAX_CEQS];
int num_ceqs;
struct hinic_ceq_cb ceq_cb[HINIC_MAX_CEQ_EVENTS];
};
void hinic_aeq_register_hw_cb(struct hinic_aeqs *aeqs,
enum hinic_aeq_type event, void *handle,
void (*hwe_handler)(void *handle, void *data,
u8 size));
void hinic_aeq_unregister_hw_cb(struct hinic_aeqs *aeqs,
enum hinic_aeq_type event);
void hinic_ceq_register_cb(struct hinic_ceqs *ceqs,
enum hinic_ceq_type event, void *handle,
void (*ceq_cb)(void *handle, u32 ceqe_data));
void hinic_ceq_unregister_cb(struct hinic_ceqs *ceqs,
enum hinic_ceq_type event);
int hinic_aeqs_init(struct hinic_aeqs *aeqs, struct hinic_hwif *hwif,
int num_aeqs, u32 q_len, u32 page_size,
struct msix_entry *msix_entries);
void hinic_aeqs_free(struct hinic_aeqs *aeqs);
int hinic_ceqs_init(struct hinic_ceqs *ceqs, struct hinic_hwif *hwif,
int num_ceqs, u32 q_len, u32 page_size,
struct msix_entry *msix_entries);
void hinic_ceqs_free(struct hinic_ceqs *ceqs);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#ifndef HINIC_HW_IO_H
#define HINIC_HW_IO_H
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/semaphore.h>
#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"
#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)
enum hinic_db_type {
HINIC_DB_CMDQ_TYPE,
HINIC_DB_SQ_TYPE,
};
enum hinic_io_path {
HINIC_CTRL_PATH,
HINIC_DATA_PATH,
};
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;
struct hinic_ceqs ceqs;
struct hinic_wqs wqs;
struct hinic_wq *sq_wq;
struct hinic_wq *rq_wq;
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;
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,
u16 base_qpn, int num_qps,
struct msix_entry *sq_msix_entries,
struct msix_entry *rq_msix_entries);
void hinic_io_destroy_qps(struct hinic_func_to_io *func_to_io,
int num_qps);
int hinic_io_init(struct hinic_func_to_io *func_to_io,
struct hinic_hwif *hwif, u16 max_qps, int num_ceqs,
struct msix_entry *ceq_msix_entries);
void hinic_io_free(struct hinic_func_to_io *func_to_io);
#endif
This diff is collapsed.
/*
* 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_MGMT_H
#define HINIC_HW_MGMT_H
#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"
#define HINIC_MSG_HEADER_MSG_LEN_SHIFT 0
#define HINIC_MSG_HEADER_MODULE_SHIFT 11
#define HINIC_MSG_HEADER_SEG_LEN_SHIFT 16
#define HINIC_MSG_HEADER_NO_ACK_SHIFT 22
#define HINIC_MSG_HEADER_ASYNC_MGMT_TO_PF_SHIFT 23
#define HINIC_MSG_HEADER_SEQID_SHIFT 24
#define HINIC_MSG_HEADER_LAST_SHIFT 30
#define HINIC_MSG_HEADER_DIRECTION_SHIFT 31
#define HINIC_MSG_HEADER_CMD_SHIFT 32
#define HINIC_MSG_HEADER_ZEROS_SHIFT 40
#define HINIC_MSG_HEADER_PCI_INTF_SHIFT 48
#define HINIC_MSG_HEADER_PF_IDX_SHIFT 50
#define HINIC_MSG_HEADER_MSG_ID_SHIFT 54
#define HINIC_MSG_HEADER_MSG_LEN_MASK 0x7FF
#define HINIC_MSG_HEADER_MODULE_MASK 0x1F
#define HINIC_MSG_HEADER_SEG_LEN_MASK 0x3F
#define HINIC_MSG_HEADER_NO_ACK_MASK 0x1
#define HINIC_MSG_HEADER_ASYNC_MGMT_TO_PF_MASK 0x1
#define HINIC_MSG_HEADER_SEQID_MASK 0x3F
#define HINIC_MSG_HEADER_LAST_MASK 0x1
#define HINIC_MSG_HEADER_DIRECTION_MASK 0x1
#define HINIC_MSG_HEADER_CMD_MASK 0xFF
#define HINIC_MSG_HEADER_ZEROS_MASK 0xFF
#define HINIC_MSG_HEADER_PCI_INTF_MASK 0x3
#define HINIC_MSG_HEADER_PF_IDX_MASK 0xF
#define HINIC_MSG_HEADER_MSG_ID_MASK 0x3FF
#define HINIC_MSG_HEADER_SET(val, member) \
((u64)((val) & HINIC_MSG_HEADER_##member##_MASK) << \
HINIC_MSG_HEADER_##member##_SHIFT)
#define HINIC_MSG_HEADER_GET(val, member) \
(((val) >> HINIC_MSG_HEADER_##member##_SHIFT) & \
HINIC_MSG_HEADER_##member##_MASK)
enum hinic_mgmt_msg_type {
HINIC_MGMT_MSG_SYNC = 1,
};
enum hinic_cfg_cmd {
HINIC_CFG_NIC_CAP = 0,
};
enum hinic_comm_cmd {
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_SQ_HI_CI_SET = 0x14,
HINIC_COMM_CMD_RES_STATE_SET = 0x24,
HINIC_COMM_CMD_IO_RES_CLEAR = 0x29,
HINIC_COMM_CMD_MAX = 0x32,
};
enum hinic_mgmt_cb_state {
HINIC_MGMT_CB_ENABLED = BIT(0),
HINIC_MGMT_CB_RUNNING = BIT(1),
};
struct hinic_recv_msg {
u8 *msg;
u8 *buf_out;
struct completion recv_done;
u16 cmd;
enum hinic_mod_type mod;
int async_mgmt_to_pf;
u16 msg_len;
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;
struct semaphore sync_msg_lock;
u16 sync_msg_id;
u8 *sync_msg_buf;
struct hinic_recv_msg recv_resp_msg_from_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,
enum hinic_mgmt_msg_type sync);
int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
struct hinic_hwif *hwif);
void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment