提交 f4b2a420 编写于 作者: D David S. Miller

Merge branch 'hns3-ethernet-driver'

Salil Mehta says:

====================
Hisilicon Network Subsystem 3 Ethernet Driver

This patch-set contains the support of the HNS3 (Hisilicon Network Subsystem 3)
Ethernet driver for hip08 family of SoCs and future upcoming SoCs.

Hisilicon's new hip08 SoCs have integrated ethernet based on PCI Express and
hence there was a need of new driver over the previous HNS driver which is
already part of the Linux mainline. This new driver is NOT backward
compatible with HNS.

This current driver is meant to control the Physical Function and there would
soon be a support of a separate driver for Virtual Function once this base PF
driver has been accepted. Also, this driver is the ongoing development work and
HNS3 Ethernet driver would be incrementally enhanced with more new features.

High Level Architecture:

        [ Ethtool ]
	   ^  |
           |  |
     [Ethernet Client]  [ODP/UIO Client] . . . [ RoCE Client ]
                         |                            |
                   [ HNAE Device ]                    |
                         |                            |
    ---------------------------------------------     |
                         |                            |
     [ HNAE3 Framework (Register/unregister) ]        |
                         |                            |
    ---------------------------------------------     |
                         |                            |
                   [ HCLGE Layer]                     |
         ________________|_________________           |
        |                |                 |          |
    [ MDIO ]    [ Scheduler/Shaper ]  [ Debugfs* ]    |
        |                |                 |          |
        |________________|_________________|          |
                         |                            |
             [ IMP command Interface ]                |
    ---------------------------------------------     |
              HIP08  H A R D W A R E                  *

Current patch-set broadly adds the support of the following PF functionality:
 1. Basic Rx and Tx functionality
 2. TSO support
 3. Ethtool support
 4. * Debugfs support -> this patch for now has been taken off.
 5. HNAE framework and hardware compatability layer
 6. Scheduler and Shaper support in transmit function
 7. MDIO support

Change Log:
V5->V6: Addressed below comments:
        * Andrew Lunn: Comments on MDIO and ethtool link mode
        * Leon Romanvosky: Some comments on HNAE layer tidy-up
        * Internal comments on redundant code removal, fixing error types etc.
V4->V5: Addressed below concerns:
        * Florian Fanelli: Miscellaneous comments on ethtool & enet layer
        * Stephen Hemminger: comment of Netdev stats in ethool layer
        * Leon Romanvosky: Comments on Driver Version String, naming & Kconfig
        * Rochard Cochran: Redundant function prototype
V3->V4: Addressed below comments:
        * Andrew Lunn: Various comments on MDIO, ethtool, ENET driver etc,
        * Stephen Hemminger: change access and updation to 64 but statistics
        * Bo You: some spelling mistakes and checkpatch.pl errors.
V2->V3: Addressed comments
        * Yuval Mintz: Removal of redundant userprio-to-tc code
        * Stephen Hemminger: Ethtool & interuupt enable
        * Andrew Lunn: On C45/C22 PHy support, HNAE, ethtool
        * Florian Fainelli: C45/C22 and phy_connect/attach
        * Intel kbuild errors
