提交 2cf8cdea 编写于 作者: D dengweiwei 提交者: Xie XiuQi

net: hns3: update IT chip code of hns3 driver

driver inclusion
category: feature
bugzilla: 13683
CVE: NA

-------------------------------------------------

Update IT chip code of hns3 driver particularly for dfx.
Tested-by: Nchenjunxin <chenjunxin1@huawei.com>
Signed-off-by: Ndengweiwei <dengweiwei@huawei.com>
Reviewed-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 98ed6faf
// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2016-2017 Hisilicon Limited.
#include <linux/etherdevice.h>
#include <linux/interrupt.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "../hnae3.h"
#include "hns3_enet_it.h"
#include "hns3pf/hclge_main_it.h"
#include "../hns3_enet.h"
extern const char hns3_driver_string[];
extern const char hns3_copyright[];
#ifdef CONFIG_IT_VALIDATION
#define HNAE_DRIVER_VERSION "B075"
#define HNAE_DRIVER_VERSION_MAX_LEN 8
#ifdef CONFIG_HNS3_X86
#define HNAE3_DEV_ID_X86_25_GE 0xA125
#endif
extern struct ethtool_ops hns3vf_ethtool_ops;
extern struct ethtool_ops hns3_ethtool_ops;
extern struct net_device_ops hns3_nic_netdev_ops;
extern const struct hnae3_client_ops client_ops;
extern struct hnae3_client client;
extern struct pci_driver hns3_driver;
extern const char hns3_driver_name[];
extern struct pci_error_handlers hns3_err_handler;
extern int hns3_set_link_ksettings_it(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd);
/* hns3_pci_tbl - PCI Device ID Table
*
* Last entry must be all 0s
*
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, private data (not used) }
*/
const struct pci_device_id hns3_pci_tbl_it[] = {
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_GE), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA),
HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA_MACSEC),
HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA),
HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA_MACSEC),
HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC),
HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_VF), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF),
HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
#ifdef CONFIG_HNS3_X86
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_X86_25_GE), 0},
#endif
/* required last entry */
{0, }
};
MODULE_DEVICE_TABLE(pci, hns3_pci_tbl_it);
#ifdef CONFIG_EXT_TEST
void hns3_nic_net_timeout_it(struct net_device *ndev)
{
if (!hns3_get_tx_timeo_queue_info(ndev))
return;
nic_call_event(ndev, HNAE3_FUNC_RESET_CUSTOM);
}
#endif
int hns3_nic_do_ioctl_it(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
switch (cmd) {
case (SIOCDEVPRIVATE + 4):
if (hns3_ioctl)
return hns3_ioctl(netdev, ifr->ifr_data);
pr_err("open nic_test failed");
return -EINVAL;
default:
return -EINVAL;
}
}
#if (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE)
u16 hns3_nic_select_queue_it(struct net_device *ndev, struct sk_buff *skb,
void *accel_priv,
select_queue_fallback_t fallback)
#else
u16 hns3_nic_select_queue_it(struct net_device *ndev, struct sk_buff *skb,
struct net_device *accel_priv,
select_queue_fallback_t fallback)
#endif
{
#define HNS3_VLAN_PRIO_SHIFT 13
if (!accel_priv)
if (skb->vlan_tci && !skb->priority)
skb->priority = skb->vlan_tci >> HNS3_VLAN_PRIO_SHIFT;
#if (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE)
return fallback(ndev, skb);
#else
return fallback(ndev, skb, accel_priv);
#endif
}
static int __init hns3_init_module_it(void)
{
struct ethtool_ops *loc_ethtool_ops;
struct net_device_ops *ndev_ops;
int ret;
#ifdef CONFIG_EXT_TEST
struct pci_error_handlers *err_handlers;
err_handlers = (struct pci_error_handlers *)&hns3_err_handler;
err_handlers->slot_reset = NULL;
#endif
pr_info("%s: %s - version\n", hns3_driver_name, hns3_driver_string);
pr_info("%s: %s\n", hns3_driver_name, hns3_copyright);
strncpy(hns3_driver_version, HNAE_DRIVER_VERSION,
HNAE_DRIVER_VERSION_MAX_LEN);
loc_ethtool_ops = (struct ethtool_ops *)&hns3_ethtool_ops;
loc_ethtool_ops->set_link_ksettings = hns3_set_link_ksettings_it;
client.type = HNAE3_CLIENT_KNIC;
snprintf(client.name, HNAE3_CLIENT_NAME_LENGTH - 1, "%s",
hns3_driver_name);
client.ops = &client_ops;
ndev_ops = (struct net_device_ops *)&hns3_nic_netdev_ops;
ndev_ops->ndo_do_ioctl = hns3_nic_do_ioctl_it;
#ifdef CONFIG_EXT_TEST
ndev_ops->ndo_tx_timeout = hns3_nic_net_timeout_it;
#endif
ndev_ops->ndo_select_queue = hns3_nic_select_queue_it;
INIT_LIST_HEAD(&client.node);
hns3_dbg_register_debugfs(hns3_driver_name);
ret = hnae3_register_client(&client);
if (ret)
goto err_reg_client;
hns3_driver.id_table = hns3_pci_tbl_it;
ret = pci_register_driver(&hns3_driver);
if (ret)
goto err_reg_driver;
return ret;
err_reg_driver:
hnae3_unregister_client(&client);
err_reg_client:
hns3_dbg_unregister_debugfs();
return ret;
}
module_init(hns3_init_module_it);
#endif
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) 2016-2017 Hisilicon Limited. */
#ifndef __HNS3_ENET_IT_H
#define __HNS3_ENET_IT_H
typedef int (*hns3_priv_func)(struct net_device *, void *);
hns3_priv_func hns3_ioctl;
#define VERSION_NUMBER "$FULL_VERSION"
#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
#else
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
#endif
#endif
// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2016-2017 Hisilicon Limited.
#include <linux/etherdevice.h>
#include <linux/string.h>
#include <linux/phy.h>
#include "../hns3_enet.h"
static int hns3_check_ksettings_para(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN;
u8 autoneg = 0;
u32 speed = 0;
u8 duplex = 0;
u32 check_flag;
/* Verify the settings we care about. */
if (cmd->base.autoneg != AUTONEG_ENABLE &&
cmd->base.autoneg != AUTONEG_DISABLE)
return -EINVAL;
if (h->ae_algo->ops->get_media_type)
h->ae_algo->ops->get_media_type(h, &media_type, &module_type);
if (h->ae_algo->ops->get_ksettings_an_result)
h->ae_algo->ops->get_ksettings_an_result(h, &autoneg, &speed,
&duplex);
if (cmd->base.autoneg == autoneg &&
cmd->base.speed == speed &&
cmd->base.duplex == duplex)
return 0;
if (media_type == HNAE3_MEDIA_TYPE_COPPER) {
check_flag = (cmd->base.speed != SPEED_10 &&
cmd->base.speed != SPEED_100 &&
cmd->base.speed != SPEED_1000);
if (check_flag)
return -EINVAL;
} else {
check_flag = (cmd->base.speed != SPEED_1000 &&
cmd->base.speed != SPEED_10000 &&
cmd->base.speed != SPEED_25000 &&
cmd->base.speed != SPEED_40000 &&
cmd->base.speed != SPEED_50000 &&
cmd->base.speed != SPEED_100000);
if (check_flag)
return -EINVAL;
}
check_flag = (cmd->base.duplex != DUPLEX_HALF &&
cmd->base.duplex != DUPLEX_FULL);
if (check_flag)
return -EINVAL;
return 0;
}
int hns3_set_link_ksettings_it(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
int ret = 0;
if (!h->ae_algo || !h->ae_algo->ops)
return -ESRCH;
ret = hns3_check_ksettings_para(netdev, cmd);
if (ret)
return ret;
netdev_info(netdev, "set link setting autoneg = %d, speed = %d, duplex = %d\n",
cmd->base.autoneg, cmd->base.speed, cmd->base.duplex);
if (netdev->phydev)
return phy_ethtool_ksettings_set(netdev->phydev, cmd);
if (h->ae_algo->ops->set_autoneg)
h->ae_algo->ops->set_autoneg(h, cmd->base.autoneg);
if (h->ae_algo->ops->cfg_mac_speed_dup_h)
h->ae_algo->ops->cfg_mac_speed_dup_h(h,
cmd->base.speed, cmd->base.duplex);
return 0;
}
EXPORT_SYMBOL(hns3_set_link_ksettings_it);
// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2016-2017 Hisilicon Limited.
#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
#include <linux/interrupt.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/skbuff.h>
#include <linux/sctp.h>
#include <linux/vermagic.h>
#include <net/gre.h>
#include <net/pkt_cls.h>
#include <net/vxlan.h>
#include "hns3_ext.h"
extern const char hns3_driver_name[];
int nic_netdev_match_check(struct net_device *netdev)
{
struct ethtool_drvinfo drv_info;
if (!netdev)
return -EINVAL;
if (netdev->ethtool_ops && netdev->ethtool_ops->get_drvinfo)
netdev->ethtool_ops->get_drvinfo(netdev, &drv_info);
if (!strncmp(drv_info.driver, hns3_driver_name,
strlen(hns3_driver_name)))
return 0;
return -EINVAL;
}
EXPORT_SYMBOL(nic_netdev_match_check);
void nic_chip_recover_handler(struct net_device *netdev,
enum hnae3_reset_type_custom event_t)
{
struct hnae3_ae_dev *ae_dev;
struct hns3_nic_priv *priv;
struct hnae3_handle *h;
if (nic_netdev_match_check(netdev))
return;
priv = netdev_priv(netdev);
h = priv->ae_handle;
ae_dev = pci_get_drvdata(h->pdev);
if (ae_dev->ops->reset_event)
ae_dev->ops->reset_event(h->pdev, NULL);
}
EXPORT_SYMBOL(nic_chip_recover_handler);
int nic_clean_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats)
{
struct hns3_nic_priv *priv;
struct hnae3_handle *h;
struct hnae3_knic_private_info *kinfo;
struct hns3_enet_ring *ring;
int i;
if (nic_netdev_match_check(ndev))
return -ENODEV;
priv = netdev_priv(ndev);
h = hns3_get_handle(ndev);
kinfo = &h->kinfo;
hclge_clean_stats64(h);
for (i = 0; i < kinfo->num_tqps; i++) {
ring = priv->ring_data[i].ring;
memset(&ring->stats, 0, sizeof(struct ring_stats));
ring = priv->ring_data[i + kinfo->num_tqps].ring;
memset(&ring->stats, 0, sizeof(struct ring_stats));
}
memset(&ndev->stats, 0, sizeof(struct net_device_stats));
return 0;
}
EXPORT_SYMBOL(nic_clean_stats64);
int nic_get_chipid(struct net_device *ndev, u32 *chip_id)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
if (!chip_id)
return -EINVAL;
h = hns3_get_handle(ndev);
return hclge_get_chipid(h, chip_id);
}
EXPORT_SYMBOL(nic_get_chipid);
int nic_get_sfpinfo(struct net_device *ndev, u8 *buff, u16 size, u16 *outlen)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
if (!buff || !outlen)
return -EINVAL;
h = hns3_get_handle(ndev);
return hclge_get_sfpinfo(h, buff, 0, size, outlen);
}
EXPORT_SYMBOL(nic_get_sfpinfo);
int nic_get_sfp_present(struct net_device *ndev, u32 *present)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
if (!present)
return -EINVAL;
h = hns3_get_handle(ndev);
return hclge_get_sfp_present(h, present);
}
EXPORT_SYMBOL(nic_get_sfp_present);
int nic_set_sfp_state(struct net_device *ndev, bool en)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
h = hns3_get_handle(ndev);
return hclge_set_sfp_state(h, en);
}
EXPORT_SYMBOL(nic_set_sfp_state);
int nic_get_sfp_speed(struct net_device *ndev, u32 *speed)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
if (!speed)
return -EINVAL;
h = hns3_get_handle(ndev);
return hclge_ext_get_sfp_speed(h, speed);
}
EXPORT_SYMBOL(nic_get_sfp_speed);
int nic_get_chip_num(struct net_device *ndev, u32 *chip_num)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
if (!chip_num)
return -EINVAL;
h = hns3_get_handle(ndev);
return hclge_get_chip_num(h, chip_num);
}
EXPORT_SYMBOL(nic_get_chip_num);
int nic_get_port_num_per_chip(struct net_device *ndev, u32 *port_num)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
if (!port_num)
return -EINVAL;
h = hns3_get_handle(ndev);
return hclge_get_port_num(h, port_num);
}
EXPORT_SYMBOL(nic_get_port_num_per_chip);
int nic_set_led(struct net_device *ndev, int type, int status)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
h = hns3_get_handle(ndev);
return hclge_set_led(h, type, status);
}
EXPORT_SYMBOL(nic_set_led);
int nic_get_led_signal(struct net_device *ndev, struct hns3_lamp_signal *signal)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
if (!signal)
return -EINVAL;
h = hns3_get_handle(ndev);
return hclge_get_led_signal(h, signal);
}
EXPORT_SYMBOL(nic_get_led_signal);
int nic_disable_net_lane(struct net_device *ndev)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
h = hns3_get_handle(ndev);
return hclge_disable_net_lane(h);
}
EXPORT_SYMBOL(nic_disable_net_lane);
int nic_get_net_lane_status(struct net_device *ndev, u32 *status)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
if (!status)
return -EINVAL;
h = hns3_get_handle(ndev);
return hclge_get_net_lane_status(h, status);
}
EXPORT_SYMBOL(nic_get_net_lane_status);
int nic_set_mac_state(struct net_device *ndev, int enable)
{
struct hnae3_handle *h;
bool en;
if (nic_netdev_match_check(ndev))
return -ENODEV;
h = hns3_get_handle(ndev);
en = !!enable;
return hclge_set_mac_state(h, en);
}
EXPORT_SYMBOL(nic_set_mac_state);
int nic_set_cpu_affinity(struct net_device *netdev, cpumask_t *affinity_mask)
{
struct hns3_enet_tqp_vector *tqp_vector;
struct hns3_nic_priv *priv;
int ret;
u16 i;
if (!netdev || !affinity_mask) {
pr_err("Invalid input param when set ethernet cpu affinity\n");
return -EINVAL;
}
if (nic_netdev_match_check(netdev))
return -ENODEV;
priv = netdev_priv(netdev);
if (test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
dev_err(&netdev->dev, "ethernet is down, not support cpu affinity set\n");
return -EOPNOTSUPP;
}
for (i = 0; i < priv->vector_num; i++) {
tqp_vector = &priv->tqp_vector[i];
if (tqp_vector->irq_init_flag != HNS3_VECTOR_INITED)
continue;
tqp_vector->affinity_mask = *affinity_mask;
ret = irq_set_affinity_hint(tqp_vector->vector_irq, NULL);
if (ret) {
dev_err(&netdev->dev, "reset affinity hint fail, ret = %d\n",
ret);
return ret;
}
ret = irq_set_affinity_hint(tqp_vector->vector_irq,
&tqp_vector->affinity_mask);
if (ret) {
dev_err(&netdev->dev, "set affinity hint fail, ret = %d\n",
ret);
return ret;
}
}
dev_info(&netdev->dev, "set nic cpu affinity %*pb succeed\n",
cpumask_pr_args(affinity_mask));
return 0;
}
EXPORT_SYMBOL(nic_set_cpu_affinity);
int nic_disable_clock(struct net_device *ndev)
{
struct hnae3_handle *h;
if (nic_netdev_match_check(ndev))
return -ENODEV;
h = hns3_get_handle(ndev);
return hclge_config_nic_clock(h, 0);
}
EXPORT_SYMBOL(nic_disable_clock);
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) 2016-2017 Hisilicon Limited. */
#ifndef __HNS3_EXT_H
#define __HNS3_EXT_H
#include <linux/types.h>
#include "../hns3_enet.h"
#include "hns3pf/hclge_ext.h"
#include "hns3pf/hclge_main_it.h"
/**
* nic_chip_recover_handler - reset net device by port id
* @netdev: net device
* @hnae3_reset_type: nic device event type
*/
void nic_chip_recover_handler(struct net_device *netdev,
enum hnae3_reset_type_custom event_t);
int nic_netdev_match_check(struct net_device *netdev);
int nic_clean_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats);
int nic_get_sfpinfo(struct net_device *netdev, u8 *buff, u16 size, u16 *outlen);
int nic_set_sfp_state(struct net_device *netdev, bool en);
int nic_get_sfp_id(struct net_device *netdev, u32 *sfp_id);
int nic_get_port_num_per_chip(struct net_device *ndev, u32 *port_num);
int nic_get_chip_num(struct net_device *ndev, u32 *chip_num);
int nic_set_led(struct net_device *ndev, int type, int status);
int nic_disable_net_lane(struct net_device *ndev);
int nic_get_net_lane_status(struct net_device *ndev, u32 *status);
int nic_set_cpu_affinity(struct net_device *netdev, cpumask_t *affinity_mask);
int nic_get_led_signal(struct net_device *ndev,
struct hns3_lamp_signal *signal);
int nic_set_mac_state(struct net_device *ndev, int enable);
int nic_disable_clock(struct net_device *ndev);
#endif
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2016-2017 Hisilicon Limited.
#include "../../hns3pf/hclge_cmd.h"
#include "../../hnae3.h"
#include "../../hns3pf/hclge_main.h"
#ifdef CONFIG_HNS3_TEST
#include "hclge_test.h"
EXPORT_SYMBOL(hclge_cmd_reuse_desc);
EXPORT_SYMBOL(hclge_cmd_setup_basic_desc);
EXPORT_SYMBOL(hclge_cmd_send);
#endif
// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2016-2017 Hisilicon Limited.
#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
#include <linux/interrupt.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/skbuff.h>
#include <linux/sctp.h>
#include <linux/vermagic.h>
#include <net/gre.h>
#include <net/pkt_cls.h>
#include <net/vxlan.h>
#include "../../hns3pf/hclge_main.h"
#include "../../hnae3.h"
#include "../../hns3pf/hclge_cmd.h"
#include "hclge_ext.h"
void hclge_clean_stats64(struct hnae3_handle *handle)
{
struct hnae3_knic_private_info *kinfo;
struct hclge_vport *vport;
struct hclge_dev *hdev;
struct hclge_tqp *tqp;
int i;
kinfo = &handle->kinfo;
vport = hclge_get_vport(handle);
hdev = vport->back;
for (i = 0; i < kinfo->num_tqps; i++) {
tqp = container_of(kinfo->tqp[i], struct hclge_tqp, q);
memset(&tqp->tqp_stats, 0, sizeof(struct hlcge_tqp_stats));
}
memset(&hdev->hw_stats.mac_stats, 0, sizeof(struct hclge_mac_stats));
}
EXPORT_SYMBOL(hclge_clean_stats64);
int hclge_get_chipid(struct hnae3_handle *handle, u32 *chip_id)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_chip_id_cmd *resp = NULL;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CHIP_ID_GET, true);
resp = (struct hclge_chip_id_cmd *)(desc.data);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev, "get chip id failed %d\n", ret);
return ret;
}
*chip_id = resp->chip_id;
return 0;
}
EXPORT_SYMBOL(hclge_get_chipid);
int hclge_get_commit_id(struct hnae3_handle *handle, u8 *commit_id,
u32 *ncl_version)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_commit_id_cmd *resp = NULL;
struct hclge_desc desc;
int ret, i;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_IMP_COMMIT_ID_GET, true);
resp = (struct hclge_commit_id_cmd *)(desc.data);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev, "get commit id failed %d\n", ret);
return ret;
}
for (i = 0; i < 8; i++)
commit_id[i] = resp->commit_id[i];
commit_id[8] = '\0';
*ncl_version = resp->ncl_version;
return 0;
}
EXPORT_SYMBOL(hclge_get_commit_id);
static int _hclge_get_sfpinfo(struct hnae3_handle *handle, u8 *buff,
u16 offset, u16 size, u16 *outlen)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_desc desc[HCLGE_SFP_INFO_LEN];
struct hclge_dev *hdev = vport->back;
struct hclge_sfp_info *resp = NULL;
int ret;
int i;
int j;
for (i = 0; i < HCLGE_SFP_INFO_LEN; i++) {
hclge_cmd_setup_basic_desc(&desc[i],
HCLGE_OPC_SFP_GET_INFO, true);
if (i == 0)
desc[0].data[0] = offset | (size << 16);
if (i < HCLGE_SFP_INFO_LEN - 1)
desc[i].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
else
desc[i].flag &= ~(cpu_to_le16(HCLGE_CMD_FLAG_NEXT));
}
ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_SFP_INFO_LEN);
if (ret) {
dev_err(&hdev->pdev->dev,
"get spf information cmd failed %d\n",
ret);
return ret;
}
for (i = 0; i < HCLGE_SFP_INFO_LEN; i++) {
resp = (struct hclge_sfp_info *)desc[i].data;
if (i == 0) {
*outlen = (resp[i].sfpinfo[0] >> 16) & 0xFFFF;
for (j = 1; j < 6; j++) {
*(u32 *)buff = resp->sfpinfo[j];
buff = buff + sizeof(u32);
}
} else {
for (j = 0; j < 6; j++) {
*(u32 *)buff = resp->sfpinfo[j];
buff = buff + sizeof(u32);
}
}
}
return 0;
}
int hclge_get_sfpinfo(struct hnae3_handle *handle, u8 *buff, u16 offset,
u16 size, u16 *outlen)
{
u16 tmp_size;
u8 *tmp_buff;
u16 tmp_outlen;
int ret;
tmp_buff = buff;
while (size) {
WARN_ON_ONCE(!tmp_buff);
if (size > HCLGE_SFP_INFO_SIZE)
tmp_size = HCLGE_SFP_INFO_SIZE;
else
tmp_size = size;
ret = _hclge_get_sfpinfo(handle, tmp_buff, offset, tmp_size,
&tmp_outlen);
if (ret)
return ret;
offset += tmp_size;
size -= tmp_size;
tmp_buff += tmp_size;
*outlen += tmp_outlen;
if (tmp_size != tmp_outlen)
break;
}
return 0;
}
EXPORT_SYMBOL(hclge_get_sfpinfo);
int hclge_set_sfp_state(struct hnae3_handle *handle, bool en)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_sfp_enable_cmd *req = NULL;
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SFP_SET_STATUS, false);
req = (struct hclge_sfp_enable_cmd *)desc.data;
req->set_sfp_enable_flag = en;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret)
dev_err(&hdev->pdev->dev,
"set spf on/off cmd failed %d\n", ret);
return ret;
}
EXPORT_SYMBOL(hclge_set_sfp_state);
int hclge_get_chip_num(struct hnae3_handle *handle, u32 *chip_num)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_GET_CHIP_NUM, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev, "get chip number failed %d\n", ret);
return ret;
}
*chip_num = desc.data[0];
return 0;
}
EXPORT_SYMBOL(hclge_get_chip_num);
int hclge_ext_get_sfp_speed(struct hnae3_handle *handle, u32 *speed)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret = 0;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_GET_SFP_INFO, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret == -EOPNOTSUPP) {
dev_warn(&hdev->pdev->dev,
"IMP do not support get SFP speed %d\n", ret);
return ret;
} else if (ret) {
dev_err(&hdev->pdev->dev, "get sfp speed failed %d\n", ret);
return ret;
}
*speed = desc.data[0];
return 0;
}
EXPORT_SYMBOL(hclge_ext_get_sfp_speed);
int hclge_get_port_num(struct hnae3_handle *handle, u32 *port_num)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_GET_PORT_NUM, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev, "get port number failed %d\n", ret);
return ret;
}
*port_num = desc.data[0];
return 0;
}
EXPORT_SYMBOL(hclge_get_port_num);
int hclge_set_led(struct hnae3_handle *handle, u32 type, u32 status)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SET_LED, false);
desc.data[0] = type;
desc.data[1] = status;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev, "get set led failed %d\n", ret);
return ret;
}
return 0;
}
EXPORT_SYMBOL(hclge_set_led);
int hclge_get_led_signal(struct hnae3_handle *handle,
struct hns3_lamp_signal *signal)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SET_LED, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"hclge_get_sgpio_tx_reg failed %d\n", ret);
return ret;
}
signal->error = desc.data[2] & 0xFF;
signal->locate = (desc.data[2] >> 8) & 0xFF;
signal->activity = (desc.data[2] >> 16) & 0xFF;
return 0;
}
EXPORT_SYMBOL(hclge_get_led_signal);
int hclge_get_sfp_present(struct hnae3_handle *handle, u32 *present)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_sfp_present_cmd *resp = NULL;
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret = 0;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SFP_GET_PRESENT, true);
resp = (struct hclge_sfp_present_cmd *)desc.data;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev, "get spf present failed %d\n", ret);
return ret;
}
*present = resp->sfp_present;
return 0;
}
EXPORT_SYMBOL(hclge_get_sfp_present);
int hclge_disable_net_lane(struct hnae3_handle *handle)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret = 0;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_DISABLE_NET_LANE, false);
desc.data[0] = 0;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev, "disable net lane failed %d\n", ret);
return ret;
}
return 0;
}
EXPORT_SYMBOL(hclge_disable_net_lane);
int hclge_get_net_lane_status(struct hnae3_handle *handle, u32 *status)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret = 0;
desc.data[0] = 0;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_DISABLE_NET_LANE, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev, "disable net lane failed %d\n", ret);
return ret;
}
*status = desc.data[0];
return 0;
}
EXPORT_SYMBOL(hclge_get_net_lane_status);
int hclge_set_mac_state(struct hnae3_handle *handle, bool enable)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
struct hclge_config_mac_mode_cmd *req =
(struct hclge_config_mac_mode_cmd *)desc.data;
u32 loop_en = 0;
int ret = 0;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_MAC_MODE, false);
hnae3_set_bit(loop_en, HCLGE_MAC_TX_EN_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_RX_EN_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_PAD_TX_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_PAD_RX_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_1588_TX_B, 0);
hnae3_set_bit(loop_en, HCLGE_MAC_1588_RX_B, 0);
hnae3_set_bit(loop_en, HCLGE_MAC_APP_LP_B, 0);
hnae3_set_bit(loop_en, HCLGE_MAC_LINE_LP_B, 0);
hnae3_set_bit(loop_en, HCLGE_MAC_FCS_TX_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_RX_FCS_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_RX_FCS_STRIP_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B, enable);
hnae3_set_bit(loop_en, HCLGE_MAC_TX_UNDER_MIN_ERR_B, enable);
req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret)
dev_err(&hdev->pdev->dev,
"set mac state %x fail, ret =%d.\n", enable, ret);
return ret;
}
EXPORT_SYMBOL(hclge_set_mac_state);
int hclge_config_nic_clock(struct hnae3_handle *handle, bool enable)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
u32 nic_clock_en = enable;
struct hclge_desc desc;
int ret = 0;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_NIC_CLOCK, false);
desc.data[0] = nic_clock_en;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret)
dev_err(&hdev->pdev->dev,
"config_nic_clock %x fail, ret = %d.\n",
nic_clock_en, ret);
return ret;
}
EXPORT_SYMBOL(hclge_config_nic_clock);
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) 2016-2017 Hisilicon Limited. */
#ifndef __HCLGE_EXT_H
#define __HCLGE_EXT_H
#include <linux/types.h>
#include "../../hnae3.h"
#define HCLGE_SFP_INFO_LEN 6
#define HCLGE_SFP_INFO_SIZE 140
#define HCLGE_OPC_CONFIG_NIC_CLOCK 0x0060
struct hclge_chip_id_cmd {
u32 chip_id;
u32 rsv[5];
};
struct hclge_commit_id_cmd {
u8 commit_id[8];
u32 ncl_version;
u32 rsv[3];
};
struct hclge_sfp_info {
u32 sfpinfo[6];
};
struct hclge_sfp_enable_cmd {
u32 set_sfp_enable_flag;
u32 rsv[5];
};
struct hclge_sfp_present_cmd {
u32 sfp_present;
u32 rsv[5];
};
struct hns3_lamp_signal {
u8 error;
u8 locate;
u8 activity;
};
enum hclge_ext_opcode_type {
/* misc command */
HCLGE_OPC_CHIP_ID_GET = 0x7003,
HCLGE_OPC_IMP_COMMIT_ID_GET = 0x7004,
HCLGE_OPC_GET_CHIP_NUM = 0x7005,
HCLGE_OPC_GET_PORT_NUM = 0x7006,
HCLGE_OPC_SET_LED = 0x7007,
HCLGE_OPC_DISABLE_NET_LANE = 0x7008,
/*SFP command*/
HCLGE_OPC_SFP_GET_INFO = 0x7100,
HCLGE_OPC_SFP_GET_PRESENT = 0x7101,
HCLGE_OPC_SFP_SET_STATUS = 0x7102,
};
void hclge_clean_stats64(struct hnae3_handle *handle);
int hclge_get_chipid(struct hnae3_handle *handle, u32 *chip_id);
int hclge_get_commit_id(struct hnae3_handle *handle, u8 *commit_id,
u32 *ncl_version);
int hclge_get_sfpinfo(struct hnae3_handle *handle, u8 *buff, u16 offset,
u16 size, u16 *outlen);
int hclge_set_sfp_state(struct hnae3_handle *handle, bool en);
int hclge_get_chip_num(struct hnae3_handle *handle, u32 *chip_num);
int hclge_get_port_num(struct hnae3_handle *handle, u32 *port_num);
int hclge_set_led(struct hnae3_handle *handle, u32 type, u32 status);
int hclge_get_sfp_present(struct hnae3_handle *handle, u32 *present);
int hclge_disable_net_lane(struct hnae3_handle *handle);
int hclge_get_net_lane_status(struct hnae3_handle *handle, u32 *status);
int hclge_ext_get_sfp_speed(struct hnae3_handle *handle, u32 *speed);
int hclge_get_led_signal(struct hnae3_handle *handle,
struct hns3_lamp_signal *signal);
int hclge_set_mac_state(struct hnae3_handle *handle, bool enable);
int hclge_config_nic_clock(struct hnae3_handle *handle, bool enable);
#endif
// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2016-2017 Hisilicon Limited.
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/if_vlan.h>
#include <net/rtnetlink.h>
#include "../../kcompat.h"
#include "../../hns3pf/hclge_cmd.h"
#include "../../hns3pf/hclge_main.h"
#include "../../hnae3.h"
#include "hclge_ext.h"
#include "hclge_main_it.h"
#include "../../hns3pf/hclge_err.h"
#ifdef CONFIG_HNS3_TEST
#include "hclge_test.h"
#endif
#ifdef CONFIG_EXT_TEST
#define HCLGE_RESET_MAX_FAIL_CNT 1
static nic_event_fn_t nic_event_call;
int nic_register_event(nic_event_fn_t event_call)
{
if (!event_call) {
pr_err("register event handle is null.\n");
return -EINVAL;
}
nic_event_call = event_call;
pr_info("netdev register success.\n");
return 0;
}
EXPORT_SYMBOL(nic_register_event);
int nic_unregister_event(void)
{
nic_event_call = NULL;
return 0;
}
EXPORT_SYMBOL(nic_unregister_event);
void nic_call_event(struct net_device *netdev,
enum hnae3_reset_type_custom event_t)
{
if (nic_event_call)
nic_event_call(netdev, event_t);
netdev_info(netdev, "report reset event %d\n", event_t);
}
EXPORT_SYMBOL(nic_call_event);
bool hclge_reset_done_it(struct hnae3_handle *handle, bool done)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct net_device *netdev;
netdev = hdev->vport[0].nic.netdev;
if (done) {
dev_info(&hdev->pdev->dev, "Report Reset DONE!\n");
nic_call_event(netdev, HNAE3_RESET_DONE_CUSTOM);
}
if (hdev->reset_fail_cnt >= HCLGE_RESET_MAX_FAIL_CNT) {
dev_err(&hdev->pdev->dev, "Report Reset fail!\n");
nic_call_event(netdev, HNAE3_PORT_FAULT);
}
return done;
}
pci_ers_result_t hclge_handle_hw_ras_error_it(struct hnae3_ae_dev *ae_dev)
{
struct hclge_dev *hdev = ae_dev->priv;
struct device *dev = &hdev->pdev->dev;
enum hnae3_reset_type_custom reset_type;
struct net_device *netdev;
u32 status;
netdev = hdev->vport[0].nic.netdev;
status = hclge_read_dev(&hdev->hw, HCLGE_RAS_PF_OTHER_INT_STS_REG);
if (status & HCLGE_RAS_REG_NFE_MASK ||
status & HCLGE_RAS_REG_ROCEE_ERR_MASK)
ae_dev->hw_err_reset_req = 0;
/* Handling Non-fatal HNS RAS errors */
if (status & HCLGE_RAS_REG_NFE_MASK) {
dev_warn(dev,
"HNS Non-Fatal RAS error(status=0x%x) identified\n",
status);
hclge_handle_all_ras_errors(hdev);
reset_type = ae_dev->ops->set_default_reset_request(ae_dev,
&ae_dev->hw_err_reset_req);
if (reset_type != HNAE3_NONE_RESET_CUSTOM)
nic_call_event(netdev, reset_type);
} else {
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) ||
hdev->pdev->revision < 0x21) {
ae_dev->override_pci_need_reset = 1;
return PCI_ERS_RESULT_RECOVERED;
}
}
if (status & HCLGE_RAS_REG_ROCEE_ERR_MASK) {
dev_warn(dev, "ROCEE uncorrected RAS error identified\n");
hclge_handle_rocee_ras_error(ae_dev);
}
if ((status & HCLGE_RAS_REG_NFE_MASK ||
status & HCLGE_RAS_REG_ROCEE_ERR_MASK) &&
ae_dev->hw_err_reset_req) {
ae_dev->override_pci_need_reset = 0;
return PCI_ERS_RESULT_NEED_RESET;
}
ae_dev->override_pci_need_reset = 1;
return PCI_ERS_RESULT_RECOVERED;
}
#endif
#ifdef CONFIG_IT_VALIDATION
#define HCLGE_NAME_IT "hclge"
EXPORT_SYMBOL(hclge_get_vport);
EXPORT_SYMBOL(hclge_cmd_set_promisc_mode);
EXPORT_SYMBOL(hclge_promisc_param_init);
struct pci_device_id ae_algo_pci_tbl_it[] = {
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_GE), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA_MACSEC), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA_MACSEC), 0},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC), 0},
#ifdef CONFIG_HNS3_X86
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_X86_25_GE), 0},
#endif
/* required last entry */
{0, }
};
int hclge_init_it(void)
{
pr_info("%s is initializing\n", HCLGE_NAME_IT);
#ifdef CONFIG_HNS3_TEST
hclge_ops.send_cmdq = hclge_send_cmdq;
#endif
#ifdef CONFIG_EXT_TEST
hclge_ops.handle_hw_ras_error = hclge_handle_hw_ras_error_it;
hclge_ops.reset_done = hclge_reset_done_it;
#endif
ae_algo.pdev_id_table = ae_algo_pci_tbl_it;
hnae3_register_ae_algo(&ae_algo);
return 0;
}
module_init(hclge_init_it);
#endif
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) 2016-2017 Hisilicon Limited. */
#ifndef __HCLGE_MAIN_IT_H
#define __HCLGE_MAIN_IT_H
extern struct hnae3_ae_algo ae_algo;
extern struct hnae3_ae_ops hclge_ops;
enum hnae3_reset_type_custom {
HNAE3_VF_RESET_CUSTOM,
HNAE3_VF_FUNC_RESET_CUSTOM,
HNAE3_VF_PF_FUNC_RESET_CUSTOM,
HNAE3_VF_FULL_RESET_CUSTOM,
HNAE3_FLR_RESET_CUSTOM,
HNAE3_FUNC_RESET_CUSTOM,
HNAE3_GLOBAL_RESET_CUSTOM,
HNAE3_IMP_RESET_CUSTOM,
HNAE3_UNKNOWN_RESET_CUSTOM,
HNAE3_NONE_RESET_CUSTOM,
HNAE3_PORT_FAULT,
HNAE3_RESET_DONE_CUSTOM,
};
#ifdef CONFIG_EXT_TEST
/**
* nic_event_fn_t - nic event handler prototype
* @netdev: net device
* @hnae3_reset_type_custom: nic device event type
*/
typedef void (*nic_event_fn_t) (struct net_device *netdev,
enum hnae3_reset_type_custom);
/**
* nic_register_event - register for nic event listening
* @event_call: nic event handler
* return 0 - success , negative - fail
*/
int nic_register_event(nic_event_fn_t event_call);
/**
* nic_unregister_event - quit nic event listening
* return 0 - success , negative - fail
*/
int nic_unregister_event(void);
void nic_call_event(struct net_device *netdev,
enum hnae3_reset_type_custom event_t);
#endif
#endif
// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2016-2017 Hisilicon Limited.
#include <linux/module.h>
#include "hclge_test.h"
int hclge_send_cmdq(struct hnae3_handle *handle, void *data, int num)
{
struct hclge_vport *vport;
struct hclge_dev *hdev;
vport = hclge_get_vport(handle);
hdev = vport->back;
return (int)hclge_cmd_send(&hdev->hw, data, num);
}
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) 2016-2017 Hisilicon Limited. */
#ifndef __HCLGE_TEST_H
#define __HCLGE_TEST_H
#include "../../hns3pf/hclge_cmd.h"
#include "../../hns3pf/hclge_main.h"
int hclge_send_cmdq(struct hnae3_handle *handle, void *data, int num);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册