OpenCloudOS-Kernel/drivers/thirdparty/ixgbe/ixgbe_cna.c

150 lines
4.0 KiB
C

// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 1999 - 2020 Intel Corporation. */
#include "ixgbe.h"
#include "ixgbe_cna.h"
#include "ixgbe_vmdq.h"
static int ixgbe_cna_open(struct net_device *cnadev)
{
struct ixgbe_adapter *adapter = netdev_priv(cnadev);
strscpy(cnadev->name, adapter->netdev->name, sizeof(cnadev->name));
DPRINTK(PROBE, INFO, "CNA pseudo device opened %s\n", cnadev->name);
return 0;
}
static int ixgbe_cna_close(struct net_device *cnadev)
{
struct ixgbe_adapter *adapter = netdev_priv(cnadev);
DPRINTK(PROBE, INFO, "CNA pseudo device closed %s\n", cnadev->name);
return 0;
}
static int ixgbe_cna_change_mtu(struct net_device *cnadev, int new_mtu)
{
struct ixgbe_adapter *adapter = netdev_priv(cnadev);
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
/* MTU < 68 is an error and causes problems on some kernels */
if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
return -EINVAL;
DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n",
cnadev->mtu, new_mtu);
/* must set new MTU before calling down or up */
cnadev->mtu = new_mtu;
return 0;
}
int ixgbe_cna_enable(struct ixgbe_adapter *adapter)
{
struct net_device *cnadev;
struct net_device *netdev;
int err;
u64 wwpn;
u64 wwnn;
netdev = adapter->netdev;
/*
* Oppositely to regular net device, CNA device doesn't have
* a private allocated region as we don't want to duplicate
* ixgbe_adapter information. Though, the CNA device still need
* to access the ixgbe_adapter while allocating queues or such. Thereby,
* cnadev->priv needs to point to netdev->priv.
*/
cnadev = alloc_etherdev_mq(0, MAX_TX_QUEUES);
if (!cnadev) {
err = -ENOMEM;
goto err_alloc_etherdev;
}
adapter->cnadev = cnadev;
SET_MODULE_OWNER(cnadev);
cnadev->priv = adapter;
cnadev->open = &ixgbe_cna_open;
cnadev->stop = &ixgbe_cna_close;
cnadev->change_mtu = &ixgbe_cna_change_mtu;
cnadev->do_ioctl = netdev->do_ioctl;
cnadev->hard_start_xmit = netdev->hard_start_xmit;
#if defined(NETIF_F_HW_VLAN_TX) || defined(NETIF_F_HW_VLAN_CTAG_TX)
cnadev->vlan_rx_register = netdev->vlan_rx_register;
cnadev->vlan_rx_add_vid = netdev->vlan_rx_add_vid;
cnadev->vlan_rx_kill_vid = netdev->vlan_rx_kill_vid;
#endif
ixgbe_set_ethtool_ops(cnadev);
#if IS_ENABLED(CONFIG_DCB)
cnadev->dcbnl_ops = netdev->dcbnl_ops;
#endif /* CONFIG_DCB */
cnadev->mtu = netdev->mtu;
cnadev->pdev = netdev->pdev;
cnadev->gso_max_size = GSO_MAX_SIZE;
cnadev->features = netdev->features | NETIF_F_CNA | NETIF_F_HW_VLAN_FILTER;
/* set the MAC address to SAN mac address */
if (ixgbe_validate_mac_addr(adapter->hw.mac.san_addr) == 0)
memcpy(cnadev->dev_addr,
adapter->hw.mac.san_addr,
cnadev->addr_len);
cnadev->features |= NETIF_F_FCOE_CRC |
NETIF_F_FCOE_MTU |
NETIF_F_FSO;
cnadev->ndo_fcoe_ddp_setup = &ixgbe_fcoe_ddp_get;
cnadev->ndo_fcoe_ddp_done = &ixgbe_fcoe_ddp_put;
cnadev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
netif_carrier_off(cnadev);
netif_tx_stop_all_queues(cnadev);
VMKNETDDI_REGISTER_QUEUEOPS(cnadev, ixgbe_netqueue_ops);
err = register_netdev(cnadev);
if (err)
goto err_register;
DPRINTK(PROBE, INFO, "CNA pseudo device registered %s\n", netdev->name);
return err;
err_register:
DPRINTK(PROBE, INFO, "CNA pseudo device cannot be registered %s\n",
netdev->name);
free_netdev(cnadev);
err_alloc_etherdev:
DPRINTK(PROBE, INFO, "CNA cannot be enabled on %s\n", netdev->name);
adapter->flags2 &= ~IXGBE_FLAG2_CNA_ENABLED;
adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
adapter->ring_feature[RING_F_FCOE].indices = 0;
return err;
}
void ixgbe_cna_disable(struct ixgbe_adapter *adapter)
{
if (!(adapter->flags2 & IXGBE_FLAG2_CNA_ENABLED))
return;
adapter->flags2 &= ~IXGBE_FLAG2_CNA_ENABLED;
adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
adapter->ring_feature[RING_F_FCOE].indices = 0;
if (adapter->cnadev) {
unregister_netdev(adapter->cnadev);
DPRINTK(PROBE, INFO, "CNA pseudo device unregistered %s\n",
adapter->cnadev->name);
free_netdev(adapter->cnadev);
adapter->cnadev = NULL;
}
}
/* ixgbe_cna.c */