V1->V2: Addressed some comments by kbuild, Yuval MIntz, Andrew Lunn &
        Florian Fainelli in the following patches:
        * Add support of HNS3 Ethernet Driver for hip08 SoC
        * Add MDIO support to HNS3 Ethernet driver for hip08 SoC
        * Add support of debugfs interface to HNS3 driver
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
......@@ -6148,6 +6148,14 @@ S: Maintained
F: drivers/net/ethernet/hisilicon/
F: Documentation/devicetree/bindings/net/hisilicon*.txt
HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
M: Yisen Zhuang <yisen.zhuang@huawei.com>
M: Salil Mehta <salil.mehta@huawei.com>
L: netdev@vger.kernel.org
W: http://www.hisilicon.com
S: Maintained
F: drivers/net/ethernet/hisilicon/hns3/
HISILICON ROCE DRIVER
M: Lijun Ou <oulijun@huawei.com>
M: Wei Hu(Xavier) <xavier.huwei@huawei.com>
......
......@@ -76,4 +76,31 @@ config HNS_ENET
This selects the general ethernet driver for HNS. This module make
use of any HNS AE driver, such as HNS_DSAF
config HNS3
tristate "Hisilicon Network Subsystem Support HNS3 (Framework)"
depends on PCI
---help---
This selects the framework support for Hisilicon Network Subsystem 3.
This layer facilitates clients like ENET, RoCE and user-space ethernet
drivers(like ODP)to register with HNAE devices and their associated
operations.
config HNS3_HCLGE
tristate "Hisilicon HNS3 HCLGE Acceleration Engine & Compatibility Layer Support"
depends on PCI_MSI
depends on HNS3
---help---
This selects the HNS3_HCLGE network acceleration engine & its hardware
compatibility layer. The engine would be used in Hisilicon hip08 family of
SoCs and further upcoming SoCs.
config HNS3_ENET
tristate "Hisilicon HNS3 Ethernet Device Support"
depends on 64BIT && PCI
depends on HNS3 && HNS3_HCLGE
---help---
This selects the Ethernet Driver for Hisilicon Network Subsystem 3 for hip08
family of SoCs. This module depends upon HNAE3 driver to access the HNAE3
devices and their associated operations.
endif # NET_VENDOR_HISILICON
......@@ -6,4 +6,5 @@ obj-$(CONFIG_HIX5HD2_GMAC) += hix5hd2_gmac.o
obj-$(CONFIG_HIP04_ETH) += hip04_eth.o
obj-$(CONFIG_HNS_MDIO) += hns_mdio.o
obj-$(CONFIG_HNS) += hns/
obj-$(CONFIG_HNS3) += hns3/
obj-$(CONFIG_HISI_FEMAC) += hisi_femac.o
#
# Makefile for the HISILICON network device drivers.
#
obj-$(CONFIG_HNS3) += hns3pf/
obj-$(CONFIG_HNS3) += hnae3.o
/*
* Copyright (c) 2016-2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include "hnae3.h"
static LIST_HEAD(hnae3_ae_algo_list);
static LIST_HEAD(hnae3_client_list);
static LIST_HEAD(hnae3_ae_dev_list);
/* we are keeping things simple and using single lock for all the
* list. This is a non-critical code so other updations, if happen
* in parallel, can wait.
*/
static DEFINE_MUTEX(hnae3_common_lock);
static bool hnae3_client_match(enum hnae3_client_type client_type,
enum hnae3_dev_type dev_type)
{
if ((dev_type == HNAE3_DEV_KNIC) && (client_type == HNAE3_CLIENT_KNIC ||
client_type == HNAE3_CLIENT_ROCE))
return true;
if (dev_type == HNAE3_DEV_UNIC && client_type == HNAE3_CLIENT_UNIC)
return true;
return false;
}
static int hnae3_match_n_instantiate(struct hnae3_client *client,
struct hnae3_ae_dev *ae_dev,
bool is_reg, bool *matched)
{
int ret;
*matched = false;
/* check if this client matches the type of ae_dev */
if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
return 0;
}
/* there is a match of client and dev */
*matched = true;
/* now, (un-)instantiate client by calling lower layer */
if (is_reg) {
ret = ae_dev->ops->init_client_instance(client, ae_dev);
if (ret)
dev_err(&ae_dev->pdev->dev,
"fail to instantiate client\n");
return ret;
}
ae_dev->ops->uninit_client_instance(client, ae_dev);
return 0;
}
int hnae3_register_client(struct hnae3_client *client)
{
struct hnae3_client *client_tmp;
struct hnae3_ae_dev *ae_dev;
bool matched;
int ret = 0;
mutex_lock(&hnae3_common_lock);
/* one system should only have one client for every type */
list_for_each_entry(client_tmp, &hnae3_client_list, node) {
if (client_tmp->type == client->type)
goto exit;
}
list_add_tail(&client->node, &hnae3_client_list);
/* initialize the client on every matched port */
list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
/* if the client could not be initialized on current port, for
* any error reasons, move on to next available port
*/
ret = hnae3_match_n_instantiate(client, ae_dev, true, &matched);
if (ret)
dev_err(&ae_dev->pdev->dev,
"match and instantiation failed for port\n");
}
exit:
mutex_unlock(&hnae3_common_lock);
return ret;
}
EXPORT_SYMBOL(hnae3_register_client);
void hnae3_unregister_client(struct hnae3_client *client)
{
struct hnae3_ae_dev *ae_dev;
bool matched;
mutex_lock(&hnae3_common_lock);
/* un-initialize the client on every matched port */
list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
hnae3_match_n_instantiate(client, ae_dev, false, &matched);
}
list_del(&client->node);
mutex_unlock(&hnae3_common_lock);
}
EXPORT_SYMBOL(hnae3_unregister_client);
/* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
* @ae_algo: AE algorithm
* NOTE: the duplicated name will not be checked
*/
int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
{
const struct pci_device_id *id;
struct hnae3_ae_dev *ae_dev;
struct hnae3_client *client;
bool matched;
int ret = 0;
mutex_lock(&hnae3_common_lock);
list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
/* Check if this algo/ops matches the list of ae_devs */
list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
if (!id)
continue;
/* ae_dev init should set flag */
ae_dev->ops = ae_algo->ops;
ret = ae_algo->ops->init_ae_dev(ae_dev);
if (ret) {
dev_err(&ae_dev->pdev->dev, "init ae_dev error.\n");
continue;
}
hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
/* check the client list for the match with this ae_dev type and
* initialize the figure out client instance
*/
list_for_each_entry(client, &hnae3_client_list, node) {
ret = hnae3_match_n_instantiate(client, ae_dev, true,
&matched);
if (ret)
dev_err(&ae_dev->pdev->dev,
"match and instantiation failed\n");
if (matched)
break;
}
}
mutex_unlock(&hnae3_common_lock);
return ret;
}
EXPORT_SYMBOL(hnae3_register_ae_algo);
/* hnae3_unregister_ae_algo - unregisters a AE algorithm
* @ae_algo: the AE algorithm to unregister
*/
void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
{
const struct pci_device_id *id;
struct hnae3_ae_dev *ae_dev;
struct hnae3_client *client;
bool matched;
mutex_lock(&hnae3_common_lock);
/* Check if there are matched ae_dev */
list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
if (!id)
continue;
/* check the client list for the match with this ae_dev type and
* un-initialize the figure out client instance
*/
list_for_each_entry(client, &hnae3_client_list, node) {
hnae3_match_n_instantiate(client, ae_dev, false,
&matched);
if (matched)
break;
}
ae_algo->ops->uninit_ae_dev(ae_dev);
hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
}
list_del(&ae_algo->node);
mutex_unlock(&hnae3_common_lock);
}
EXPORT_SYMBOL(hnae3_unregister_ae_algo);
/* hnae3_register_ae_dev - registers a AE device to hnae3 framework
* @ae_dev: the AE device
* NOTE: the duplicated name will not be checked
*/
int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
{
const struct pci_device_id *id;
struct hnae3_ae_algo *ae_algo;
struct hnae3_client *client;
bool matched;
int ret = 0;
mutex_lock(&hnae3_common_lock);
list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
/* Check if there are matched ae_algo */
list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
if (!id)
continue;
ae_dev->ops = ae_algo->ops;
if (!ae_dev->ops) {
dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
goto out_err;
}
/* ae_dev init should set flag */
ret = ae_dev->ops->init_ae_dev(ae_dev);
if (ret) {
dev_err(&ae_dev->pdev->dev, "init ae_dev error\n");
goto out_err;
}
hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
break;
}
/* check the client list for the match with this ae_dev type and
* initialize the figure out client instance
*/
list_for_each_entry(client, &hnae3_client_list, node) {
ret = hnae3_match_n_instantiate(client, ae_dev, true,
&matched);
if (ret)
dev_err(&ae_dev->pdev->dev,
"match and instantiation failed\n");
if (matched)
break;
}
out_err:
mutex_unlock(&hnae3_common_lock);
return ret;
}
EXPORT_SYMBOL(hnae3_register_ae_dev);
/* hnae3_unregister_ae_dev - unregisters a AE device
* @ae_dev: the AE device to unregister
*/
void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
{
const struct pci_device_id *id;
struct hnae3_ae_algo *ae_algo;
struct hnae3_client *client;
bool matched;
mutex_lock(&hnae3_common_lock);
/* Check if there are matched ae_algo */
list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
if (!id)
continue;
list_for_each_entry(client, &hnae3_client_list, node) {
hnae3_match_n_instantiate(client, ae_dev, false,
&matched);
if (matched)
break;
}
ae_algo->ops->uninit_ae_dev(ae_dev);
hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
}
list_del(&ae_dev->node);
mutex_unlock(&hnae3_common_lock);
}
EXPORT_SYMBOL(hnae3_unregister_ae_dev);
MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
/*
* Copyright (c) 2016-2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __HNAE3_H
#define __HNAE3_H
/* Names used in this framework:
* ae handle (handle):
* a set of queues provided by AE
* ring buffer queue (rbq):
* the channel between upper layer and the AE, can do tx and rx
* ring:
* a tx or rx channel within a rbq
* ring description (desc):
* an element in the ring with packet information
* buffer:
* a memory region referred by desc with the full packet payload
*
* "num" means a static number set as a parameter, "count" mean a dynamic
* number set while running
* "cb" means control block
*/
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/types.h>
/* Device IDs */
#define HNAE3_DEV_ID_GE 0xA220
#define HNAE3_DEV_ID_25GE 0xA221
#define HNAE3_DEV_ID_25GE_RDMA 0xA222
#define HNAE3_DEV_ID_25GE_RDMA_MACSEC 0xA223
#define HNAE3_DEV_ID_50GE_RDMA 0xA224
#define HNAE3_DEV_ID_50GE_RDMA_MACSEC 0xA225
#define HNAE3_DEV_ID_100G_RDMA_MACSEC 0xA226
#define HNAE3_DEV_ID_100G_VF 0xA22E
#define HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF 0xA22F
#define HNAE3_CLASS_NAME_SIZE 16
#define HNAE3_DEV_INITED_B 0x0
#define HNAE_DEV_SUPPORT_ROCE_B 0x1
#define ring_ptr_move_fw(ring, p) \
((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
#define ring_ptr_move_bw(ring, p) \
((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num)
enum hns_desc_type {
DESC_TYPE_SKB,
DESC_TYPE_PAGE,
};
struct hnae3_handle;
struct hnae3_queue {
void __iomem *io_base;
struct hnae3_ae_algo *ae_algo;
struct hnae3_handle *handle;
int tqp_index; /* index in a handle */
u32 buf_size; /* size for hnae_desc->addr, preset by AE */
u16 desc_num; /* total number of desc */
};
/*hnae3 loop mode*/
enum hnae3_loop {
HNAE3_MAC_INTER_LOOP_MAC,
HNAE3_MAC_INTER_LOOP_SERDES,
HNAE3_MAC_INTER_LOOP_PHY,
HNAE3_MAC_LOOP_NONE,
};
enum hnae3_client_type {
HNAE3_CLIENT_KNIC,
HNAE3_CLIENT_UNIC,
HNAE3_CLIENT_ROCE,
};
enum hnae3_dev_type {
HNAE3_DEV_KNIC,
HNAE3_DEV_UNIC,
};
/* mac media type */
enum hnae3_media_type {
HNAE3_MEDIA_TYPE_UNKNOWN,
HNAE3_MEDIA_TYPE_FIBER,
HNAE3_MEDIA_TYPE_COPPER,
HNAE3_MEDIA_TYPE_BACKPLANE,
};
struct hnae3_vector_info {
u8 __iomem *io_addr;
int vector;
};
#define HNAE3_RING_TYPE_B 0
#define HNAE3_RING_TYPE_TX 0
#define HNAE3_RING_TYPE_RX 1
struct hnae3_ring_chain_node {
struct hnae3_ring_chain_node *next;
u32 tqp_index;
u32 flag;
};
#define HNAE3_IS_TX_RING(node) \
(((node)->flag & (1 << HNAE3_RING_TYPE_B)) == HNAE3_RING_TYPE_TX)
struct hnae3_client_ops {
int (*init_instance)(struct hnae3_handle *handle);
void (*uninit_instance)(struct hnae3_handle *handle, bool reset);
void (*link_status_change)(struct hnae3_handle *handle, bool state);
};
#define HNAE3_CLIENT_NAME_LENGTH 16
struct hnae3_client {
char name[HNAE3_CLIENT_NAME_LENGTH];
u16 version;
unsigned long state;
enum hnae3_client_type type;
const struct hnae3_client_ops *ops;
struct list_head node;
};
struct hnae3_ae_dev {
struct pci_dev *pdev;
const struct hnae3_ae_ops *ops;
struct list_head node;
u32 flag;
enum hnae3_dev_type dev_type;
void *priv;
};
/* This struct defines the operation on the handle.
*
* init_ae_dev(): (mandatory)
* Get PF configure from pci_dev and initialize PF hardware
* uninit_ae_dev()
* Disable PF device and release PF resource
* register_client
* Register client to ae_dev
* unregister_client()
* Unregister client from ae_dev
* start()
* Enable the hardware
* stop()
* Disable the hardware
* get_status()
* Get the carrier state of the back channel of the handle, 1 for ok, 0 for
* non-ok
* get_ksettings_an_result()
* Get negotiation status,speed and duplex
* update_speed_duplex_h()
* Update hardware speed and duplex
* get_media_type()
* Get media type of MAC
* adjust_link()
* Adjust link status
* set_loopback()
* Set loopback
* set_promisc_mode
* Set promisc mode
* set_mtu()
* set mtu
* get_pauseparam()
* get tx and rx of pause frame use
* set_pauseparam()
* set tx and rx of pause frame use
* set_autoneg()
* set auto autonegotiation of pause frame use
* get_autoneg()
* get auto autonegotiation of pause frame use
* get_coalesce_usecs()
* get usecs to delay a TX interrupt after a packet is sent
* get_rx_max_coalesced_frames()
* get Maximum number of packets to be sent before a TX interrupt.
* set_coalesce_usecs()
* set usecs to delay a TX interrupt after a packet is sent
* set_coalesce_frames()
* set Maximum number of packets to be sent before a TX interrupt.
* get_mac_addr()
* get mac address
* set_mac_addr()
* set mac address
* add_uc_addr
* Add unicast addr to mac table
* rm_uc_addr
* Remove unicast addr from mac table
* set_mc_addr()
* Set multicast address
* add_mc_addr
* Add multicast address to mac table
* rm_mc_addr
* Remove multicast address from mac table
* update_stats()
* Update Old network device statistics
* get_ethtool_stats()
* Get ethtool network device statistics
* get_strings()
* Get a set of strings that describe the requested objects
* get_sset_count()
* Get number of strings that @get_strings will write
* update_led_status()
* Update the led status
* set_led_id()
* Set led id
* get_regs()
* Get regs dump
* get_regs_len()
* Get the len of the regs dump
* get_rss_key_size()
* Get rss key size
* get_rss_indir_size()
* Get rss indirection table size
* get_rss()
* Get rss table
* set_rss()
* Set rss table
* get_tc_size()
* Get tc size of handle
* get_vector()
* Get vector number and vector information
* map_ring_to_vector()
* Map rings to vector
* unmap_ring_from_vector()
* Unmap rings from vector
* add_tunnel_udp()
* Add tunnel information to hardware
* del_tunnel_udp()
* Delete tunnel information from hardware
* reset_queue()
* Reset queue
* get_fw_version()
* Get firmware version
* get_mdix_mode()
* Get media typr of phy
* set_vlan_filter()
* Set vlan filter config of Ports
* set_vf_vlan_filter()
* Set vlan filter config of vf
*/
struct hnae3_ae_ops {
int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
void (*uninit_ae_dev)(struct hnae3_ae_dev *ae_dev);
int (*init_client_instance)(struct hnae3_client *client,
struct hnae3_ae_dev *ae_dev);
void (*uninit_client_instance)(struct hnae3_client *client,
struct hnae3_ae_dev *ae_dev);
int (*start)(struct hnae3_handle *handle);
void (*stop)(struct hnae3_handle *handle);
int (*get_status)(struct hnae3_handle *handle);
void (*get_ksettings_an_result)(struct hnae3_handle *handle,
u8 *auto_neg, u32 *speed, u8 *duplex);
int (*update_speed_duplex_h)(struct hnae3_handle *handle);
int (*cfg_mac_speed_dup_h)(struct hnae3_handle *handle, int speed,
u8 duplex);
void (*get_media_type)(struct hnae3_handle *handle, u8 *media_type);
void (*adjust_link)(struct hnae3_handle *handle, int speed, int duplex);
int (*set_loopback)(struct hnae3_handle *handle,
enum hnae3_loop loop_mode, bool en);
void (*set_promisc_mode)(struct hnae3_handle *handle, u32 en);
int (*set_mtu)(struct hnae3_handle *handle, int new_mtu);
void (*get_pauseparam)(struct hnae3_handle *handle,
u32 *auto_neg, u32 *rx_en, u32 *tx_en);
int (*set_pauseparam)(struct hnae3_handle *handle,
u32 auto_neg, u32 rx_en, u32 tx_en);
int (*set_autoneg)(struct hnae3_handle *handle, bool enable);
int (*get_autoneg)(struct hnae3_handle *handle);
void (*get_coalesce_usecs)(struct hnae3_handle *handle,
u32 *tx_usecs, u32 *rx_usecs);
void (*get_rx_max_coalesced_frames)(struct hnae3_handle *handle,
u32 *tx_frames, u32 *rx_frames);
int (*set_coalesce_usecs)(struct hnae3_handle *handle, u32 timeout);
int (*set_coalesce_frames)(struct hnae3_handle *handle,
u32 coalesce_frames);
void (*get_coalesce_range)(struct hnae3_handle *handle,
u32 *tx_frames_low, u32 *rx_frames_low,
u32 *tx_frames_high, u32 *rx_frames_high,
u32 *tx_usecs_low, u32 *rx_usecs_low,
u32 *tx_usecs_high, u32 *rx_usecs_high);
void (*get_mac_addr)(struct hnae3_handle *handle, u8 *p);
int (*set_mac_addr)(struct hnae3_handle *handle, void *p);
int (*add_uc_addr)(struct hnae3_handle *handle,
const unsigned char *addr);
int (*rm_uc_addr)(struct hnae3_handle *handle,
const unsigned char *addr);
int (*set_mc_addr)(struct hnae3_handle *handle, void *addr);
int (*add_mc_addr)(struct hnae3_handle *handle,
const unsigned char *addr);
int (*rm_mc_addr)(struct hnae3_handle *handle,
const unsigned char *addr);
void (*set_tso_stats)(struct hnae3_handle *handle, int enable);
void (*update_stats)(struct hnae3_handle *handle,
struct net_device_stats *net_stats);
void (*get_stats)(struct hnae3_handle *handle, u64 *data);
void (*get_strings)(struct hnae3_handle *handle,
u32 stringset, u8 *data);
int (*get_sset_count)(struct hnae3_handle *handle, int stringset);
void (*get_regs)(struct hnae3_handle *handle, void *data);
int (*get_regs_len)(struct hnae3_handle *handle);
u32 (*get_rss_key_size)(struct hnae3_handle *handle);
u32 (*get_rss_indir_size)(struct hnae3_handle *handle);
int (*get_rss)(struct hnae3_handle *handle, u32 *indir, u8 *key,
u8 *hfunc);
int (*set_rss)(struct hnae3_handle *handle, const u32 *indir,
const u8 *key, const u8 hfunc);
int (*get_tc_size)(struct hnae3_handle *handle);
int (*get_vector)(struct hnae3_handle *handle, u16 vector_num,
struct hnae3_vector_info *vector_info);
int (*map_ring_to_vector)(struct hnae3_handle *handle,
int vector_num,
struct hnae3_ring_chain_node *vr_chain);
int (*unmap_ring_from_vector)(struct hnae3_handle *handle,
int vector_num,
struct hnae3_ring_chain_node *vr_chain);
int (*add_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
int (*del_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
void (*reset_queue)(struct hnae3_handle *handle, u16 queue_id);
u32 (*get_fw_version)(struct hnae3_handle *handle);
void (*get_mdix_mode)(struct hnae3_handle *handle,
u8 *tp_mdix_ctrl, u8 *tp_mdix);
int (*set_vlan_filter)(struct hnae3_handle *handle, __be16 proto,
u16 vlan_id, bool is_kill);
int (*set_vf_vlan_filter)(struct hnae3_handle *handle, int vfid,
u16 vlan, u8 qos, __be16 proto);
};
struct hnae3_ae_algo {
const struct hnae3_ae_ops *ops;
struct list_head node;
char name[HNAE3_CLASS_NAME_SIZE];
const struct pci_device_id *pdev_id_table;
};
#define HNAE3_INT_NAME_LEN (IFNAMSIZ + 16)
#define HNAE3_ITR_COUNTDOWN_START 100
struct hnae3_tc_info {
u16 tqp_offset; /* TQP offset from base TQP */
u16 tqp_count; /* Total TQPs */
u8 up; /* user priority */
u8 tc; /* TC index */
bool enable; /* If this TC is enable or not */
};
#define HNAE3_MAX_TC 8
struct hnae3_knic_private_info {
struct net_device *netdev; /* Set by KNIC client when init instance */
u16 rss_size; /* Allocated RSS queues */
u16 rx_buf_len;
u16 num_desc;
u8 num_tc; /* Total number of enabled TCs */
struct hnae3_tc_info tc_info[HNAE3_MAX_TC]; /* Idx of array is HW TC */
u16 num_tqps; /* total number of TQPs in this handle */
struct hnae3_queue **tqp; /* array base of all TQPs in this instance */
};
struct hnae3_roce_private_info {
struct net_device *netdev;
void __iomem *roce_io_base;
int base_vector;
int num_vectors;
};
struct hnae3_unic_private_info {
struct net_device *netdev;
u16 rx_buf_len;
u16 num_desc;
u16 num_tqps; /* total number of tqps in this handle */
struct hnae3_queue **tqp; /* array base of all TQPs of this instance */
};
#define HNAE3_SUPPORT_MAC_LOOPBACK 1
#define HNAE3_SUPPORT_PHY_LOOPBACK 2
#define HNAE3_SUPPORT_SERDES_LOOPBACK 4
struct hnae3_handle {
struct hnae3_client *client;
struct pci_dev *pdev;
void *priv;
struct hnae3_ae_algo *ae_algo; /* the class who provides this handle */
u64 flags; /* Indicate the capabilities for this handle*/
union {
struct net_device *netdev; /* first member */
struct hnae3_knic_private_info kinfo;
struct hnae3_unic_private_info uinfo;
struct hnae3_roce_private_info rinfo;
};
u32 numa_node_mask; /* for multi-chip support */
};
#define hnae_set_field(origin, mask, shift, val) \
do { \
(origin) &= (~(mask)); \
(origin) |= ((val) << (shift)) & (mask); \
} while (0)
#define hnae_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift))
#define hnae_set_bit(origin, shift, val) \
hnae_set_field((origin), (0x1 << (shift)), (shift), (val))
#define hnae_get_bit(origin, shift) \
hnae_get_field((origin), (0x1 << (shift)), (shift))
int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo);
int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo);
void hnae3_unregister_client(struct hnae3_client *client);
int hnae3_register_client(struct hnae3_client *client);
#endif
#
# Makefile for the HISILICON network device drivers.
#
ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3
obj-$(CONFIG_HNS3_HCLGE) += hclge.o
hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o
obj-$(CONFIG_HNS3_ENET) += hns3.o
hns3-objs = hns3_enet.o hns3_ethtool.o
/*
* Copyright (c) 2016~2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/dma-direction.h>
#include "hclge_cmd.h"
#include "hnae3.h"
#include "hclge_main.h"
#define hclge_is_csq(ring) ((ring)->flag & HCLGE_TYPE_CSQ)
#define hclge_ring_to_dma_dir(ring) (hclge_is_csq(ring) ? \
DMA_TO_DEVICE : DMA_FROM_DEVICE)
#define cmq_ring_to_dev(ring) (&(ring)->dev->pdev->dev)
static int hclge_ring_space(struct hclge_cmq_ring *ring)
{
int ntu = ring->next_to_use;
int ntc = ring->next_to_clean;
int used = (ntu - ntc + ring->desc_num) % ring->desc_num;
return ring->desc_num - used - 1;
}
static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
{
int size = ring->desc_num * sizeof(struct hclge_desc);
ring->desc = kzalloc(size, GFP_KERNEL);
if (!ring->desc)
return -ENOMEM;
ring->desc_dma_addr = dma_map_single(cmq_ring_to_dev(ring), ring->desc,
size, DMA_BIDIRECTIONAL);
if (dma_mapping_error(cmq_ring_to_dev(ring), ring->desc_dma_addr)) {
ring->desc_dma_addr = 0;
kfree(ring->desc);
ring->desc = NULL;
return -ENOMEM;
}
return 0;
}
static void hclge_free_cmd_desc(struct hclge_cmq_ring *ring)
{
dma_unmap_single(cmq_ring_to_dev(ring), ring->desc_dma_addr,
ring->desc_num * sizeof(ring->desc[0]),
DMA_BIDIRECTIONAL);
ring->desc_dma_addr = 0;
kfree(ring->desc);
ring->desc = NULL;
}
static int hclge_init_cmd_queue(struct hclge_dev *hdev, int ring_type)
{
struct hclge_hw *hw = &hdev->hw;
struct hclge_cmq_ring *ring =
(ring_type == HCLGE_TYPE_CSQ) ? &hw->cmq.csq : &hw->cmq.crq;
int ret;
ring->flag = ring_type;
ring->dev = hdev;
ret = hclge_alloc_cmd_desc(ring);
if (ret) {
dev_err(&hdev->pdev->dev, "descriptor %s alloc error %d\n",
(ring_type == HCLGE_TYPE_CSQ) ? "CSQ" : "CRQ", ret);
return ret;
}
ring->next_to_clean = 0;
ring->next_to_use = 0;
return 0;
}
void hclge_cmd_setup_basic_desc(struct hclge_desc *desc,
enum hclge_opcode_type opcode, bool is_read)
{
memset((void *)desc, 0, sizeof(struct hclge_desc));
desc->opcode = cpu_to_le16(opcode);
desc->flag = cpu_to_le16(HCLGE_CMD_FLAG_NO_INTR | HCLGE_CMD_FLAG_IN);
if (is_read)
desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_WR);
else
desc->flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
}
static void hclge_cmd_config_regs(struct hclge_cmq_ring *ring)
{
dma_addr_t dma = ring->desc_dma_addr;
struct hclge_dev *hdev = ring->dev;
struct hclge_hw *hw = &hdev->hw;
if (ring->flag == HCLGE_TYPE_CSQ) {
hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_L_REG,
(u32)dma);
hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG,
(u32)((dma >> 31) >> 1));
hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG,
(ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S) |
HCLGE_NIC_CMQ_ENABLE);
hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, 0);
hclge_write_dev(hw, HCLGE_NIC_CSQ_HEAD_REG, 0);
} else {
hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_L_REG,
(u32)dma);
hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_H_REG,
(u32)((dma >> 31) >> 1));
hclge_write_dev(hw, HCLGE_NIC_CRQ_DEPTH_REG,
(ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S) |
HCLGE_NIC_CMQ_ENABLE);
hclge_write_dev(hw, HCLGE_NIC_CRQ_TAIL_REG, 0);
hclge_write_dev(hw, HCLGE_NIC_CRQ_HEAD_REG, 0);
}
}
static void hclge_cmd_init_regs(struct hclge_hw *hw)
{
hclge_cmd_config_regs(&hw->cmq.csq);
hclge_cmd_config_regs(&hw->cmq.crq);
}
static int hclge_cmd_csq_clean(struct hclge_hw *hw)
{
struct hclge_cmq_ring *csq = &hw->cmq.csq;
u16 ntc = csq->next_to_clean;
struct hclge_desc *desc;
int clean = 0;
u32 head;
desc = &csq->desc[ntc];
head = hclge_read_dev(hw, HCLGE_NIC_CSQ_HEAD_REG);
while (head != ntc) {
memset(desc, 0, sizeof(*desc));
ntc++;
if (ntc == csq->desc_num)
ntc = 0;
desc = &csq->desc[ntc];
clean++;
}
csq->next_to_clean = ntc;
return clean;
}
static int hclge_cmd_csq_done(struct hclge_hw *hw)
{
u32 head = hclge_read_dev(hw, HCLGE_NIC_CSQ_HEAD_REG);
return head == hw->cmq.csq.next_to_use;
}
static bool hclge_is_special_opcode(u16 opcode)
{
u16 spec_opcode[3] = {0x0030, 0x0031, 0x0032};
int i;
for (i = 0; i < ARRAY_SIZE(spec_opcode); i++) {
if (spec_opcode[i] == opcode)
return true;
}
return false;
}
/**
* hclge_cmd_send - send command to command queue
* @hw: pointer to the hw struct
* @desc: prefilled descriptor for describing the command
* @num : the number of descriptors to be sent
*
* This is the main send command for command queue, it
* sends the queue, cleans the queue, etc
**/
int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
{
struct hclge_dev *hdev = (struct hclge_dev *)hw->back;
struct hclge_desc *desc_to_use;
bool complete = false;
u32 timeout = 0;
int handle = 0;
int retval = 0;
u16 opcode, desc_ret;
int ntc;
spin_lock_bh(&hw->cmq.csq.lock);
if (num > hclge_ring_space(&hw->cmq.csq)) {
spin_unlock_bh(&hw->cmq.csq.lock);
return -EBUSY;
}
/**
* Record the location of desc in the ring for this time
* which will be use for hardware to write back
*/
ntc = hw->cmq.csq.next_to_use;
opcode = desc[0].opcode;
while (handle < num) {
desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use];
*desc_to_use = desc[handle];
(hw->cmq.csq.next_to_use)++;
if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num)
hw->cmq.csq.next_to_use = 0;
handle++;
}
/* Write to hardware */
hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, hw->cmq.csq.next_to_use);
/**
* If the command is sync, wait for the firmware to write back,
* if multi descriptors to be sent, use the first one to check
*/
if (HCLGE_SEND_SYNC(desc->flag)) {
do {
if (hclge_cmd_csq_done(hw))
break;
udelay(1);
timeout++;
} while (timeout < hw->cmq.tx_timeout);
}
if (hclge_cmd_csq_done(hw)) {
complete = true;
handle = 0;
while (handle < num) {
/* Get the result of hardware write back */
desc_to_use = &hw->cmq.csq.desc[ntc];
desc[handle] = *desc_to_use;
pr_debug("Get cmd desc:\n");
if (likely(!hclge_is_special_opcode(opcode)))
desc_ret = desc[handle].retval;
else
desc_ret = desc[0].retval;
if ((enum hclge_cmd_return_status)desc_ret ==
HCLGE_CMD_EXEC_SUCCESS)
retval = 0;
else
retval = -EIO;
hw->cmq.last_status = (enum hclge_cmd_status)desc_ret;
ntc++;
handle++;
if (ntc == hw->cmq.csq.desc_num)
ntc = 0;
}
}
if (!complete)
retval = -EAGAIN;
/* Clean the command send queue */
handle = hclge_cmd_csq_clean(hw);
if (handle != num) {
dev_warn(&hdev->pdev->dev,
"cleaned %d, need to clean %d\n", handle, num);
}
spin_unlock_bh(&hw->cmq.csq.lock);
return retval;
}
enum hclge_cmd_status hclge_cmd_query_firmware_version(struct hclge_hw *hw,
u32 *version)
{
struct hclge_query_version *resp;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_FW_VER, 1);
resp = (struct hclge_query_version *)desc.data;
ret = hclge_cmd_send(hw, &desc, 1);
if (!ret)
*version = le32_to_cpu(resp->firmware);
return ret;
}
int hclge_cmd_init(struct hclge_dev *hdev)
{
u32 version;
int ret;
/* Setup the queue entries for use cmd queue */
hdev->hw.cmq.csq.desc_num = HCLGE_NIC_CMQ_DESC_NUM;
hdev->hw.cmq.crq.desc_num = HCLGE_NIC_CMQ_DESC_NUM;
/* Setup the lock for command queue */
spin_lock_init(&hdev->hw.cmq.csq.lock);
spin_lock_init(&hdev->hw.cmq.crq.lock);
/* Setup Tx write back timeout */
hdev->hw.cmq.tx_timeout = HCLGE_CMDQ_TX_TIMEOUT;
/* Setup queue rings */
ret = hclge_init_cmd_queue(hdev, HCLGE_TYPE_CSQ);
if (ret) {
dev_err(&hdev->pdev->dev,
"CSQ ring setup error %d\n", ret);
return ret;
}
ret = hclge_init_cmd_queue(hdev, HCLGE_TYPE_CRQ);
if (ret) {
dev_err(&hdev->pdev->dev,
"CRQ ring setup error %d\n", ret);
goto err_csq;
}
hclge_cmd_init_regs(&hdev->hw);
ret = hclge_cmd_query_firmware_version(&hdev->hw, &version);
if (ret) {
dev_err(&hdev->pdev->dev,
"firmware version query failed %d\n", ret);
return ret;
}
hdev->fw_version = version;
dev_info(&hdev->pdev->dev, "The firware version is %08x\n", version);
return 0;
err_csq:
hclge_free_cmd_desc(&hdev->hw.cmq.csq);
return ret;
}
static void hclge_destroy_queue(struct hclge_cmq_ring *ring)
{
spin_lock_bh(&ring->lock);
hclge_free_cmd_desc(ring);
spin_unlock_bh(&ring->lock);
}
void hclge_destroy_cmd_queue(struct hclge_hw *hw)
{
hclge_destroy_queue(&hw->cmq.csq);
hclge_destroy_queue(&hw->cmq.crq);
}
/*
* Copyright (c) 2016~2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __HCLGE_CMD_H
#define __HCLGE_CMD_H
#include <linux/types.h>
#include <linux/io.h>
#define HCLGE_CMDQ_TX_TIMEOUT 1000
struct hclge_dev;
struct hclge_desc {
__le16 opcode;
#define HCLGE_CMDQ_RX_INVLD_B 0
#define HCLGE_CMDQ_RX_OUTVLD_B 1
__le16 flag;
__le16 retval;
__le16 rsv;
__le32 data[6];
};
struct hclge_desc_cb {
dma_addr_t dma;
void *va;
u32 length;
};
struct hclge_cmq_ring {
dma_addr_t desc_dma_addr;
struct hclge_desc *desc;
struct hclge_desc_cb *desc_cb;
struct hclge_dev *dev;
u32 head;
u32 tail;
u16 buf_size;
u16 desc_num;
int next_to_use;
int next_to_clean;
u8 flag;
spinlock_t lock; /* Command queue lock */
};
enum hclge_cmd_return_status {
HCLGE_CMD_EXEC_SUCCESS = 0,
HCLGE_CMD_NO_AUTH = 1,
HCLGE_CMD_NOT_EXEC = 2,
HCLGE_CMD_QUEUE_FULL = 3,
};
enum hclge_cmd_status {
HCLGE_STATUS_SUCCESS = 0,
HCLGE_ERR_CSQ_FULL = -1,
HCLGE_ERR_CSQ_TIMEOUT = -2,
HCLGE_ERR_CSQ_ERROR = -3,
};
struct hclge_cmq {
struct hclge_cmq_ring csq;
struct hclge_cmq_ring crq;
u16 tx_timeout; /* Tx timeout */
enum hclge_cmd_status last_status;
};
#define HCLGE_CMD_FLAG_IN_VALID_SHIFT 0
#define HCLGE_CMD_FLAG_OUT_VALID_SHIFT 1
#define HCLGE_CMD_FLAG_NEXT_SHIFT 2
#define HCLGE_CMD_FLAG_WR_OR_RD_SHIFT 3
#define HCLGE_CMD_FLAG_NO_INTR_SHIFT 4
#define HCLGE_CMD_FLAG_ERR_INTR_SHIFT 5
#define HCLGE_CMD_FLAG_IN BIT(HCLGE_CMD_FLAG_IN_VALID_SHIFT)
#define HCLGE_CMD_FLAG_OUT BIT(HCLGE_CMD_FLAG_OUT_VALID_SHIFT)
#define HCLGE_CMD_FLAG_NEXT BIT(HCLGE_CMD_FLAG_NEXT_SHIFT)
#define HCLGE_CMD_FLAG_WR BIT(HCLGE_CMD_FLAG_WR_OR_RD_SHIFT)
#define HCLGE_CMD_FLAG_NO_INTR BIT(HCLGE_CMD_FLAG_NO_INTR_SHIFT)
#define HCLGE_CMD_FLAG_ERR_INTR BIT(HCLGE_CMD_FLAG_ERR_INTR_SHIFT)
enum hclge_opcode_type {
/* Generic command */
HCLGE_OPC_QUERY_FW_VER = 0x0001,
HCLGE_OPC_CFG_RST_TRIGGER = 0x0020,
HCLGE_OPC_GBL_RST_STATUS = 0x0021,
HCLGE_OPC_QUERY_FUNC_STATUS = 0x0022,
HCLGE_OPC_QUERY_PF_RSRC = 0x0023,
HCLGE_OPC_QUERY_VF_RSRC = 0x0024,
HCLGE_OPC_GET_CFG_PARAM = 0x0025,
HCLGE_OPC_STATS_64_BIT = 0x0030,
HCLGE_OPC_STATS_32_BIT = 0x0031,
HCLGE_OPC_STATS_MAC = 0x0032,
/* Device management command */
/* MAC commond */
HCLGE_OPC_CONFIG_MAC_MODE = 0x0301,
HCLGE_OPC_CONFIG_AN_MODE = 0x0304,
HCLGE_OPC_QUERY_AN_RESULT = 0x0306,
HCLGE_OPC_QUERY_LINK_STATUS = 0x0307,
HCLGE_OPC_CONFIG_MAX_FRM_SIZE = 0x0308,
HCLGE_OPC_CONFIG_SPEED_DUP = 0x0309,
/* MACSEC command */
/* PFC/Pause CMD*/
HCLGE_OPC_CFG_MAC_PAUSE_EN = 0x0701,
HCLGE_OPC_CFG_PFC_PAUSE_EN = 0x0702,
HCLGE_OPC_CFG_MAC_PARA = 0x0703,
HCLGE_OPC_CFG_PFC_PARA = 0x0704,
HCLGE_OPC_QUERY_MAC_TX_PKT_CNT = 0x0705,
HCLGE_OPC_QUERY_MAC_RX_PKT_CNT = 0x0706,
HCLGE_OPC_QUERY_PFC_TX_PKT_CNT = 0x0707,
HCLGE_OPC_QUERY_PFC_RX_PKT_CNT = 0x0708,
HCLGE_OPC_PRI_TO_TC_MAPPING = 0x0709,
HCLGE_OPC_QOS_MAP = 0x070A,
/* ETS/scheduler commands */
HCLGE_OPC_TM_PG_TO_PRI_LINK = 0x0804,
HCLGE_OPC_TM_QS_TO_PRI_LINK = 0x0805,
HCLGE_OPC_TM_NQ_TO_QS_LINK = 0x0806,
HCLGE_OPC_TM_RQ_TO_QS_LINK = 0x0807,
HCLGE_OPC_TM_PORT_WEIGHT = 0x0808,
HCLGE_OPC_TM_PG_WEIGHT = 0x0809,
HCLGE_OPC_TM_QS_WEIGHT = 0x080A,
HCLGE_OPC_TM_PRI_WEIGHT = 0x080B,
HCLGE_OPC_TM_PRI_C_SHAPPING = 0x080C,
HCLGE_OPC_TM_PRI_P_SHAPPING = 0x080D,
HCLGE_OPC_TM_PG_C_SHAPPING = 0x080E,
HCLGE_OPC_TM_PG_P_SHAPPING = 0x080F,
HCLGE_OPC_TM_PORT_SHAPPING = 0x0810,
HCLGE_OPC_TM_PG_SCH_MODE_CFG = 0x0812,
HCLGE_OPC_TM_PRI_SCH_MODE_CFG = 0x0813,
HCLGE_OPC_TM_QS_SCH_MODE_CFG = 0x0814,
HCLGE_OPC_TM_BP_TO_QSET_MAPPING = 0x0815,
/* Packet buffer allocate command */
HCLGE_OPC_TX_BUFF_ALLOC = 0x0901,
HCLGE_OPC_RX_PRIV_BUFF_ALLOC = 0x0902,
HCLGE_OPC_RX_PRIV_WL_ALLOC = 0x0903,
HCLGE_OPC_RX_COM_THRD_ALLOC = 0x0904,
HCLGE_OPC_RX_COM_WL_ALLOC = 0x0905,
HCLGE_OPC_RX_GBL_PKT_CNT = 0x0906,
/* PTP command */
/* TQP management command */
HCLGE_OPC_SET_TQP_MAP = 0x0A01,
/* TQP command */
HCLGE_OPC_CFG_TX_QUEUE = 0x0B01,
HCLGE_OPC_QUERY_TX_POINTER = 0x0B02,
HCLGE_OPC_QUERY_TX_STATUS = 0x0B03,
HCLGE_OPC_CFG_RX_QUEUE = 0x0B11,
HCLGE_OPC_QUERY_RX_POINTER = 0x0B12,
HCLGE_OPC_QUERY_RX_STATUS = 0x0B13,
HCLGE_OPC_STASH_RX_QUEUE_LRO = 0x0B16,
HCLGE_OPC_CFG_RX_QUEUE_LRO = 0x0B17,
HCLGE_OPC_CFG_COM_TQP_QUEUE = 0x0B20,
HCLGE_OPC_RESET_TQP_QUEUE = 0x0B22,
/* TSO cmd */
HCLGE_OPC_TSO_GENERIC_CONFIG = 0x0C01,
/* RSS cmd */
HCLGE_OPC_RSS_GENERIC_CONFIG = 0x0D01,
HCLGE_OPC_RSS_INDIR_TABLE = 0x0D07,
HCLGE_OPC_RSS_TC_MODE = 0x0D08,
HCLGE_OPC_RSS_INPUT_TUPLE = 0x0D02,
/* Promisuous mode command */
HCLGE_OPC_CFG_PROMISC_MODE = 0x0E01,
/* Interrupts cmd */
HCLGE_OPC_ADD_RING_TO_VECTOR = 0x1503,
HCLGE_OPC_DEL_RING_TO_VECTOR = 0x1504,
/* MAC command */
HCLGE_OPC_MAC_VLAN_ADD = 0x1000,
HCLGE_OPC_MAC_VLAN_REMOVE = 0x1001,
HCLGE_OPC_MAC_VLAN_TYPE_ID = 0x1002,
HCLGE_OPC_MAC_VLAN_INSERT = 0x1003,
HCLGE_OPC_MAC_ETHTYPE_ADD = 0x1010,
HCLGE_OPC_MAC_ETHTYPE_REMOVE = 0x1011,
/* Multicast linear table cmd */
HCLGE_OPC_MTA_MAC_MODE_CFG = 0x1020,
HCLGE_OPC_MTA_MAC_FUNC_CFG = 0x1021,
HCLGE_OPC_MTA_TBL_ITEM_CFG = 0x1022,
HCLGE_OPC_MTA_TBL_ITEM_QUERY = 0x1023,
/* VLAN command */
HCLGE_OPC_VLAN_FILTER_CTRL = 0x1100,
HCLGE_OPC_VLAN_FILTER_PF_CFG = 0x1101,
HCLGE_OPC_VLAN_FILTER_VF_CFG = 0x1102,
/* MDIO command */
HCLGE_OPC_MDIO_CONFIG = 0x1900,
/* QCN command */
HCLGE_OPC_QCN_MOD_CFG = 0x1A01,
HCLGE_OPC_QCN_GRP_TMPLT_CFG = 0x1A02,
HCLGE_OPC_QCN_SHAPPING_IR_CFG = 0x1A03,
HCLGE_OPC_QCN_SHAPPING_BS_CFG = 0x1A04,
HCLGE_OPC_QCN_QSET_LINK_CFG = 0x1A05,
HCLGE_OPC_QCN_RP_STATUS_GET = 0x1A06,
HCLGE_OPC_QCN_AJUST_INIT = 0x1A07,
HCLGE_OPC_QCN_DFX_CNT_STATUS = 0x1A08,
/* Mailbox cmd */
HCLGEVF_OPC_MBX_PF_TO_VF = 0x2000,
};
#define HCLGE_TQP_REG_OFFSET 0x80000
#define HCLGE_TQP_REG_SIZE 0x200
#define HCLGE_RCB_INIT_QUERY_TIMEOUT 10
#define HCLGE_RCB_INIT_FLAG_EN_B 0
#define HCLGE_RCB_INIT_FLAG_FINI_B 8
struct hclge_config_rcb_init {
__le16 rcb_init_flag;
u8 rsv[22];
};
struct hclge_tqp_map {
__le16 tqp_id; /* Absolute tqp id for in this pf */
u8 tqp_vf; /* VF id */
#define HCLGE_TQP_MAP_TYPE_PF 0
#define HCLGE_TQP_MAP_TYPE_VF 1
#define HCLGE_TQP_MAP_TYPE_B 0
#define HCLGE_TQP_MAP_EN_B 1
u8 tqp_flag; /* Indicate it's pf or vf tqp */
__le16 tqp_vid; /* Virtual id in this pf/vf */
u8 rsv[18];
};
#define HCLGE_VECTOR_ELEMENTS_PER_CMD 11
enum hclge_int_type {
HCLGE_INT_TX,
HCLGE_INT_RX,
HCLGE_INT_EVENT,
};
struct hclge_ctrl_vector_chain {
u8 int_vector_id;
u8 int_cause_num;
#define HCLGE_INT_TYPE_S 0
#define HCLGE_INT_TYPE_M 0x3
#define HCLGE_TQP_ID_S 2
#define HCLGE_TQP_ID_M (0x3fff << HCLGE_TQP_ID_S)
__le16 tqp_type_and_id[HCLGE_VECTOR_ELEMENTS_PER_CMD];
};
#define HCLGE_TC_NUM 8
#define HCLGE_TC0_PRI_BUF_EN_B 15 /* Bit 15 indicate enable or not */
#define HCLGE_BUF_UNIT_S 7 /* Buf size is united by 128 bytes */
struct hclge_tx_buff_alloc {
__le16 tx_pkt_buff[HCLGE_TC_NUM];
u8 tx_buff_rsv[8];
};
struct hclge_rx_priv_buff {
__le16 buf_num[HCLGE_TC_NUM];
u8 rsv[8];
};
struct hclge_query_version {
__le32 firmware;
__le32 firmware_rsv[5];
};
#define HCLGE_RX_PRIV_EN_B 15
#define HCLGE_TC_NUM_ONE_DESC 4
struct hclge_priv_wl {
__le16 high;
__le16 low;
};
struct hclge_rx_priv_wl_buf {
struct hclge_priv_wl tc_wl[HCLGE_TC_NUM_ONE_DESC];
};
struct hclge_rx_com_thrd {
struct hclge_priv_wl com_thrd[HCLGE_TC_NUM_ONE_DESC];
};
struct hclge_rx_com_wl {
struct hclge_priv_wl com_wl;
};
struct hclge_waterline {
u32 low;
u32 high;
};
struct hclge_tc_thrd {
u32 low;
u32 high;
};
struct hclge_priv_buf {
struct hclge_waterline wl; /* Waterline for low and high*/
u32 buf_size; /* TC private buffer size */
u32 enable; /* Enable TC private buffer or not */
};
#define HCLGE_MAX_TC_NUM 8
struct hclge_shared_buf {
struct hclge_waterline self;
struct hclge_tc_thrd tc_thrd[HCLGE_MAX_TC_NUM];
u32 buf_size;
};
#define HCLGE_RX_COM_WL_EN_B 15
struct hclge_rx_com_wl_buf {
__le16 high_wl;
__le16 low_wl;
u8 rsv[20];
};
#define HCLGE_RX_PKT_EN_B 15
struct hclge_rx_pkt_buf {
__le16 high_pkt;
__le16 low_pkt;
u8 rsv[20];
};
#define HCLGE_PF_STATE_DONE_B 0
#define HCLGE_PF_STATE_MAIN_B 1
#define HCLGE_PF_STATE_BOND_B 2
#define HCLGE_PF_STATE_MAC_N_B 6
#define HCLGE_PF_MAC_NUM_MASK 0x3
#define HCLGE_PF_STATE_MAIN BIT(HCLGE_PF_STATE_MAIN_B)
#define HCLGE_PF_STATE_DONE BIT(HCLGE_PF_STATE_DONE_B)
struct hclge_func_status {
__le32 vf_rst_state[4];
u8 pf_state;
u8 mac_id;
u8 rsv1;
u8 pf_cnt_in_mac;
u8 pf_num;
u8 vf_num;
u8 rsv[2];
};
struct hclge_pf_res {
__le16 tqp_num;
__le16 buf_size;
__le16 msixcap_localid_ba_nic;
__le16 msixcap_localid_ba_rocee;
#define HCLGE_PF_VEC_NUM_S 0
#define HCLGE_PF_VEC_NUM_M (0xff << HCLGE_PF_VEC_NUM_S)
__le16 pf_intr_vector_number;
__le16 pf_own_fun_number;
__le32 rsv[3];
};
#define HCLGE_CFG_OFFSET_S 0
#define HCLGE_CFG_OFFSET_M 0xfffff /* Byte (8-10.3) */
#define HCLGE_CFG_RD_LEN_S 24
#define HCLGE_CFG_RD_LEN_M (0xf << HCLGE_CFG_RD_LEN_S)
#define HCLGE_CFG_RD_LEN_BYTES 16
#define HCLGE_CFG_RD_LEN_UNIT 4
#define HCLGE_CFG_VMDQ_S 0
#define HCLGE_CFG_VMDQ_M (0xff << HCLGE_CFG_VMDQ_S)
#define HCLGE_CFG_TC_NUM_S 8
#define HCLGE_CFG_TC_NUM_M (0xff << HCLGE_CFG_TC_NUM_S)
#define HCLGE_CFG_TQP_DESC_N_S 16
#define HCLGE_CFG_TQP_DESC_N_M (0xffff << HCLGE_CFG_TQP_DESC_N_S)
#define HCLGE_CFG_PHY_ADDR_S 0
#define HCLGE_CFG_PHY_ADDR_M (0x1f << HCLGE_CFG_PHY_ADDR_S)
#define HCLGE_CFG_MEDIA_TP_S 8
#define HCLGE_CFG_MEDIA_TP_M (0xff << HCLGE_CFG_MEDIA_TP_S)
#define HCLGE_CFG_RX_BUF_LEN_S 16
#define HCLGE_CFG_RX_BUF_LEN_M (0xffff << HCLGE_CFG_RX_BUF_LEN_S)
#define HCLGE_CFG_MAC_ADDR_H_S 0
#define HCLGE_CFG_MAC_ADDR_H_M (0xffff << HCLGE_CFG_MAC_ADDR_H_S)
#define HCLGE_CFG_DEFAULT_SPEED_S 16
#define HCLGE_CFG_DEFAULT_SPEED_M (0xff << HCLGE_CFG_DEFAULT_SPEED_S)
struct hclge_cfg_param {
__le32 offset;
__le32 rsv;
__le32 param[4];
};
#define HCLGE_MAC_MODE 0x0
#define HCLGE_DESC_NUM 0x40
#define HCLGE_ALLOC_VALID_B 0
struct hclge_vf_num {
u8 alloc_valid;
u8 rsv[23];
};
#define HCLGE_RSS_DEFAULT_OUTPORT_B 4
#define HCLGE_RSS_HASH_KEY_OFFSET_B 4
#define HCLGE_RSS_HASH_KEY_NUM 16
struct hclge_rss_config {
u8 hash_config;
u8 rsv[7];
u8 hash_key[HCLGE_RSS_HASH_KEY_NUM];
};
struct hclge_rss_input_tuple {
u8 ipv4_tcp_en;
u8 ipv4_udp_en;
u8 ipv4_sctp_en;
u8 ipv4_fragment_en;
u8 ipv6_tcp_en;
u8 ipv6_udp_en;
u8 ipv6_sctp_en;
u8 ipv6_fragment_en;
u8 rsv[16];
};
#define HCLGE_RSS_CFG_TBL_SIZE 16
struct hclge_rss_indirection_table {
u16 start_table_index;
u16 rss_set_bitmap;
u8 rsv[4];
u8 rss_result[HCLGE_RSS_CFG_TBL_SIZE];
};
#define HCLGE_RSS_TC_OFFSET_S 0
#define HCLGE_RSS_TC_OFFSET_M (0x3ff << HCLGE_RSS_TC_OFFSET_S)
#define HCLGE_RSS_TC_SIZE_S 12
#define HCLGE_RSS_TC_SIZE_M (0x7 << HCLGE_RSS_TC_SIZE_S)
#define HCLGE_RSS_TC_VALID_B 15
struct hclge_rss_tc_mode {
u16 rss_tc_mode[HCLGE_MAX_TC_NUM];
u8 rsv[8];
};
#define HCLGE_LINK_STS_B 0
#define HCLGE_LINK_STATUS BIT(HCLGE_LINK_STS_B)
struct hclge_link_status {
u8 status;
u8 rsv[23];
};
struct hclge_promisc_param {
u8 vf_id;
u8 enable;
};
#define HCLGE_PROMISC_EN_B 1
#define HCLGE_PROMISC_EN_ALL 0x7
#define HCLGE_PROMISC_EN_UC 0x1
#define HCLGE_PROMISC_EN_MC 0x2
#define HCLGE_PROMISC_EN_BC 0x4
struct hclge_promisc_cfg {
u8 flag;
u8 vf_id;
__le16 rsv0;
u8 rsv1[20];
};
enum hclge_promisc_type {
HCLGE_UNICAST = 1,
HCLGE_MULTICAST = 2,
HCLGE_BROADCAST = 3,
};
#define HCLGE_MAC_TX_EN_B 6
#define HCLGE_MAC_RX_EN_B 7
#define HCLGE_MAC_PAD_TX_B 11
#define HCLGE_MAC_PAD_RX_B 12
#define HCLGE_MAC_1588_TX_B 13
#define HCLGE_MAC_1588_RX_B 14
#define HCLGE_MAC_APP_LP_B 15
#define HCLGE_MAC_LINE_LP_B 16
#define HCLGE_MAC_FCS_TX_B 17
#define HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B 18
#define HCLGE_MAC_RX_FCS_STRIP_B 19
#define HCLGE_MAC_RX_FCS_B 20
#define HCLGE_MAC_TX_UNDER_MIN_ERR_B 21
#define HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B 22
struct hclge_config_mac_mode {
__le32 txrx_pad_fcs_loop_en;
u8 rsv[20];
};
#define HCLGE_CFG_SPEED_S 0
#define HCLGE_CFG_SPEED_M (0x3f << HCLGE_CFG_SPEED_S)
#define HCLGE_CFG_DUPLEX_B 7
#define HCLGE_CFG_DUPLEX_M BIT(HCLGE_CFG_DUPLEX_B)
struct hclge_config_mac_speed_dup {
u8 speed_dup;
#define HCLGE_CFG_MAC_SPEED_CHANGE_EN_B 0
u8 mac_change_fec_en;
u8 rsv[22];
};
#define HCLGE_QUERY_SPEED_S 3
#define HCLGE_QUERY_AN_B 0
#define HCLGE_QUERY_DUPLEX_B 2
#define HCLGE_QUERY_SPEED_M (0x1f << HCLGE_QUERY_SPEED_S)
#define HCLGE_QUERY_AN_M BIT(HCLGE_QUERY_AN_B)
#define HCLGE_QUERY_DUPLEX_M BIT(HCLGE_QUERY_DUPLEX_B)
struct hclge_query_an_speed_dup {
u8 an_syn_dup_speed;
u8 pause;
u8 rsv[23];
};
#define HCLGE_RING_ID_MASK 0x3ff
#define HCLGE_TQP_ENABLE_B 0
#define HCLGE_MAC_CFG_AN_EN_B 0
#define HCLGE_MAC_CFG_AN_INT_EN_B 1
#define HCLGE_MAC_CFG_AN_INT_MSK_B 2
#define HCLGE_MAC_CFG_AN_INT_CLR_B 3
#define HCLGE_MAC_CFG_AN_RST_B 4
#define HCLGE_MAC_CFG_AN_EN BIT(HCLGE_MAC_CFG_AN_EN_B)
struct hclge_config_auto_neg {
__le32 cfg_an_cmd_flag;
u8 rsv[20];
};
#define HCLGE_MAC_MIN_MTU 64
#define HCLGE_MAC_MAX_MTU 9728
#define HCLGE_MAC_UPLINK_PORT 0x100
struct hclge_config_max_frm_size {
__le16 max_frm_size;
u8 rsv[22];
};
enum hclge_mac_vlan_tbl_opcode {
HCLGE_MAC_VLAN_ADD, /* Add new or modify mac_vlan */
HCLGE_MAC_VLAN_UPDATE, /* Modify other fields of this table */
HCLGE_MAC_VLAN_REMOVE, /* Remove a entry through mac_vlan key */
HCLGE_MAC_VLAN_LKUP, /* Lookup a entry through mac_vlan key */
};
#define HCLGE_MAC_VLAN_BIT0_EN_B 0x0
#define HCLGE_MAC_VLAN_BIT1_EN_B 0x1
#define HCLGE_MAC_EPORT_SW_EN_B 0xc
#define HCLGE_MAC_EPORT_TYPE_B 0xb
#define HCLGE_MAC_EPORT_VFID_S 0x3
#define HCLGE_MAC_EPORT_VFID_M (0xff << HCLGE_MAC_EPORT_VFID_S)
#define HCLGE_MAC_EPORT_PFID_S 0x0
#define HCLGE_MAC_EPORT_PFID_M (0x7 << HCLGE_MAC_EPORT_PFID_S)
struct hclge_mac_vlan_tbl_entry {
u8 flags;
u8 resp_code;
__le16 vlan_tag;
__le32 mac_addr_hi32;
__le16 mac_addr_lo16;
__le16 rsv1;
u8 entry_type;
u8 mc_mac_en;
__le16 egress_port;
__le16 egress_queue;
u8 rsv2[6];
};
#define HCLGE_CFG_MTA_MAC_SEL_S 0x0
#define HCLGE_CFG_MTA_MAC_SEL_M (0x3 << HCLGE_CFG_MTA_MAC_SEL_S)
#define HCLGE_CFG_MTA_MAC_EN_B 0x7
struct hclge_mta_filter_mode {
u8 dmac_sel_en; /* Use lowest 2 bit as sel_mode, bit 7 as enable */
u8 rsv[23];
};
#define HCLGE_CFG_FUNC_MTA_ACCEPT_B 0x0
struct hclge_cfg_func_mta_filter {
u8 accept; /* Only used lowest 1 bit */
u8 function_id;
u8 rsv[22];
};
#define HCLGE_CFG_MTA_ITEM_ACCEPT_B 0x0
#define HCLGE_CFG_MTA_ITEM_IDX_S 0x0
#define HCLGE_CFG_MTA_ITEM_IDX_M (0xfff << HCLGE_CFG_MTA_ITEM_IDX_S)
struct hclge_cfg_func_mta_item {
u16 item_idx; /* Only used lowest 12 bit */
u8 accept; /* Only used lowest 1 bit */
u8 rsv[21];
};
struct hclge_mac_vlan_add {
__le16 flags;
__le16 mac_addr_hi16;
__le32 mac_addr_lo32;
__le32 mac_addr_msk_hi32;
__le16 mac_addr_msk_lo16;
__le16 vlan_tag;
__le16 ingress_port;
__le16 egress_port;
u8 rsv[4];
};
#define HNS3_MAC_VLAN_CFG_FLAG_BIT 0
struct hclge_mac_vlan_remove {
__le16 flags;
__le16 mac_addr_hi16;
__le32 mac_addr_lo32;
__le32 mac_addr_msk_hi32;
__le16 mac_addr_msk_lo16;
__le16 vlan_tag;
__le16 ingress_port;
__le16 egress_port;
u8 rsv[4];
};
struct hclge_vlan_filter_ctrl {
u8 vlan_type;
u8 vlan_fe;
u8 rsv[22];
};
struct hclge_vlan_filter_pf_cfg {
u8 vlan_offset;
u8 vlan_cfg;
u8 rsv[2];
u8 vlan_offset_bitmap[20];
};
struct hclge_vlan_filter_vf_cfg {
u16 vlan_id;
u8 resp_code;
u8 rsv;
u8 vlan_cfg;
u8 rsv1[3];
u8 vf_bitmap[16];
};
struct hclge_cfg_com_tqp_queue {
__le16 tqp_id;
__le16 stream_id;
u8 enable;
u8 rsv[19];
};
struct hclge_cfg_tx_queue_pointer {
__le16 tqp_id;
__le16 tx_tail;
__le16 tx_head;
__le16 fbd_num;
__le16 ring_offset;
u8 rsv[14];
};
#define HCLGE_TSO_MSS_MIN_S 0
#define HCLGE_TSO_MSS_MIN_M (0x3FFF << HCLGE_TSO_MSS_MIN_S)
#define HCLGE_TSO_MSS_MAX_S 16
#define HCLGE_TSO_MSS_MAX_M (0x3FFF << HCLGE_TSO_MSS_MAX_S)
struct hclge_cfg_tso_status {
__le16 tso_mss_min;
__le16 tso_mss_max;
u8 rsv[20];
};
#define HCLGE_TSO_MSS_MIN 256
#define HCLGE_TSO_MSS_MAX 9668
#define HCLGE_TQP_RESET_B 0
struct hclge_reset_tqp_queue {
__le16 tqp_id;
u8 reset_req;
u8 ready_to_reset;
u8 rsv[20];
};
#define HCLGE_DEFAULT_TX_BUF 0x4000 /* 16k bytes */
#define HCLGE_TOTAL_PKT_BUF 0x108000 /* 1.03125M bytes */
#define HCLGE_DEFAULT_DV 0xA000 /* 40k byte */
#define HCLGE_TYPE_CRQ 0
#define HCLGE_TYPE_CSQ 1
#define HCLGE_NIC_CSQ_BASEADDR_L_REG 0x27000
#define HCLGE_NIC_CSQ_BASEADDR_H_REG 0x27004
#define HCLGE_NIC_CSQ_DEPTH_REG 0x27008
#define HCLGE_NIC_CSQ_TAIL_REG 0x27010
#define HCLGE_NIC_CSQ_HEAD_REG 0x27014
#define HCLGE_NIC_CRQ_BASEADDR_L_REG 0x27018
#define HCLGE_NIC_CRQ_BASEADDR_H_REG 0x2701c
#define HCLGE_NIC_CRQ_DEPTH_REG 0x27020
#define HCLGE_NIC_CRQ_TAIL_REG 0x27024
#define HCLGE_NIC_CRQ_HEAD_REG 0x27028
#define HCLGE_NIC_CMQ_EN_B 16
#define HCLGE_NIC_CMQ_ENABLE BIT(HCLGE_NIC_CMQ_EN_B)
#define HCLGE_NIC_CMQ_DESC_NUM 1024
#define HCLGE_NIC_CMQ_DESC_NUM_S 3
int hclge_cmd_init(struct hclge_dev *hdev);
static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
{
writel(value, base + reg);
}
#define hclge_write_dev(a, reg, value) \
hclge_write_reg((a)->io_base, (reg), (value))
#define hclge_read_dev(a, reg) \
hclge_read_reg((a)->io_base, (reg))
static inline u32 hclge_read_reg(u8 __iomem *base, u32 reg)
{
u8 __iomem *reg_addr = READ_ONCE(base);
return readl(reg_addr + reg);
}
#define HCLGE_SEND_SYNC(flag) \
((flag) & HCLGE_CMD_FLAG_NO_INTR)
struct hclge_hw;
int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num);
void hclge_cmd_setup_basic_desc(struct hclge_desc *desc,
enum hclge_opcode_type opcode, bool is_read);
int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev,
struct hclge_promisc_param *param);
enum hclge_cmd_status hclge_cmd_mdio_write(struct hclge_hw *hw,
struct hclge_desc *desc);
enum hclge_cmd_status hclge_cmd_mdio_read(struct hclge_hw *hw,
struct hclge_desc *desc);
void hclge_destroy_cmd_queue(struct hclge_hw *hw);
#endif
此差异已折叠。
/*
* Copyright (c) 2016~2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __HCLGE_MAIN_H
#define __HCLGE_MAIN_H
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/phy.h>
#include "hclge_cmd.h"
#include "hnae3.h"
#define HCLGE_MOD_VERSION "v1.0"
#define HCLGE_DRIVER_NAME "hclge"
#define HCLGE_INVALID_VPORT 0xffff
#define HCLGE_ROCE_VECTOR_OFFSET 96
#define HCLGE_PF_CFG_BLOCK_SIZE 32
#define HCLGE_PF_CFG_DESC_NUM \
(HCLGE_PF_CFG_BLOCK_SIZE / HCLGE_CFG_RD_LEN_BYTES)
#define HCLGE_VECTOR_REG_BASE 0x20000
#define HCLGE_VECTOR_REG_OFFSET 0x4
#define HCLGE_VECTOR_VF_OFFSET 0x100000
#define HCLGE_RSS_IND_TBL_SIZE 512
#define HCLGE_RSS_SET_BITMAP_MSK 0xffff
#define HCLGE_RSS_KEY_SIZE 40
#define HCLGE_RSS_HASH_ALGO_TOEPLITZ 0
#define HCLGE_RSS_HASH_ALGO_SIMPLE 1
#define HCLGE_RSS_HASH_ALGO_SYMMETRIC 2
#define HCLGE_RSS_HASH_ALGO_MASK 0xf
#define HCLGE_RSS_CFG_TBL_NUM \
(HCLGE_RSS_IND_TBL_SIZE / HCLGE_RSS_CFG_TBL_SIZE)
#define HCLGE_RSS_TC_SIZE_0 1
#define HCLGE_RSS_TC_SIZE_1 2
#define HCLGE_RSS_TC_SIZE_2 4
#define HCLGE_RSS_TC_SIZE_3 8
#define HCLGE_RSS_TC_SIZE_4 16
#define HCLGE_RSS_TC_SIZE_5 32
#define HCLGE_RSS_TC_SIZE_6 64
#define HCLGE_RSS_TC_SIZE_7 128
#define HCLGE_TQP_RESET_TRY_TIMES 10
#define HCLGE_PHY_PAGE_MDIX 0
#define HCLGE_PHY_PAGE_COPPER 0
/* Page Selection Reg. */
#define HCLGE_PHY_PAGE_REG 22
/* Copper Specific Control Register */
#define HCLGE_PHY_CSC_REG 16
/* Copper Specific Status Register */
#define HCLGE_PHY_CSS_REG 17
#define HCLGE_PHY_MDIX_CTRL_S (5)
#define HCLGE_PHY_MDIX_CTRL_M (3 << HCLGE_PHY_MDIX_CTRL_S)
#define HCLGE_PHY_MDIX_STATUS_B (6)
#define HCLGE_PHY_SPEED_DUP_RESOLVE_B (11)
enum HCLGE_DEV_STATE {
HCLGE_STATE_REINITING,
HCLGE_STATE_DOWN,
HCLGE_STATE_DISABLED,
HCLGE_STATE_REMOVING,
HCLGE_STATE_SERVICE_INITED,
HCLGE_STATE_SERVICE_SCHED,
HCLGE_STATE_MBX_HANDLING,
HCLGE_STATE_MBX_IRQ,
HCLGE_STATE_MAX
};
#define HCLGE_MPF_ENBALE 1
struct hclge_caps {
u16 num_tqp;
u16 num_buffer_cell;
u32 flag;
u16 vmdq;
};
enum HCLGE_MAC_SPEED {
HCLGE_MAC_SPEED_10M = 10, /* 10 Mbps */
HCLGE_MAC_SPEED_100M = 100, /* 100 Mbps */
HCLGE_MAC_SPEED_1G = 1000, /* 1000 Mbps = 1 Gbps */
HCLGE_MAC_SPEED_10G = 10000, /* 10000 Mbps = 10 Gbps */
HCLGE_MAC_SPEED_25G = 25000, /* 25000 Mbps = 25 Gbps */
HCLGE_MAC_SPEED_40G = 40000, /* 40000 Mbps = 40 Gbps */
HCLGE_MAC_SPEED_50G = 50000, /* 50000 Mbps = 50 Gbps */
HCLGE_MAC_SPEED_100G = 100000 /* 100000 Mbps = 100 Gbps */
};
enum HCLGE_MAC_DUPLEX {
HCLGE_MAC_HALF,
HCLGE_MAC_FULL
};
enum hclge_mta_dmac_sel_type {
HCLGE_MAC_ADDR_47_36,
HCLGE_MAC_ADDR_46_35,
HCLGE_MAC_ADDR_45_34,
HCLGE_MAC_ADDR_44_33,
};
struct hclge_mac {
u8 phy_addr;
u8 flag;
u8 media_type;
u8 mac_addr[ETH_ALEN];
u8 autoneg;
u8 duplex;
u32 speed;
int link; /* store the link status of mac & phy (if phy exit)*/
struct phy_device *phydev;
struct mii_bus *mdio_bus;
phy_interface_t phy_if;
};
struct hclge_hw {
void __iomem *io_base;
struct hclge_mac mac;
int num_vec;
struct hclge_cmq cmq;
struct hclge_caps caps;
void *back;
};
/* TQP stats */
struct hlcge_tqp_stats {
/* query_tqp_tx_queue_statistics ,opcode id: 0x0B03 */
u64 rcb_tx_ring_pktnum_rcd; /* 32bit */
/* query_tqp_rx_queue_statistics ,opcode id: 0x0B13 */
u64 rcb_rx_ring_pktnum_rcd; /* 32bit */
};
struct hclge_tqp {
struct device *dev; /* Device for DMA mapping */
struct hnae3_queue q;
struct hlcge_tqp_stats tqp_stats;
u16 index; /* Global index in a NIC controller */
bool alloced;
};
enum hclge_fc_mode {
HCLGE_FC_NONE,
HCLGE_FC_RX_PAUSE,
HCLGE_FC_TX_PAUSE,
HCLGE_FC_FULL,
HCLGE_FC_PFC,
HCLGE_FC_DEFAULT
};
#define HCLGE_PG_NUM 4
#define HCLGE_SCH_MODE_SP 0
#define HCLGE_SCH_MODE_DWRR 1
struct hclge_pg_info {
u8 pg_id;
u8 pg_sch_mode; /* 0: sp; 1: dwrr */
u8 tc_bit_map;
u32 bw_limit;
u8 tc_dwrr[HNAE3_MAX_TC];
};
struct hclge_tc_info {
u8 tc_id;
u8 tc_sch_mode; /* 0: sp; 1: dwrr */
u8 up;
u8 pgid;
u32 bw_limit;
};
struct hclge_cfg {
u8 vmdq_vport_num;
u8 tc_num;
u16 tqp_desc_num;
u16 rx_buf_len;
u8 phy_addr;
u8 media_type;
u8 mac_addr[ETH_ALEN];
u8 default_speed;
u32 numa_node_map;
};
struct hclge_tm_info {
u8 num_tc;
u8 num_pg; /* It must be 1 if vNET-Base schd */
u8 pg_dwrr[HCLGE_PG_NUM];
struct hclge_pg_info pg_info[HCLGE_PG_NUM];
struct hclge_tc_info tc_info[HNAE3_MAX_TC];
enum hclge_fc_mode fc_mode;
u8 hw_pfc_map; /* Allow for packet drop or not on this TC */
};
struct hclge_comm_stats_str {
char desc[ETH_GSTRING_LEN];
unsigned long offset;
};
/* all 64bit stats, opcode id: 0x0030 */
struct hclge_64_bit_stats {
/* query_igu_stat */
u64 igu_rx_oversize_pkt;
u64 igu_rx_undersize_pkt;
u64 igu_rx_out_all_pkt;
u64 igu_rx_uni_pkt;
u64 igu_rx_multi_pkt;
u64 igu_rx_broad_pkt;
u64 rsv0;
/* query_egu_stat */
u64 egu_tx_out_all_pkt;
u64 egu_tx_uni_pkt;
u64 egu_tx_multi_pkt;
u64 egu_tx_broad_pkt;
/* ssu_ppp packet stats */
u64 ssu_ppp_mac_key_num;
u64 ssu_ppp_host_key_num;
u64 ppp_ssu_mac_rlt_num;
u64 ppp_ssu_host_rlt_num;
/* ssu_tx_in_out_dfx_stats */
u64 ssu_tx_in_num;
u64 ssu_tx_out_num;
/* ssu_rx_in_out_dfx_stats */
u64 ssu_rx_in_num;
u64 ssu_rx_out_num;
};
/* all 32bit stats, opcode id: 0x0031 */
struct hclge_32_bit_stats {
u64 igu_rx_err_pkt;
u64 igu_rx_no_eof_pkt;
u64 igu_rx_no_sof_pkt;
u64 egu_tx_1588_pkt;
u64 egu_tx_err_pkt;
u64 ssu_full_drop_num;
u64 ssu_part_drop_num;
u64 ppp_key_drop_num;
u64 ppp_rlt_drop_num;
u64 ssu_key_drop_num;
u64 pkt_curr_buf_cnt;
u64 qcn_fb_rcv_cnt;
u64 qcn_fb_drop_cnt;
u64 qcn_fb_invaild_cnt;
u64 rsv0;
u64 rx_packet_tc0_in_cnt;
u64 rx_packet_tc1_in_cnt;
u64 rx_packet_tc2_in_cnt;
u64 rx_packet_tc3_in_cnt;
u64 rx_packet_tc4_in_cnt;
u64 rx_packet_tc5_in_cnt;
u64 rx_packet_tc6_in_cnt;
u64 rx_packet_tc7_in_cnt;
u64 rx_packet_tc0_out_cnt;
u64 rx_packet_tc1_out_cnt;
u64 rx_packet_tc2_out_cnt;
u64 rx_packet_tc3_out_cnt;
u64 rx_packet_tc4_out_cnt;
u64 rx_packet_tc5_out_cnt;
u64 rx_packet_tc6_out_cnt;
u64 rx_packet_tc7_out_cnt;
/* Tx packet level statistics */
u64 tx_packet_tc0_in_cnt;
u64 tx_packet_tc1_in_cnt;
u64 tx_packet_tc2_in_cnt;
u64 tx_packet_tc3_in_cnt;
u64 tx_packet_tc4_in_cnt;
u64 tx_packet_tc5_in_cnt;
u64 tx_packet_tc6_in_cnt;
u64 tx_packet_tc7_in_cnt;
u64 tx_packet_tc0_out_cnt;
u64 tx_packet_tc1_out_cnt;
u64 tx_packet_tc2_out_cnt;
u64 tx_packet_tc3_out_cnt;
u64 tx_packet_tc4_out_cnt;
u64 tx_packet_tc5_out_cnt;
u64 tx_packet_tc6_out_cnt;
u64 tx_packet_tc7_out_cnt;
/* packet buffer statistics */
u64 pkt_curr_buf_tc0_cnt;
u64 pkt_curr_buf_tc1_cnt;
u64 pkt_curr_buf_tc2_cnt;
u64 pkt_curr_buf_tc3_cnt;
u64 pkt_curr_buf_tc4_cnt;
u64 pkt_curr_buf_tc5_cnt;
u64 pkt_curr_buf_tc6_cnt;
u64 pkt_curr_buf_tc7_cnt;
u64 mb_uncopy_num;
u64 lo_pri_unicast_rlt_drop_num;
u64 hi_pri_multicast_rlt_drop_num;
u64 lo_pri_multicast_rlt_drop_num;
u64 rx_oq_drop_pkt_cnt;
u64 tx_oq_drop_pkt_cnt;
u64 nic_l2_err_drop_pkt_cnt;
u64 roc_l2_err_drop_pkt_cnt;
};
/* mac stats ,opcode id: 0x0032 */
struct hclge_mac_stats {
u64 mac_tx_mac_pause_num;
u64 mac_rx_mac_pause_num;
u64 mac_tx_pfc_pri0_pkt_num;
u64 mac_tx_pfc_pri1_pkt_num;
u64 mac_tx_pfc_pri2_pkt_num;
u64 mac_tx_pfc_pri3_pkt_num;
u64 mac_tx_pfc_pri4_pkt_num;
u64 mac_tx_pfc_pri5_pkt_num;
u64 mac_tx_pfc_pri6_pkt_num;
u64 mac_tx_pfc_pri7_pkt_num;
u64 mac_rx_pfc_pri0_pkt_num;
u64 mac_rx_pfc_pri1_pkt_num;
u64 mac_rx_pfc_pri2_pkt_num;
u64 mac_rx_pfc_pri3_pkt_num;
u64 mac_rx_pfc_pri4_pkt_num;
u64 mac_rx_pfc_pri5_pkt_num;
u64 mac_rx_pfc_pri6_pkt_num;
u64 mac_rx_pfc_pri7_pkt_num;
u64 mac_tx_total_pkt_num;
u64 mac_tx_total_oct_num;
u64 mac_tx_good_pkt_num;
u64 mac_tx_bad_pkt_num;
u64 mac_tx_good_oct_num;
u64 mac_tx_bad_oct_num;
u64 mac_tx_uni_pkt_num;
u64 mac_tx_multi_pkt_num;
u64 mac_tx_broad_pkt_num;
u64 mac_tx_undersize_pkt_num;
u64 mac_tx_overrsize_pkt_num;
u64 mac_tx_64_oct_pkt_num;
u64 mac_tx_65_127_oct_pkt_num;
u64 mac_tx_128_255_oct_pkt_num;
u64 mac_tx_256_511_oct_pkt_num;
u64 mac_tx_512_1023_oct_pkt_num;
u64 mac_tx_1024_1518_oct_pkt_num;
u64 mac_tx_1519_max_oct_pkt_num;
u64 mac_rx_total_pkt_num;
u64 mac_rx_total_oct_num;
u64 mac_rx_good_pkt_num;
u64 mac_rx_bad_pkt_num;
u64 mac_rx_good_oct_num;
u64 mac_rx_bad_oct_num;
u64 mac_rx_uni_pkt_num;
u64 mac_rx_multi_pkt_num;
u64 mac_rx_broad_pkt_num;
u64 mac_rx_undersize_pkt_num;
u64 mac_rx_overrsize_pkt_num;
u64 mac_rx_64_oct_pkt_num;
u64 mac_rx_65_127_oct_pkt_num;
u64 mac_rx_128_255_oct_pkt_num;
u64 mac_rx_256_511_oct_pkt_num;
u64 mac_rx_512_1023_oct_pkt_num;
u64 mac_rx_1024_1518_oct_pkt_num;
u64 mac_rx_1519_max_oct_pkt_num;
u64 mac_trans_fragment_pkt_num;
u64 mac_trans_undermin_pkt_num;
u64 mac_trans_jabber_pkt_num;
u64 mac_trans_err_all_pkt_num;
u64 mac_trans_from_app_good_pkt_num;
u64 mac_trans_from_app_bad_pkt_num;
u64 mac_rcv_fragment_pkt_num;
u64 mac_rcv_undermin_pkt_num;
u64 mac_rcv_jabber_pkt_num;
u64 mac_rcv_fcs_err_pkt_num;
u64 mac_rcv_send_app_good_pkt_num;
u64 mac_rcv_send_app_bad_pkt_num;
};
struct hclge_hw_stats {
struct hclge_mac_stats mac_stats;
struct hclge_64_bit_stats all_64_bit_stats;
struct hclge_32_bit_stats all_32_bit_stats;
};
struct hclge_dev {
struct pci_dev *pdev;
struct hnae3_ae_dev *ae_dev;
struct hclge_hw hw;
struct hclge_hw_stats hw_stats;
unsigned long state;
u32 fw_version;
u16 num_vmdq_vport; /* Num vmdq vport this PF has set up */
u16 num_tqps; /* Num task queue pairs of this PF */
u16 num_req_vfs; /* Num VFs requested for this PF */
u16 num_roce_msix; /* Num of roce vectors for this PF */
int roce_base_vector;
/* Base task tqp physical id of this PF */
u16 base_tqp_pid;
u16 alloc_rss_size; /* Allocated RSS task queue */
u16 rss_size_max; /* HW defined max RSS task queue */
/* Num of guaranteed filters for this PF */
u16 fdir_pf_filter_count;
u16 num_alloc_vport; /* Num vports this driver supports */
u32 numa_node_mask;
u16 rx_buf_len;
u16 num_desc;
u8 hw_tc_map;
u8 tc_num_last_time;
enum hclge_fc_mode fc_mode_last_time;
#define HCLGE_FLAG_TC_BASE_SCH_MODE 1
#define HCLGE_FLAG_VNET_BASE_SCH_MODE 2
u8 tx_sch_mode;
u8 default_up;
struct hclge_tm_info tm_info;
u16 num_msi;
u16 num_msi_left;
u16 num_msi_used;
u32 base_msi_vector;
struct msix_entry *msix_entries;
u16 *vector_status;
u16 pending_udp_bitmap;
u16 rx_itr_default;
u16 tx_itr_default;
u16 adminq_work_limit; /* Num of admin receive queue desc to process */
unsigned long service_timer_period;
unsigned long service_timer_previous;
struct timer_list service_timer;
struct work_struct service_task;
bool cur_promisc;
int num_alloc_vfs; /* Actual number of VFs allocated */
struct hclge_tqp *htqp;
struct hclge_vport *vport;
struct dentry *hclge_dbgfs;
struct hnae3_client *nic_client;
struct hnae3_client *roce_client;
#define HCLGE_FLAG_USE_MSI 0x00000001
#define HCLGE_FLAG_USE_MSIX 0x00000002
#define HCLGE_FLAG_MAIN 0x00000004
#define HCLGE_FLAG_DCB_CAPABLE 0x00000008
#define HCLGE_FLAG_DCB_ENABLE 0x00000010
u32 flag;
u32 pkt_buf_size; /* Total pf buf size for tx/rx */
u32 mps; /* Max packet size */
struct hclge_priv_buf *priv_buf;
struct hclge_shared_buf s_buf;
enum hclge_mta_dmac_sel_type mta_mac_sel_type;
bool enable_mta; /* Mutilcast filter enable */
bool accept_mta_mc; /* Whether accept mta filter multicast */
};
struct hclge_vport {
u16 alloc_tqps; /* Allocated Tx/Rx queues */
u8 rss_hash_key[HCLGE_RSS_KEY_SIZE]; /* User configured hash keys */
/* User configured lookup table entries */
u8 rss_indirection_tbl[HCLGE_RSS_IND_TBL_SIZE];
u16 qs_offset;
u16 bw_limit; /* VSI BW Limit (0 = disabled) */
u8 dwrr;
int vport_id;
struct hclge_dev *back; /* Back reference to associated dev */
struct hnae3_handle nic;
struct hnae3_handle roce;
};
void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
bool en_mc, bool en_bc, int vport_id);
int hclge_add_uc_addr_common(struct hclge_vport *vport,
const unsigned char *addr);
int hclge_rm_uc_addr_common(struct hclge_vport *vport,
const unsigned char *addr);
int hclge_add_mc_addr_common(struct hclge_vport *vport,
const unsigned char *addr);
int hclge_rm_mc_addr_common(struct hclge_vport *vport,
const unsigned char *addr);
int hclge_cfg_func_mta_filter(struct hclge_dev *hdev,
u8 func_id,
bool enable);
struct hclge_vport *hclge_get_vport(struct hnae3_handle *handle);
int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector,
struct hnae3_ring_chain_node *ring_chain);
static inline int hclge_get_queue_id(struct hnae3_queue *queue)
{
struct hclge_tqp *tqp = container_of(queue, struct hclge_tqp, q);
return tqp->index;
}
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex);
int hclge_set_vf_vlan_common(struct hclge_dev *vport, int vfid,
bool is_kill, u16 vlan, u8 qos, __be16 proto);
#endif
/*
* Copyright (c) 2016~2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include "hclge_cmd.h"
#include "hclge_main.h"
#include "hclge_mdio.h"
enum hclge_mdio_c22_op_seq {
HCLGE_MDIO_C22_WRITE = 1,
HCLGE_MDIO_C22_READ = 2
};
#define HCLGE_MDIO_CTRL_START_B 0
#define HCLGE_MDIO_CTRL_ST_S 1
#define HCLGE_MDIO_CTRL_ST_M (0x3 << HCLGE_MDIO_CTRL_ST_S)
#define HCLGE_MDIO_CTRL_OP_S 3
#define HCLGE_MDIO_CTRL_OP_M (0x3 << HCLGE_MDIO_CTRL_OP_S)
#define HCLGE_MDIO_PHYID_S 0
#define HCLGE_MDIO_PHYID_M (0x1f << HCLGE_MDIO_PHYID_S)
#define HCLGE_MDIO_PHYREG_S 0
#define HCLGE_MDIO_PHYREG_M (0x1f << HCLGE_MDIO_PHYREG_S)
#define HCLGE_MDIO_STA_B 0
struct hclge_mdio_cfg_cmd {
u8 ctrl_bit;
u8 phyid;
u8 phyad;
u8 rsvd;
__le16 reserve;
__le16 data_wr;
__le16 data_rd;
__le16 sta;
};
static int hclge_mdio_write(struct mii_bus *bus, int phyid, int regnum,
u16 data)
{
struct hclge_mdio_cfg_cmd *mdio_cmd;
struct hclge_dev *hdev = bus->priv;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, false);
mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
hnae_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
HCLGE_MDIO_PHYID_S, phyid);
hnae_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
HCLGE_MDIO_PHYREG_S, regnum);
hnae_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
HCLGE_MDIO_CTRL_ST_S, 1);
hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_WRITE);
mdio_cmd->data_wr = cpu_to_le16(data);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"mdio write fail when sending cmd, status is %d.\n",
ret);
return ret;
}
return 0;
}
static int hclge_mdio_read(struct mii_bus *bus, int phyid, int regnum)
{
struct hclge_mdio_cfg_cmd *mdio_cmd;
struct hclge_dev *hdev = bus->priv;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, true);
mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
hnae_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
HCLGE_MDIO_PHYID_S, phyid);
hnae_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
HCLGE_MDIO_PHYREG_S, regnum);
hnae_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
HCLGE_MDIO_CTRL_ST_S, 1);
hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_READ);
/* Read out phy data */
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"mdio read fail when get data, status is %d.\n",
ret);
return ret;
}
if (hnae_get_bit(le16_to_cpu(mdio_cmd->sta), HCLGE_MDIO_STA_B)) {
dev_err(&hdev->pdev->dev, "mdio read data error\n");
return -EIO;
}
return le16_to_cpu(mdio_cmd->data_rd);
}
int hclge_mac_mdio_config(struct hclge_dev *hdev)
{
struct hclge_mac *mac = &hdev->hw.mac;
struct phy_device *phydev;
struct mii_bus *mdio_bus;
int ret;
if (hdev->hw.mac.phy_addr >= PHY_MAX_ADDR)
return 0;
mdio_bus = devm_mdiobus_alloc(&hdev->pdev->dev);
if (!mdio_bus)
return -ENOMEM;
mdio_bus->name = "hisilicon MII bus";
mdio_bus->read = hclge_mdio_read;
mdio_bus->write = hclge_mdio_write;
snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "mii",
dev_name(&hdev->pdev->dev));
mdio_bus->parent = &hdev->pdev->dev;
mdio_bus->priv = hdev;
mdio_bus->phy_mask = ~(1 << mac->phy_addr);
ret = mdiobus_register(mdio_bus);
if (ret) {
dev_err(mdio_bus->parent,
"Failed to register MDIO bus ret = %#x\n", ret);
return ret;
}
phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr);
if (!phydev || IS_ERR(phydev)) {
dev_err(mdio_bus->parent, "Failed to get phy device\n");
mdiobus_unregister(mdio_bus);
return -EIO;
}
mac->phydev = phydev;
mac->mdio_bus = mdio_bus;
return 0;
}
static void hclge_mac_adjust_link(struct net_device *netdev)
{
struct hnae3_handle *h = *((void **)netdev_priv(netdev));
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
int duplex, speed;
int ret;
speed = netdev->phydev->speed;
duplex = netdev->phydev->duplex;
ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
if (ret)
netdev_err(netdev, "failed to adjust link.\n");
}
int hclge_mac_start_phy(struct hclge_dev *hdev)
{
struct net_device *netdev = hdev->vport[0].nic.netdev;
struct phy_device *phydev = hdev->hw.mac.phydev;
int ret;
if (!phydev)
return 0;
ret = phy_connect_direct(netdev, phydev,
hclge_mac_adjust_link,
PHY_INTERFACE_MODE_SGMII);
if (ret) {
netdev_err(netdev, "phy_connect_direct err.\n");
return ret;
}
phy_start(phydev);
return 0;
}
void hclge_mac_stop_phy(struct hclge_dev *hdev)
{
struct net_device *netdev = hdev->vport[0].nic.netdev;
struct phy_device *phydev = netdev->phydev;
if (!phydev)
return;
phy_stop(phydev);
phy_disconnect(phydev);
}
/*
* Copyright (c) 2016-2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __HCLGE_MDIO_H
#define __HCLGE_MDIO_H
int hclge_mac_mdio_config(struct hclge_dev *hdev);
int hclge_mac_start_phy(struct hclge_dev *hdev);
void hclge_mac_stop_phy(struct hclge_dev *hdev);
#endif
此差异已折叠。
/*
* Copyright (c) 2016~2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __HCLGE_TM_H
#define __HCLGE_TM_H
#include <linux/types.h>
/* MAC Pause */
#define HCLGE_TX_MAC_PAUSE_EN_MSK BIT(0)
#define HCLGE_RX_MAC_PAUSE_EN_MSK BIT(1)
#define HCLGE_TM_PORT_BASE_MODE_MSK BIT(0)
/* SP or DWRR */
#define HCLGE_TM_TX_SCHD_DWRR_MSK BIT(0)
#define HCLGE_TM_TX_SCHD_SP_MSK (0xFE)
struct hclge_pg_to_pri_link_cmd {
u8 pg_id;
u8 rsvd1[3];
u8 pri_bit_map;
};
struct hclge_qs_to_pri_link_cmd {
__le16 qs_id;
__le16 rsvd;
u8 priority;
#define HCLGE_TM_QS_PRI_LINK_VLD_MSK BIT(0)
u8 link_vld;
};
struct hclge_nq_to_qs_link_cmd {
__le16 nq_id;
__le16 rsvd;
#define HCLGE_TM_Q_QS_LINK_VLD_MSK BIT(10)
__le16 qset_id;
};
struct hclge_pg_weight_cmd {
u8 pg_id;
u8 dwrr;
};
struct hclge_priority_weight_cmd {
u8 pri_id;
u8 dwrr;
};
struct hclge_qs_weight_cmd {
__le16 qs_id;
u8 dwrr;
};
#define HCLGE_TM_SHAP_IR_B_MSK GENMASK(7, 0)
#define HCLGE_TM_SHAP_IR_B_LSH 0
#define HCLGE_TM_SHAP_IR_U_MSK GENMASK(11, 8)
#define HCLGE_TM_SHAP_IR_U_LSH 8
#define HCLGE_TM_SHAP_IR_S_MSK GENMASK(15, 12)
#define HCLGE_TM_SHAP_IR_S_LSH 12
#define HCLGE_TM_SHAP_BS_B_MSK GENMASK(20, 16)
#define HCLGE_TM_SHAP_BS_B_LSH 16
#define HCLGE_TM_SHAP_BS_S_MSK GENMASK(25, 21)
#define HCLGE_TM_SHAP_BS_S_LSH 21
enum hclge_shap_bucket {
HCLGE_TM_SHAP_C_BUCKET = 0,
HCLGE_TM_SHAP_P_BUCKET,
};
struct hclge_pri_shapping_cmd {
u8 pri_id;
u8 rsvd[3];
__le32 pri_shapping_para;
};
struct hclge_pg_shapping_cmd {
u8 pg_id;
u8 rsvd[3];
__le32 pg_shapping_para;
};
struct hclge_bp_to_qs_map_cmd {
u8 tc_id;
u8 rsvd[2];
u8 qs_group_id;
__le32 qs_bit_map;
u32 rsvd1;
};
#define hclge_tm_set_feild(dest, string, val) \
hnae_set_field((dest), (HCLGE_TM_SHAP_##string##_MSK), \
(HCLGE_TM_SHAP_##string##_LSH), val)
#define hclge_tm_get_feild(src, string) \
hnae_get_field((src), (HCLGE_TM_SHAP_##string##_MSK), \
(HCLGE_TM_SHAP_##string##_LSH))
int hclge_tm_schd_init(struct hclge_dev *hdev);
int hclge_pause_setup_hw(struct hclge_dev *hdev);
#endif
此差异已折叠。
/*
* Copyright (c) 2016 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __HNS3_ENET_H
#define __HNS3_ENET_H
#include "hnae3.h"
extern const char hns3_driver_version[];
enum hns3_nic_state {
HNS3_NIC_STATE_TESTING,
HNS3_NIC_STATE_RESETTING,
HNS3_NIC_STATE_REINITING,
HNS3_NIC_STATE_DOWN,
HNS3_NIC_STATE_DISABLED,
HNS3_NIC_STATE_REMOVING,
HNS3_NIC_STATE_SERVICE_INITED,
HNS3_NIC_STATE_SERVICE_SCHED,
HNS3_NIC_STATE2_RESET_REQUESTED,
HNS3_NIC_STATE_MAX
};
#define HNS3_RING_RX_RING_BASEADDR_L_REG 0x00000
#define HNS3_RING_RX_RING_BASEADDR_H_REG 0x00004
#define HNS3_RING_RX_RING_BD_NUM_REG 0x00008
#define HNS3_RING_RX_RING_BD_LEN_REG 0x0000C
#define HNS3_RING_RX_RING_TAIL_REG 0x00018
#define HNS3_RING_RX_RING_HEAD_REG 0x0001C
#define HNS3_RING_RX_RING_FBDNUM_REG 0x00020
#define HNS3_RING_RX_RING_PKTNUM_RECORD_REG 0x0002C
#define HNS3_RING_TX_RING_BASEADDR_L_REG 0x00040
#define HNS3_RING_TX_RING_BASEADDR_H_REG 0x00044
#define HNS3_RING_TX_RING_BD_NUM_REG 0x00048
#define HNS3_RING_TX_RING_BD_LEN_REG 0x0004C
#define HNS3_RING_TX_RING_TAIL_REG 0x00058
#define HNS3_RING_TX_RING_HEAD_REG 0x0005C
#define HNS3_RING_TX_RING_FBDNUM_REG 0x00060
#define HNS3_RING_TX_RING_OFFSET_REG 0x00064
#define HNS3_RING_TX_RING_PKTNUM_RECORD_REG 0x0006C
#define HNS3_RING_PREFETCH_EN_REG 0x0007C
#define HNS3_RING_CFG_VF_NUM_REG 0x00080
#define HNS3_RING_ASID_REG 0x0008C
#define HNS3_RING_RX_VM_REG 0x00090
#define HNS3_RING_T0_BE_RST 0x00094
#define HNS3_RING_COULD_BE_RST 0x00098
#define HNS3_RING_WRR_WEIGHT_REG 0x0009c
#define HNS3_RING_INTMSK_RXWL_REG 0x000A0
#define HNS3_RING_INTSTS_RX_RING_REG 0x000A4
#define HNS3_RX_RING_INT_STS_REG 0x000A8
#define HNS3_RING_INTMSK_TXWL_REG 0x000AC
#define HNS3_RING_INTSTS_TX_RING_REG 0x000B0
#define HNS3_TX_RING_INT_STS_REG 0x000B4
#define HNS3_RING_INTMSK_RX_OVERTIME_REG 0x000B8
#define HNS3_RING_INTSTS_RX_OVERTIME_REG 0x000BC
#define HNS3_RING_INTMSK_TX_OVERTIME_REG 0x000C4
#define HNS3_RING_INTSTS_TX_OVERTIME_REG 0x000C8
#define HNS3_RING_MB_CTRL_REG 0x00100
#define HNS3_RING_MB_DATA_BASE_REG 0x00200
#define HNS3_TX_REG_OFFSET 0x40
#define HNS3_RX_HEAD_SIZE 256
#define HNS3_TX_TIMEOUT (5 * HZ)
#define HNS3_RING_NAME_LEN 16
#define HNS3_BUFFER_SIZE_2048 2048
#define HNS3_RING_MAX_PENDING 32768
#define HNS3_BD_SIZE_512_TYPE 0
#define HNS3_BD_SIZE_1024_TYPE 1
#define HNS3_BD_SIZE_2048_TYPE 2
#define HNS3_BD_SIZE_4096_TYPE 3
#define HNS3_RX_FLAG_VLAN_PRESENT 0x1
#define HNS3_RX_FLAG_L3ID_IPV4 0x0
#define HNS3_RX_FLAG_L3ID_IPV6 0x1
#define HNS3_RX_FLAG_L4ID_UDP 0x0
#define HNS3_RX_FLAG_L4ID_TCP 0x1
#define HNS3_RXD_DMAC_S 0
#define HNS3_RXD_DMAC_M (0x3 << HNS3_RXD_DMAC_S)
#define HNS3_RXD_VLAN_S 2
#define HNS3_RXD_VLAN_M (0x3 << HNS3_RXD_VLAN_S)
#define HNS3_RXD_L3ID_S 4
#define HNS3_RXD_L3ID_M (0xf << HNS3_RXD_L3ID_S)
#define HNS3_RXD_L4ID_S 8
#define HNS3_RXD_L4ID_M (0xf << HNS3_RXD_L4ID_S)
#define HNS3_RXD_FRAG_B 12
#define HNS3_RXD_L2E_B 16
#define HNS3_RXD_L3E_B 17
#define HNS3_RXD_L4E_B 18
#define HNS3_RXD_TRUNCAT_B 19
#define HNS3_RXD_HOI_B 20
#define HNS3_RXD_DOI_B 21
#define HNS3_RXD_OL3E_B 22
#define HNS3_RXD_OL4E_B 23
#define HNS3_RXD_ODMAC_S 0
#define HNS3_RXD_ODMAC_M (0x3 << HNS3_RXD_ODMAC_S)
#define HNS3_RXD_OVLAN_S 2
#define HNS3_RXD_OVLAN_M (0x3 << HNS3_RXD_OVLAN_S)
#define HNS3_RXD_OL3ID_S 4
#define HNS3_RXD_OL3ID_M (0xf << HNS3_RXD_OL3ID_S)
#define HNS3_RXD_OL4ID_S 8
#define HNS3_RXD_OL4ID_M (0xf << HNS3_RXD_OL4ID_S)
#define HNS3_RXD_FBHI_S 12
#define HNS3_RXD_FBHI_M (0x3 << HNS3_RXD_FBHI_S)
#define HNS3_RXD_FBLI_S 14
#define HNS3_RXD_FBLI_M (0x3 << HNS3_RXD_FBLI_S)
#define HNS3_RXD_BDTYPE_S 0
#define HNS3_RXD_BDTYPE_M (0xf << HNS3_RXD_BDTYPE_S)
#define HNS3_RXD_VLD_B 4
#define HNS3_RXD_UDP0_B 5
#define HNS3_RXD_EXTEND_B 7
#define HNS3_RXD_FE_B 8
#define HNS3_RXD_LUM_B 9
#define HNS3_RXD_CRCP_B 10
#define HNS3_RXD_L3L4P_B 11
#define HNS3_RXD_TSIND_S 12
#define HNS3_RXD_TSIND_M (0x7 << HNS3_RXD_TSIND_S)
#define HNS3_RXD_LKBK_B 15
#define HNS3_RXD_HDL_S 16
#define HNS3_RXD_HDL_M (0x7ff << HNS3_RXD_HDL_S)
#define HNS3_RXD_HSIND_B 31
#define HNS3_TXD_L3T_S 0
#define HNS3_TXD_L3T_M (0x3 << HNS3_TXD_L3T_S)
#define HNS3_TXD_L4T_S 2
#define HNS3_TXD_L4T_M (0x3 << HNS3_TXD_L4T_S)
#define HNS3_TXD_L3CS_B 4
#define HNS3_TXD_L4CS_B 5
#define HNS3_TXD_VLAN_B 6
#define HNS3_TXD_TSO_B 7
#define HNS3_TXD_L2LEN_S 8
#define HNS3_TXD_L2LEN_M (0xff << HNS3_TXD_L2LEN_S)
#define HNS3_TXD_L3LEN_S 16
#define HNS3_TXD_L3LEN_M (0xff << HNS3_TXD_L3LEN_S)
#define HNS3_TXD_L4LEN_S 24
#define HNS3_TXD_L4LEN_M (0xff << HNS3_TXD_L4LEN_S)
#define HNS3_TXD_OL3T_S 0
#define HNS3_TXD_OL3T_M (0x3 << HNS3_TXD_OL3T_S)
#define HNS3_TXD_OVLAN_B 2
#define HNS3_TXD_MACSEC_B 3
#define HNS3_TXD_TUNTYPE_S 4
#define HNS3_TXD_TUNTYPE_M (0xf << HNS3_TXD_TUNTYPE_S)
#define HNS3_TXD_BDTYPE_S 0
#define HNS3_TXD_BDTYPE_M (0xf << HNS3_TXD_BDTYPE_S)
#define HNS3_TXD_FE_B 4
#define HNS3_TXD_SC_S 5
#define HNS3_TXD_SC_M (0x3 << HNS3_TXD_SC_S)
#define HNS3_TXD_EXTEND_B 7
#define HNS3_TXD_VLD_B 8
#define HNS3_TXD_RI_B 9
#define HNS3_TXD_RA_B 10
#define HNS3_TXD_TSYN_B 11
#define HNS3_TXD_DECTTL_S 12
#define HNS3_TXD_DECTTL_M (0xf << HNS3_TXD_DECTTL_S)
#define HNS3_TXD_MSS_S 0
#define HNS3_TXD_MSS_M (0x3fff << HNS3_TXD_MSS_S)
#define HNS3_VECTOR_TX_IRQ BIT_ULL(0)
#define HNS3_VECTOR_RX_IRQ BIT_ULL(1)
#define HNS3_VECTOR_NOT_INITED 0
#define HNS3_VECTOR_INITED 1
#define HNS3_MAX_BD_SIZE 65535
#define HNS3_MAX_BD_PER_FRAG 8
#define HNS3_MAX_BD_PER_PKT MAX_SKB_FRAGS
#define HNS3_VECTOR_GL0_OFFSET 0x100
#define HNS3_VECTOR_GL1_OFFSET 0x200
#define HNS3_VECTOR_GL2_OFFSET 0x300
#define HNS3_VECTOR_RL_OFFSET 0x900
#define HNS3_VECTOR_RL_EN_B 6
enum hns3_pkt_l3t_type {
HNS3_L3T_NONE,
HNS3_L3T_IPV6,
HNS3_L3T_IPV4,
HNS3_L3T_RESERVED
};
enum hns3_pkt_l4t_type {
HNS3_L4T_UNKNOWN,
HNS3_L4T_TCP,
HNS3_L4T_UDP,
HNS3_L4T_SCTP
};
enum hns3_pkt_ol3t_type {
HNS3_OL3T_NONE,
HNS3_OL3T_IPV6,
HNS3_OL3T_IPV4_NO_CSUM,
HNS3_OL3T_IPV4_CSUM
};
enum hns3_pkt_tun_type {
HNS3_TUN_NONE,
HNS3_TUN_MAC_IN_UDP,
HNS3_TUN_NVGRE,
HNS3_TUN_OTHER
};
/* hardware spec ring buffer format */
struct __packed hns3_desc {
__le64 addr;
union {
struct {
__le16 vlan_tag;
__le16 send_size;
union {
__le32 type_cs_vlan_tso_len;
struct {
__u8 type_cs_vlan_tso;
__u8 l2_len;
__u8 l3_len;
__u8 l4_len;
};
};
__le16 outer_vlan_tag;
__le16 tv;
union {
__le32 ol_type_vlan_len_msec;
struct {
__u8 ol_type_vlan_msec;
__u8 ol2_len;
__u8 ol3_len;
__u8 ol4_len;
};
};
__le32 paylen;
__le16 bdtp_fe_sc_vld_ra_ri;
__le16 mss;
} tx;
struct {
__le32 l234_info;
__le16 pkt_len;
__le16 size;
__le32 rss_hash;
__le16 fd_id;
__le16 vlan_tag;
union {
__le32 ol_info;
struct {
__le16 o_dm_vlan_id_fb;
__le16 ot_vlan_tag;
};
};
__le32 bd_base_info;
} rx;
};
};
struct hns3_desc_cb {
dma_addr_t dma; /* dma address of this desc */
void *buf; /* cpu addr for a desc */
/* priv data for the desc, e.g. skb when use with ip stack*/
void *priv;
u16 page_offset;
u16 reuse_flag;
u16 length; /* length of the buffer */
/* desc type, used by the ring user to mark the type of the priv data */
u16 type;
};
enum hns3_pkt_l3type {
HNS3_L3_TYPE_IPV4,
HNS3_L3_TYPE_IPV6,
HNS3_L3_TYPE_ARP,
HNS3_L3_TYPE_RARP,
HNS3_L3_TYPE_IPV4_OPT,
HNS3_L3_TYPE_IPV6_EXT,
HNS3_L3_TYPE_LLDP,
HNS3_L3_TYPE_BPDU,
HNS3_L3_TYPE_MAC_PAUSE,
HNS3_L3_TYPE_PFC_PAUSE,/* 0x9*/
/* reserved for 0xA~0xB*/
HNS3_L3_TYPE_CNM = 0xc,
/* reserved for 0xD~0xE*/
HNS3_L3_TYPE_PARSE_FAIL = 0xf /* must be last */
};
enum hns3_pkt_l4type {
HNS3_L4_TYPE_UDP,
HNS3_L4_TYPE_TCP,
HNS3_L4_TYPE_GRE,
HNS3_L4_TYPE_SCTP,
HNS3_L4_TYPE_IGMP,
HNS3_L4_TYPE_ICMP,
/* reserved for 0x6~0xE */
HNS3_L4_TYPE_PARSE_FAIL = 0xf /* must be last */
};
enum hns3_pkt_ol3type {
HNS3_OL3_TYPE_IPV4 = 0,
HNS3_OL3_TYPE_IPV6,
/* reserved for 0x2~0x3 */
HNS3_OL3_TYPE_IPV4_OPT = 4,
HNS3_OL3_TYPE_IPV6_EXT,
/* reserved for 0x6~0xE*/
HNS3_OL3_TYPE_PARSE_FAIL = 0xf /* must be last */
};
enum hns3_pkt_ol4type {
HNS3_OL4_TYPE_NO_TUN,
HNS3_OL4_TYPE_MAC_IN_UDP,
HNS3_OL4_TYPE_NVGRE,
HNS3_OL4_TYPE_UNKNOWN
};
struct ring_stats {
u64 io_err_cnt;
u64 sw_err_cnt;
u64 seg_pkt_cnt;
union {
struct {
u64 tx_pkts;
u64 tx_bytes;
u64 tx_err_cnt;
u64 restart_queue;
u64 tx_busy;
};
struct {
u64 rx_pkts;
u64 rx_bytes;
u64 rx_err_cnt;
u64 reuse_pg_cnt;
u64 err_pkt_len;
u64 non_vld_descs;
u64 err_bd_num;
u64 l2_err;
u64 l3l4_csum_err;
};
};
};
struct hns3_enet_ring {
u8 __iomem *io_base; /* base io address for the ring */
struct hns3_desc *desc; /* dma map address space */
struct hns3_desc_cb *desc_cb;
struct hns3_enet_ring *next;
struct hns3_enet_tqp_vector *tqp_vector;
struct hnae3_queue *tqp;
char ring_name[HNS3_RING_NAME_LEN];
struct device *dev; /* will be used for DMA mapping of descriptors */
/* statistic */
struct ring_stats stats;
struct u64_stats_sync syncp;
dma_addr_t desc_dma_addr;
u32 buf_size; /* size for hnae_desc->addr, preset by AE */
u16 desc_num; /* total number of desc */
u16 max_desc_num_per_pkt;
u16 max_raw_data_sz_per_desc;
u16 max_pkt_size;
int next_to_use; /* idx of next spare desc */
/* idx of lastest sent desc, the ring is empty when equal to
* next_to_use
*/
int next_to_clean;
u32 flag; /* ring attribute */
int irq_init_flag;
int numa_node;
cpumask_t affinity_mask;
};
struct hns_queue;
struct hns3_nic_ring_data {
struct hns3_enet_ring *ring;
struct napi_struct napi;
int queue_index;
int (*poll_one)(struct hns3_nic_ring_data *, int, void *);
void (*ex_process)(struct hns3_nic_ring_data *, struct sk_buff *);
void (*fini_process)(struct hns3_nic_ring_data *);
};
struct hns3_nic_ops {
int (*fill_desc)(struct hns3_enet_ring *ring, void *priv,
int size, dma_addr_t dma, int frag_end,
enum hns_desc_type type);
int (*maybe_stop_tx)(struct sk_buff **out_skb,
int *bnum, struct hns3_enet_ring *ring);
void (*get_rxd_bnum)(u32 bnum_flag, int *out_bnum);
};
enum hns3_flow_level_range {
HNS3_FLOW_LOW = 0,
HNS3_FLOW_MID = 1,
HNS3_FLOW_HIGH = 2,
HNS3_FLOW_ULTRA = 3,
};
enum hns3_link_mode_bits {
HNS3_LM_FIBRE_BIT = BIT(0),
HNS3_LM_AUTONEG_BIT = BIT(1),
HNS3_LM_TP_BIT = BIT(2),
HNS3_LM_PAUSE_BIT = BIT(3),
HNS3_LM_BACKPLANE_BIT = BIT(4),
HNS3_LM_10BASET_HALF_BIT = BIT(5),
HNS3_LM_10BASET_FULL_BIT = BIT(6),
HNS3_LM_100BASET_HALF_BIT = BIT(7),
HNS3_LM_100BASET_FULL_BIT = BIT(8),
HNS3_LM_1000BASET_FULL_BIT = BIT(9),
HNS3_LM_10000BASEKR_FULL_BIT = BIT(10),
HNS3_LM_25000BASEKR_FULL_BIT = BIT(11),
HNS3_LM_40000BASELR4_FULL_BIT = BIT(12),
HNS3_LM_50000BASEKR2_FULL_BIT = BIT(13),
HNS3_LM_100000BASEKR4_FULL_BIT = BIT(14),
HNS3_LM_COUNT = 15
};
#define HNS3_INT_GL_50K 0x000A
#define HNS3_INT_GL_20K 0x0019
#define HNS3_INT_GL_18K 0x001B
#define HNS3_INT_GL_8K 0x003E
struct hns3_enet_ring_group {
/* array of pointers to rings */
struct hns3_enet_ring *ring;
u64 total_bytes; /* total bytes processed this group */
u64 total_packets; /* total packets processed this group */
u16 count;
enum hns3_flow_level_range flow_level;
u16 int_gl;
};
struct hns3_enet_tqp_vector {
struct hnae3_handle *handle;
u8 __iomem *mask_addr;
int vector_irq;
int irq_init_flag;
u16 idx; /* index in the TQP vector array per handle. */
struct napi_struct napi;
struct hns3_enet_ring_group rx_group;
struct hns3_enet_ring_group tx_group;
u16 num_tqps; /* total number of tqps in TQP vector */
cpumask_t affinity_mask;
char name[HNAE3_INT_NAME_LEN];
/* when 0 should adjust interrupt coalesce parameter */
u8 int_adapt_down;
} ____cacheline_internodealigned_in_smp;
enum hns3_udp_tnl_type {
HNS3_UDP_TNL_VXLAN,
HNS3_UDP_TNL_GENEVE,
HNS3_UDP_TNL_MAX,
};
struct hns3_udp_tunnel {
u16 dst_port;
int used;
};
struct hns3_nic_priv {
struct hnae3_handle *ae_handle;
u32 enet_ver;
u32 port_id;
struct net_device *netdev;
struct device *dev;
struct hns3_nic_ops ops;
/**
* the cb for nic to manage the ring buffer, the first half of the
* array is for tx_ring and vice versa for the second half
*/
struct hns3_nic_ring_data *ring_data;
struct hns3_enet_tqp_vector *tqp_vector;
u16 vector_num;
/* The most recently read link state */
int link;
u64 tx_timeout_count;
unsigned long state;
struct timer_list service_timer;
struct work_struct service_task;
struct notifier_block notifier_block;
/* Vxlan/Geneve information */
struct hns3_udp_tunnel udp_tnl[HNS3_UDP_TNL_MAX];
};
union l3_hdr_info {
struct iphdr *v4;
struct ipv6hdr *v6;
unsigned char *hdr;
};
union l4_hdr_info {
struct tcphdr *tcp;
struct udphdr *udp;
unsigned char *hdr;
};
/* the distance between [begin, end) in a ring buffer
* note: there is a unuse slot between the begin and the end
*/
static inline int ring_dist(struct hns3_enet_ring *ring, int begin, int end)
{
return (end - begin + ring->desc_num) % ring->desc_num;
}
static inline int ring_space(struct hns3_enet_ring *ring)
{
return ring->desc_num -
ring_dist(ring, ring->next_to_clean, ring->next_to_use) - 1;
}
static inline int is_ring_empty(struct hns3_enet_ring *ring)
{
return ring->next_to_use == ring->next_to_clean;
}
static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
{
u8 __iomem *reg_addr = READ_ONCE(base);
writel(value, reg_addr + reg);
}
#define hns3_write_dev(a, reg, value) \
hns3_write_reg((a)->io_base, (reg), (value))
#define hnae_queue_xmit(tqp, buf_num) writel_relaxed(buf_num, \
(tqp)->io_base + HNS3_RING_TX_RING_TAIL_REG)
#define ring_to_dev(ring) (&(ring)->tqp->handle->pdev->dev)
#define ring_to_dma_dir(ring) (HNAE3_IS_TX_RING(ring) ? \
DMA_TO_DEVICE : DMA_FROM_DEVICE)
#define tx_ring_data(priv, idx) ((priv)->ring_data[idx])
#define hnae_buf_size(_ring) ((_ring)->buf_size)
#define hnae_page_order(_ring) (get_order(hnae_buf_size(_ring)))
#define hnae_page_size(_ring) (PAGE_SIZE << hnae_page_order(_ring))
/* iterator for handling rings in ring group */
#define hns3_for_each_ring(pos, head) \
for (pos = (head).ring; pos; pos = pos->next)
void hns3_ethtool_set_ops(struct net_device *netdev);
int hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget);
#endif
/*
* Copyright (c) 2016~2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/etherdevice.h>
#include <linux/string.h>
#include "hns3_enet.h"
struct hns3_stats {
char stats_string[ETH_GSTRING_LEN];
int stats_size;
int stats_offset;
};
/* tqp related stats */
#define HNS3_TQP_STAT(_string, _member) { \
.stats_string = _string, \
.stats_size = FIELD_SIZEOF(struct ring_stats, _member), \
.stats_offset = offsetof(struct hns3_enet_ring, stats), \
} \
static const struct hns3_stats hns3_txq_stats[] = {
/* Tx per-queue statistics */
HNS3_TQP_STAT("tx_io_err_cnt", io_err_cnt),
HNS3_TQP_STAT("tx_sw_err_cnt", sw_err_cnt),
HNS3_TQP_STAT("tx_seg_pkt_cnt", seg_pkt_cnt),
HNS3_TQP_STAT("tx_pkts", tx_pkts),
HNS3_TQP_STAT("tx_bytes", tx_bytes),
HNS3_TQP_STAT("tx_err_cnt", tx_err_cnt),
HNS3_TQP_STAT("tx_restart_queue", restart_queue),
HNS3_TQP_STAT("tx_busy", tx_busy),
};
#define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats)
static const struct hns3_stats hns3_rxq_stats[] = {
/* Rx per-queue statistics */
HNS3_TQP_STAT("rx_io_err_cnt", io_err_cnt),
HNS3_TQP_STAT("rx_sw_err_cnt", sw_err_cnt),
HNS3_TQP_STAT("rx_seg_pkt_cnt", seg_pkt_cnt),
HNS3_TQP_STAT("rx_pkts", rx_pkts),
HNS3_TQP_STAT("rx_bytes", rx_bytes),
HNS3_TQP_STAT("rx_err_cnt", rx_err_cnt),
HNS3_TQP_STAT("rx_reuse_pg_cnt", reuse_pg_cnt),
HNS3_TQP_STAT("rx_err_pkt_len", err_pkt_len),
HNS3_TQP_STAT("rx_non_vld_descs", non_vld_descs),
HNS3_TQP_STAT("rx_err_bd_num", err_bd_num),
HNS3_TQP_STAT("rx_l2_err", l2_err),
HNS3_TQP_STAT("rx_l3l4_csum_err", l3l4_csum_err),
};
#define HNS3_RXQ_STATS_COUNT ARRAY_SIZE(hns3_rxq_stats)
#define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT)
struct hns3_link_mode_mapping {
u32 hns3_link_mode;
u32 ethtool_link_mode;
};
static const struct hns3_link_mode_mapping hns3_lm_map[] = {
{HNS3_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT},
{HNS3_LM_AUTONEG_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT},
{HNS3_LM_TP_BIT, ETHTOOL_LINK_MODE_TP_BIT},
{HNS3_LM_PAUSE_BIT, ETHTOOL_LINK_MODE_Pause_BIT},
{HNS3_LM_BACKPLANE_BIT, ETHTOOL_LINK_MODE_Backplane_BIT},
{HNS3_LM_10BASET_HALF_BIT, ETHTOOL_LINK_MODE_10baseT_Half_BIT},
{HNS3_LM_10BASET_FULL_BIT, ETHTOOL_LINK_MODE_10baseT_Full_BIT},
{HNS3_LM_100BASET_HALF_BIT, ETHTOOL_LINK_MODE_100baseT_Half_BIT},
{HNS3_LM_100BASET_FULL_BIT, ETHTOOL_LINK_MODE_100baseT_Full_BIT},
{HNS3_LM_1000BASET_FULL_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
};
static void hns3_driv_to_eth_caps(u32 caps, struct ethtool_link_ksettings *cmd,
bool is_advertised)
{
int i;
for (i = 0; i < ARRAY_SIZE(hns3_lm_map); i++) {
if (!(caps & hns3_lm_map[i].hns3_link_mode))
continue;
if (is_advertised) {
ethtool_link_ksettings_zero_link_mode(cmd,
advertising);
__set_bit(hns3_lm_map[i].ethtool_link_mode,
cmd->link_modes.advertising);
} else {
ethtool_link_ksettings_zero_link_mode(cmd,
supported);
__set_bit(hns3_lm_map[i].ethtool_link_mode,
cmd->link_modes.supported);
}
}
}
static int hns3_get_sset_count(struct net_device *netdev, int stringset)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
const struct hnae3_ae_ops *ops = h->ae_algo->ops;
if (!ops->get_sset_count)
return -EOPNOTSUPP;
switch (stringset) {
case ETH_SS_STATS:
return ((HNS3_TQP_STATS_COUNT * h->kinfo.num_tqps) +
ops->get_sset_count(h, stringset));
case ETH_SS_TEST:
return ops->get_sset_count(h, stringset);
}
return 0;
}
static void *hns3_update_strings(u8 *data, const struct hns3_stats *stats,
u32 stat_count, u32 num_tqps)
{
#define MAX_PREFIX_SIZE (8 + 4)
u32 size_left;
u32 i, j;
u32 n1;
for (i = 0; i < num_tqps; i++) {
for (j = 0; j < stat_count; j++) {
data[ETH_GSTRING_LEN - 1] = '\0';
/* first, prepend the prefix string */
n1 = snprintf(data, MAX_PREFIX_SIZE, "rcb_q%d_", i);
n1 = min_t(uint, n1, MAX_PREFIX_SIZE - 1);
size_left = (ETH_GSTRING_LEN - 1) - n1;
/* now, concatenate the stats string to it */
strncat(data, stats[j].stats_string, size_left);
data += ETH_GSTRING_LEN;
}
}
return data;
}
static u8 *hns3_get_strings_tqps(struct hnae3_handle *handle, u8 *data)
{
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
/* get strings for Tx */
data = hns3_update_strings(data, hns3_txq_stats, HNS3_TXQ_STATS_COUNT,
kinfo->num_tqps);
/* get strings for Rx */
data = hns3_update_strings(data, hns3_rxq_stats, HNS3_RXQ_STATS_COUNT,
kinfo->num_tqps);
return data;
}
static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
const struct hnae3_ae_ops *ops = h->ae_algo->ops;
char *buff = (char *)data;
if (!ops->get_strings)
return;
switch (stringset) {
case ETH_SS_STATS:
buff = hns3_get_strings_tqps(h, buff);
h->ae_algo->ops->get_strings(h, stringset, (u8 *)buff);
break;
case ETH_SS_TEST:
ops->get_strings(h, stringset, data);
break;
}
}
static u64 *hns3_get_stats_tqps(struct hnae3_handle *handle, u64 *data)
{
struct hns3_nic_priv *nic_priv = (struct hns3_nic_priv *)handle->priv;
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
struct hns3_enet_ring *ring;
u8 *stat;
u32 i;
/* get stats for Tx */
for (i = 0; i < kinfo->num_tqps; i++) {
ring = nic_priv->ring_data[i].ring;
for (i = 0; i < HNS3_TXQ_STATS_COUNT; i++) {
stat = (u8 *)ring + hns3_txq_stats[i].stats_offset;
*data++ = *(u64 *)stat;
}
}
/* get stats for Rx */
for (i = 0; i < kinfo->num_tqps; i++) {
ring = nic_priv->ring_data[i + kinfo->num_tqps].ring;
for (i = 0; i < HNS3_RXQ_STATS_COUNT; i++) {
stat = (u8 *)ring + hns3_rxq_stats[i].stats_offset;
*data++ = *(u64 *)stat;
}
}
return data;
}
/* hns3_get_stats - get detail statistics.
* @netdev: net device
* @stats: statistics info.
* @data: statistics data.
*/
void hns3_get_stats(struct net_device *netdev, struct ethtool_stats *stats,
u64 *data)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
u64 *p = data;
if (!h->ae_algo->ops->get_stats || !h->ae_algo->ops->update_stats) {
netdev_err(netdev, "could not get any statistics\n");
return;
}
h->ae_algo->ops->update_stats(h, &netdev->stats);
/* get per-queue stats */
p = hns3_get_stats_tqps(h, p);
/* get MAC & other misc hardware stats */
h->ae_algo->ops->get_stats(h, p);
}
static void hns3_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
strncpy(drvinfo->version, hns3_driver_version,
sizeof(drvinfo->version));
drvinfo->version[sizeof(drvinfo->version) - 1] = '\0';
strncpy(drvinfo->driver, h->pdev->driver->name,
sizeof(drvinfo->driver));
drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0';
strncpy(drvinfo->bus_info, pci_name(h->pdev),
sizeof(drvinfo->bus_info));
drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0';
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "0x%08x",
priv->ae_handle->ae_algo->ops->get_fw_version(h));
}
static u32 hns3_get_link(struct net_device *netdev)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h;
h = priv->ae_handle;
if (h->ae_algo && h->ae_algo->ops && h->ae_algo->ops->get_status)
return h->ae_algo->ops->get_status(h);
else
return 0;
}
static void hns3_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *param)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
int queue_num = priv->ae_handle->kinfo.num_tqps;
param->tx_max_pending = HNS3_RING_MAX_PENDING;
param->rx_max_pending = HNS3_RING_MAX_PENDING;
param->tx_pending = priv->ring_data[0].ring->desc_num;
param->rx_pending = priv->ring_data[queue_num].ring->desc_num;
}
static void hns3_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *param)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
if (h->ae_algo && h->ae_algo->ops && h->ae_algo->ops->get_pauseparam)
h->ae_algo->ops->get_pauseparam(h, &param->autoneg,
&param->rx_pause, &param->tx_pause);
}
static int hns3_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
u32 supported_caps;
u32 advertised_caps;
u8 media_type;
u8 link_stat;
u8 auto_neg;
u8 duplex;
u32 speed;
if (!h->ae_algo || !h->ae_algo->ops)
return -EOPNOTSUPP;
/* 1.auto_neg&speed&duplex from cmd */
if (h->ae_algo->ops->get_ksettings_an_result) {
h->ae_algo->ops->get_ksettings_an_result(h, &auto_neg,
&speed, &duplex);
cmd->base.autoneg = auto_neg;
cmd->base.speed = speed;
cmd->base.duplex = duplex;
link_stat = hns3_get_link(netdev);
if (!link_stat) {
cmd->base.speed = (u32)SPEED_UNKNOWN;
cmd->base.duplex = DUPLEX_UNKNOWN;
}
}
/* 2.media_type get from bios parameter block */
if (h->ae_algo->ops->get_media_type)
h->ae_algo->ops->get_media_type(h, &media_type);
switch (media_type) {
case HNAE3_MEDIA_TYPE_FIBER:
cmd->base.port = PORT_FIBRE;
supported_caps = HNS3_LM_FIBRE_BIT | HNS3_LM_AUTONEG_BIT |
HNS3_LM_PAUSE_BIT | HNS3_LM_1000BASET_FULL_BIT;
advertised_caps = supported_caps;
break;
case HNAE3_MEDIA_TYPE_COPPER:
cmd->base.port = PORT_TP;
supported_caps = HNS3_LM_TP_BIT | HNS3_LM_AUTONEG_BIT |
HNS3_LM_PAUSE_BIT | HNS3_LM_1000BASET_FULL_BIT |
HNS3_LM_100BASET_FULL_BIT | HNS3_LM_100BASET_HALF_BIT |
HNS3_LM_10BASET_FULL_BIT | HNS3_LM_10BASET_HALF_BIT;
advertised_caps = supported_caps;
break;
case HNAE3_MEDIA_TYPE_BACKPLANE:
cmd->base.port = PORT_NONE;
supported_caps = HNS3_LM_BACKPLANE_BIT | HNS3_LM_PAUSE_BIT |
HNS3_LM_AUTONEG_BIT | HNS3_LM_1000BASET_FULL_BIT |
HNS3_LM_100BASET_FULL_BIT | HNS3_LM_100BASET_HALF_BIT |
HNS3_LM_10BASET_FULL_BIT | HNS3_LM_10BASET_HALF_BIT;
advertised_caps = supported_caps;
break;
case HNAE3_MEDIA_TYPE_UNKNOWN:
default:
cmd->base.port = PORT_OTHER;
supported_caps = 0;
advertised_caps = 0;
break;
}
/* now, map driver link modes to ethtool link modes */
hns3_driv_to_eth_caps(supported_caps, cmd, false);
hns3_driv_to_eth_caps(advertised_caps, cmd, true);
/* 3.mdix_ctrl&mdix get from phy reg */
if (h->ae_algo->ops->get_mdix_mode)
h->ae_algo->ops->get_mdix_mode(h, &cmd->base.eth_tp_mdix_ctrl,
&cmd->base.eth_tp_mdix);
/* 4.mdio_support */
cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22;
return 0;
}
static u32 hns3_get_rss_key_size(struct net_device *netdev)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
if (!h->ae_algo || !h->ae_algo->ops ||
!h->ae_algo->ops->get_rss_key_size)
return -EOPNOTSUPP;
return h->ae_algo->ops->get_rss_key_size(h);
}
static u32 hns3_get_rss_indir_size(struct net_device *netdev)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
if (!h->ae_algo || !h->ae_algo->ops ||
!h->ae_algo->ops->get_rss_indir_size)
return -EOPNOTSUPP;
return h->ae_algo->ops->get_rss_indir_size(h);
}
static int hns3_get_rss(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->get_rss)
return -EOPNOTSUPP;
return h->ae_algo->ops->get_rss(h, indir, key, hfunc);
}
static int hns3_set_rss(struct net_device *netdev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->set_rss)
return -EOPNOTSUPP;
/* currently we only support Toeplitz hash */
if ((hfunc != ETH_RSS_HASH_NO_CHANGE) && (hfunc != ETH_RSS_HASH_TOP)) {
netdev_err(netdev,
"hash func not supported (only Toeplitz hash)\n");
return -EOPNOTSUPP;
}
if (!indir) {
netdev_err(netdev,
"set rss failed for indir is empty\n");
return -EOPNOTSUPP;
}
return h->ae_algo->ops->set_rss(h, indir, key, hfunc);
}
static int hns3_get_rxnfc(struct net_device *netdev,
struct ethtool_rxnfc *cmd,
u32 *rule_locs)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->get_tc_size)
return -EOPNOTSUPP;
switch (cmd->cmd) {
case ETHTOOL_GRXRINGS:
cmd->data = h->ae_algo->ops->get_tc_size(h);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
static const struct ethtool_ops hns3_ethtool_ops = {
.get_drvinfo = hns3_get_drvinfo,
.get_link = hns3_get_link,
.get_ringparam = hns3_get_ringparam,
.get_pauseparam = hns3_get_pauseparam,
.get_strings = hns3_get_strings,
.get_ethtool_stats = hns3_get_stats,
.get_sset_count = hns3_get_sset_count,
.get_rxnfc = hns3_get_rxnfc,
.get_rxfh_key_size = hns3_get_rss_key_size,
.get_rxfh_indir_size = hns3_get_rss_indir_size,
.get_rxfh = hns3_get_rss,
.set_rxfh = hns3_set_rss,
.get_link_ksettings = hns3_get_link_ksettings,
};
void hns3_ethtool_set_ops(struct net_device *netdev)
{
netdev->ethtool_ops = &hns3_ethtool_ops;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册