Commit a251eee6 authored by Joshua Hay's avatar Joshua Hay Committed by Tony Nguyen

idpf: add SRIOV support and other ndo_ops

Add support for SRIOV: send the requested number of VFs
to the device Control Plane, via the virtchnl message
and then enable the VFs using 'pci_enable_sriov'.

Add other ndo ops supported by the driver such as features_check,
set_rx_mode, validate_addr, set_mac_address, change_mtu, get_stats64,
set_features, and tx_timeout. Initialize the statistics task which
requests the queue related statistics to the CP. Add loopback
and promiscuous mode support and the respective virtchnl messages.

Finally, add documentation and build support for the driver.
Signed-off-by: default avatarJoshua Hay <joshua.a.hay@intel.com>
Co-developed-by: default avatarAlan Brady <alan.brady@intel.com>
Signed-off-by: default avatarAlan Brady <alan.brady@intel.com>
Co-developed-by: default avatarMadhu Chittim <madhu.chittim@intel.com>
Signed-off-by: default avatarMadhu Chittim <madhu.chittim@intel.com>
Co-developed-by: default avatarPhani Burra <phani.r.burra@intel.com>
Signed-off-by: default avatarPhani Burra <phani.r.burra@intel.com>
Reviewed-by: default avatarSridhar Samudrala <sridhar.samudrala@intel.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Co-developed-by: default avatarPavan Kumar Linga <pavan.kumar.linga@intel.com>
Signed-off-by: default avatarPavan Kumar Linga <pavan.kumar.linga@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 02cbfba1
......@@ -32,6 +32,7 @@ Contents:
intel/e1000
intel/e1000e
intel/fm10k
intel/idpf
intel/igb
intel/igbvf
intel/ixgbe
......
.. SPDX-License-Identifier: GPL-2.0+
==========================================================================
idpf Linux* Base Driver for the Intel(R) Infrastructure Data Path Function
==========================================================================
Intel idpf Linux driver.
Copyright(C) 2023 Intel Corporation.
.. contents::
The idpf driver serves as both the Physical Function (PF) and Virtual Function
(VF) driver for the Intel(R) Infrastructure Data Path Function.
Driver information can be obtained using ethtool, lspci, and ip.
For questions related to hardware requirements, refer to the documentation
supplied with your Intel adapter. All hardware requirements listed apply to use
with Linux.
Identifying Your Adapter
========================
For information on how to identify your adapter, and for the latest Intel
network drivers, refer to the Intel Support website:
http://www.intel.com/support
Additional Features and Configurations
======================================
ethtool
-------
The driver utilizes the ethtool interface for driver configuration and
diagnostics, as well as displaying statistical information. The latest ethtool
version is required for this functionality. If you don't have one yet, you can
obtain it at:
https://kernel.org/pub/software/network/ethtool/
Viewing Link Messages
---------------------
Link messages will not be displayed to the console if the distribution is
restricting system messages. In order to see network driver link messages on
your console, set dmesg to eight by entering the following::
# dmesg -n 8
.. note::
This setting is not saved across reboots.
Jumbo Frames
------------
Jumbo Frames support is enabled by changing the Maximum Transmission Unit (MTU)
to a value larger than the default value of 1500.
Use the ip command to increase the MTU size. For example, enter the following
where <ethX> is the interface number::
# ip link set mtu 9000 dev <ethX>
# ip link set up dev <ethX>
.. note::
The maximum MTU setting for jumbo frames is 9706. This corresponds to the
maximum jumbo frame size of 9728 bytes.
.. note::
This driver will attempt to use multiple page sized buffers to receive
each jumbo packet. This should help to avoid buffer starvation issues when
allocating receive packets.
.. note::
Packet loss may have a greater impact on throughput when you use jumbo
frames. If you observe a drop in performance after enabling jumbo frames,
enabling flow control may mitigate the issue.
Performance Optimization
========================
Driver defaults are meant to fit a wide variety of workloads, but if further
optimization is required, we recommend experimenting with the following
settings.
Interrupt Rate Limiting
-----------------------
This driver supports an adaptive interrupt throttle rate (ITR) mechanism that
is tuned for general workloads. The user can customize the interrupt rate
control for specific workloads, via ethtool, adjusting the number of
microseconds between interrupts.
To set the interrupt rate manually, you must disable adaptive mode::
# ethtool -C <ethX> adaptive-rx off adaptive-tx off
For lower CPU utilization:
- Disable adaptive ITR and lower Rx and Tx interrupts. The examples below
affect every queue of the specified interface.
- Setting rx-usecs and tx-usecs to 80 will limit interrupts to about
12,500 interrupts per second per queue::
# ethtool -C <ethX> adaptive-rx off adaptive-tx off rx-usecs 80
tx-usecs 80
For reduced latency:
- Disable adaptive ITR and ITR by setting rx-usecs and tx-usecs to 0
using ethtool::
# ethtool -C <ethX> adaptive-rx off adaptive-tx off rx-usecs 0
tx-usecs 0
Per-queue interrupt rate settings:
- The following examples are for queues 1 and 3, but you can adjust other
queues.
- To disable Rx adaptive ITR and set static Rx ITR to 10 microseconds or
about 100,000 interrupts/second, for queues 1 and 3::
# ethtool --per-queue <ethX> queue_mask 0xa --coalesce adaptive-rx off
rx-usecs 10
- To show the current coalesce settings for queues 1 and 3::
# ethtool --per-queue <ethX> queue_mask 0xa --show-coalesce
Virtualized Environments
------------------------
In addition to the other suggestions in this section, the following may be
helpful to optimize performance in VMs.
- Using the appropriate mechanism (vcpupin) in the VM, pin the CPUs to
individual LCPUs, making sure to use a set of CPUs included in the
device's local_cpulist: /sys/class/net/<ethX>/device/local_cpulist.
- Configure as many Rx/Tx queues in the VM as available. (See the idpf driver
documentation for the number of queues supported.) For example::
# ethtool -L <virt_interface> rx <max> tx <max>
Support
=======
For general information, go to the Intel support website at:
http://www.intel.com/support/
If an issue is identified with the released source code on a supported kernel
with a supported adapter, email the specific information related to the issue
to intel-wired-lan@lists.osuosl.org.
Trademarks
==========
Intel is a trademark or registered trademark of Intel Corporation or its
subsidiaries in the United States and/or other countries.
* Other names and brands may be claimed as the property of others.
......@@ -355,5 +355,17 @@ config IGC
To compile this driver as a module, choose M here. The module
will be called igc.
config IDPF
tristate "Intel(R) Infrastructure Data Path Function Support"
depends on PCI_MSI
select DIMLIB
select PAGE_POOL
select PAGE_POOL_STATS
help
This driver supports Intel(R) Infrastructure Data Path Function
devices.
To compile this driver as a module, choose M here. The module
will be called idpf.
endif # NET_VENDOR_INTEL
......@@ -15,3 +15,4 @@ obj-$(CONFIG_I40E) += i40e/
obj-$(CONFIG_IAVF) += iavf/
obj-$(CONFIG_FM10K) += fm10k/
obj-$(CONFIG_ICE) += ice/
obj-$(CONFIG_IDPF) += idpf/
......@@ -147,6 +147,8 @@ enum idpf_vport_state {
* @vport_id: Vport identifier
* @vport_idx: Relative vport index
* @state: See enum idpf_vport_state
* @netstats: Packet and byte stats
* @stats_lock: Lock to protect stats update
*/
struct idpf_netdev_priv {
struct idpf_adapter *adapter;
......@@ -154,6 +156,8 @@ struct idpf_netdev_priv {
u32 vport_id;
u16 vport_idx;
enum idpf_vport_state state;
struct rtnl_link_stats64 netstats;
spinlock_t stats_lock;
};
/**
......@@ -239,6 +243,8 @@ struct idpf_dev_ops {
STATE(IDPF_VC_ALLOC_VECTORS_ERR) \
STATE(IDPF_VC_DEALLOC_VECTORS) \
STATE(IDPF_VC_DEALLOC_VECTORS_ERR) \
STATE(IDPF_VC_SET_SRIOV_VFS) \
STATE(IDPF_VC_SET_SRIOV_VFS_ERR) \
STATE(IDPF_VC_GET_RSS_LUT) \
STATE(IDPF_VC_GET_RSS_LUT_ERR) \
STATE(IDPF_VC_SET_RSS_LUT) \
......@@ -247,12 +253,16 @@ struct idpf_dev_ops {
STATE(IDPF_VC_GET_RSS_KEY_ERR) \
STATE(IDPF_VC_SET_RSS_KEY) \
STATE(IDPF_VC_SET_RSS_KEY_ERR) \
STATE(IDPF_VC_GET_STATS) \
STATE(IDPF_VC_GET_STATS_ERR) \
STATE(IDPF_VC_ADD_MAC_ADDR) \
STATE(IDPF_VC_ADD_MAC_ADDR_ERR) \
STATE(IDPF_VC_DEL_MAC_ADDR) \
STATE(IDPF_VC_DEL_MAC_ADDR_ERR) \
STATE(IDPF_VC_GET_PTYPE_INFO) \
STATE(IDPF_VC_GET_PTYPE_INFO_ERR) \
STATE(IDPF_VC_LOOPBACK_STATE) \
STATE(IDPF_VC_LOOPBACK_STATE_ERR) \
STATE(IDPF_VC_NBITS)
#define IDPF_GEN_ENUM(ENUM) ENUM,
......@@ -268,10 +278,14 @@ extern const char * const idpf_vport_vc_state_str[];
* enum idpf_vport_reset_cause - Vport soft reset causes
* @IDPF_SR_Q_CHANGE: Soft reset queue change
* @IDPF_SR_Q_DESC_CHANGE: Soft reset descriptor change
* @IDPF_SR_MTU_CHANGE: Soft reset MTU change
* @IDPF_SR_RSC_CHANGE: Soft reset RSC change
*/
enum idpf_vport_reset_cause {
IDPF_SR_Q_CHANGE,
IDPF_SR_Q_DESC_CHANGE,
IDPF_SR_MTU_CHANGE,
IDPF_SR_RSC_CHANGE,
};
/**
......@@ -402,6 +416,19 @@ struct idpf_vport {
struct mutex vc_buf_lock;
};
/**
* enum idpf_user_flags
* @__IDPF_PROMISC_UC: Unicast promiscuous mode
* @__IDPF_PROMISC_MC: Multicast promiscuous mode
* @__IDPF_USER_FLAGS_NBITS: Must be last
*/
enum idpf_user_flags {
__IDPF_PROMISC_UC = 32,
__IDPF_PROMISC_MC,
__IDPF_USER_FLAGS_NBITS,
};
/**
* struct idpf_rss_data - Associated RSS data
* @rss_key_size: Size of RSS hash key
......@@ -428,6 +455,7 @@ struct idpf_rss_data {
* ethtool
* @num_req_rxq_desc: Number of user requested RX queue descriptors through
* ethtool
* @user_flags: User toggled config flags
* @mac_filter_list: List of MAC filters
*
* Used to restore configuration after a reset as the vport will get wiped.
......@@ -438,6 +466,7 @@ struct idpf_vport_user_config_data {
u16 num_req_rx_qs;
u32 num_req_txq_desc;
u32 num_req_rxq_desc;
DECLARE_BITMAP(user_flags, __IDPF_USER_FLAGS_NBITS);
struct list_head mac_filter_list;
};
......@@ -548,6 +577,7 @@ struct idpf_vport_config {
* @mb_vector: Mailbox vector data
* @vector_stack: Stack to store the msix vector indexes
* @irq_mb_handler: Handler for hard interrupt for mailbox
* @tx_timeout_count: Number of TX timeouts that have occurred
* @avail_queues: Device given queue limits
* @vports: Array to store vports created by the driver
* @netdevs: Associated Vport netdevs
......@@ -566,6 +596,8 @@ struct idpf_vport_config {
* @mbx_wq: Workqueue for mailbox responses
* @vc_event_task: Task to handle out of band virtchnl event notifications
* @vc_event_wq: Workqueue for virtchnl events
* @stats_task: Periodic statistics retrieval task
* @stats_wq: Workqueue for statistics task
* @caps: Negotiated capabilities with device
* @vchnl_wq: Wait queue for virtchnl messages
* @vc_state: Virtchnl message state
......@@ -601,6 +633,7 @@ struct idpf_adapter {
struct idpf_vector_lifo vector_stack;
irqreturn_t (*irq_mb_handler)(int irq, void *data);
u32 tx_timeout_count;
struct idpf_avail_queue_info avail_queues;
struct idpf_vport **vports;
struct net_device **netdevs;
......@@ -621,6 +654,8 @@ struct idpf_adapter {
struct workqueue_struct *mbx_wq;
struct delayed_work vc_event_task;
struct workqueue_struct *vc_event_wq;
struct delayed_work stats_task;
struct workqueue_struct *stats_wq;
struct virtchnl2_get_capabilities caps;
wait_queue_head_t vchnl_wq;
......@@ -825,6 +860,15 @@ static inline bool idpf_is_feature_ena(const struct idpf_vport *vport,
return vport->netdev->features & feature;
}
/**
* idpf_get_max_tx_hdr_size -- get the size of tx header
* @adapter: Driver specific private structure
*/
static inline u16 idpf_get_max_tx_hdr_size(struct idpf_adapter *adapter)
{
return le16_to_cpu(adapter->caps.max_tx_hdr_size);
}
/**
* idpf_vport_ctrl_lock - Acquire the vport control lock
* @netdev: Network interface device structure
......@@ -850,6 +894,7 @@ static inline void idpf_vport_ctrl_unlock(struct net_device *netdev)
mutex_unlock(&np->adapter->vport_ctrl_lock);
}
void idpf_statistics_task(struct work_struct *work);
void idpf_init_task(struct work_struct *work);
void idpf_service_task(struct work_struct *work);
void idpf_mbx_task(struct work_struct *work);
......@@ -865,6 +910,7 @@ int idpf_intr_req(struct idpf_adapter *adapter);
void idpf_intr_rel(struct idpf_adapter *adapter);
int idpf_get_reg_intr_vecs(struct idpf_vport *vport,
struct idpf_vec_regs *reg_vals);
u16 idpf_get_max_tx_hdr_size(struct idpf_adapter *adapter);
int idpf_send_delete_queues_msg(struct idpf_vport *vport);
int idpf_send_add_queues_msg(const struct idpf_vport *vport, u16 num_tx_q,
u16 num_complq, u16 num_rx_q, u16 num_rx_bufq);
......@@ -874,6 +920,7 @@ int idpf_send_enable_vport_msg(struct idpf_vport *vport);
int idpf_send_disable_vport_msg(struct idpf_vport *vport);
int idpf_send_destroy_vport_msg(struct idpf_vport *vport);
int idpf_send_get_rx_ptype_msg(struct idpf_vport *vport);
int idpf_send_ena_dis_loopback_msg(struct idpf_vport *vport);
int idpf_send_get_set_rss_key_msg(struct idpf_vport *vport, bool get);
int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get);
int idpf_send_dealloc_vectors_msg(struct idpf_adapter *adapter);
......@@ -883,6 +930,7 @@ int idpf_req_rel_vector_indexes(struct idpf_adapter *adapter,
u16 *q_vector_idxs,
struct idpf_vector_info *vec_info);
int idpf_vport_alloc_vec_indexes(struct idpf_vport *vport);
int idpf_send_get_stats_msg(struct idpf_vport *vport);
int idpf_get_vec_ids(struct idpf_adapter *adapter,
u16 *vecids, int num_vecids,
struct virtchnl2_vector_chunks *chunks);
......@@ -898,6 +946,9 @@ void idpf_vport_dealloc_max_qs(struct idpf_adapter *adapter,
int idpf_add_del_mac_filters(struct idpf_vport *vport,
struct idpf_netdev_priv *np,
bool add, bool async);
int idpf_set_promiscuous(struct idpf_adapter *adapter,
struct idpf_vport_user_config_data *config_data,
u32 vport_id);
int idpf_send_disable_queues_msg(struct idpf_vport *vport);
void idpf_vport_init(struct idpf_vport *vport, struct idpf_vport_max_q *max_q);
u32 idpf_get_vport_id(struct idpf_vport *vport);
......
This diff is collapsed.
......@@ -26,6 +26,9 @@ static void idpf_remove(struct pci_dev *pdev)
* end up in bad state.
*/
cancel_delayed_work_sync(&adapter->vc_event_task);
if (adapter->num_vfs)
idpf_sriov_configure(pdev, 0);
idpf_vc_core_deinit(adapter);
/* Be a good citizen and leave the device clean on exit */
adapter->dev_ops.reg_ops.trigger_reset(adapter, IDPF_HR_FUNC_RESET);
......@@ -52,6 +55,7 @@ static void idpf_remove(struct pci_dev *pdev)
destroy_workqueue(adapter->init_wq);
destroy_workqueue(adapter->serv_wq);
destroy_workqueue(adapter->mbx_wq);
destroy_workqueue(adapter->stats_wq);
destroy_workqueue(adapter->vc_event_wq);
for (i = 0; i < adapter->max_vports; i++) {
......@@ -192,6 +196,15 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_mbx_wq_alloc;
}
adapter->stats_wq = alloc_workqueue("%s-%s-stats", 0, 0,
dev_driver_string(dev),
dev_name(dev));
if (!adapter->stats_wq) {
dev_err(dev, "Failed to allocate workqueue\n");
err = -ENOMEM;
goto err_stats_wq_alloc;
}
adapter->vc_event_wq = alloc_workqueue("%s-%s-vc_event", 0, 0,
dev_driver_string(dev),
dev_name(dev));
......@@ -221,6 +234,7 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_DELAYED_WORK(&adapter->init_task, idpf_init_task);
INIT_DELAYED_WORK(&adapter->serv_task, idpf_service_task);
INIT_DELAYED_WORK(&adapter->mbx_task, idpf_mbx_task);
INIT_DELAYED_WORK(&adapter->stats_task, idpf_statistics_task);
INIT_DELAYED_WORK(&adapter->vc_event_task, idpf_vc_event_task);
adapter->dev_ops.reg_ops.reset_reg_init(adapter);
......@@ -233,6 +247,8 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_cfg_hw:
destroy_workqueue(adapter->vc_event_wq);
err_vc_event_wq_alloc:
destroy_workqueue(adapter->stats_wq);
err_stats_wq_alloc:
destroy_workqueue(adapter->mbx_wq);
err_mbx_wq_alloc:
destroy_workqueue(adapter->serv_wq);
......@@ -256,6 +272,7 @@ static struct pci_driver idpf_driver = {
.name = KBUILD_MODNAME,
.id_table = idpf_pci_tbl,
.probe = idpf_probe,
.sriov_configure = idpf_sriov_configure,
.remove = idpf_remove,
.shutdown = idpf_shutdown,
};
......
......@@ -33,6 +33,27 @@ static struct idpf_tx_stash *idpf_buf_lifo_pop(struct idpf_buf_lifo *stack)
return stack->bufs[--stack->top];
}
/**
* idpf_tx_timeout - Respond to a Tx Hang
* @netdev: network interface device structure
* @txqueue: TX queue
*/
void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue)
{
struct idpf_adapter *adapter = idpf_netdev_to_adapter(netdev);
adapter->tx_timeout_count++;
netdev_err(netdev, "Detected Tx timeout: Count %d, Queue %d\n",
adapter->tx_timeout_count, txqueue);
if (!idpf_is_reset_in_prog(adapter)) {
set_bit(IDPF_HR_FUNC_RESET, adapter->flags);
queue_delayed_work(adapter->vc_event_wq,
&adapter->vc_event_task,
msecs_to_jiffies(10));
}
}
/**
* idpf_tx_buf_rel - Release a Tx buffer
* @tx_q: the queue that owns the buffer
......
......@@ -101,6 +101,7 @@ do { \
#define IDPF_HDR_BUF_SIZE 256
#define IDPF_PACKET_HDR_PAD \
(ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN * 2)
#define IDPF_TX_TSO_MIN_MSS 88
/* Minimum number of descriptors between 2 descriptors with the RE bit set;
* only relevant in flow scheduling mode
......@@ -1010,6 +1011,7 @@ unsigned int idpf_tx_desc_count_required(struct idpf_queue *txq,
bool idpf_chk_linearize(struct sk_buff *skb, unsigned int max_bufs,
unsigned int count);
int idpf_tx_maybe_stop_common(struct idpf_queue *tx_q, unsigned int size);
void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue);
netdev_tx_t idpf_tx_splitq_start(struct sk_buff *skb,
struct net_device *netdev);
netdev_tx_t idpf_tx_singleq_start(struct sk_buff *skb,
......
......@@ -200,6 +200,7 @@ static int idpf_find_vport(struct idpf_adapter *adapter,
case VIRTCHNL2_OP_VERSION:
case VIRTCHNL2_OP_GET_CAPS:
case VIRTCHNL2_OP_CREATE_VPORT:
case VIRTCHNL2_OP_SET_SRIOV_VFS:
case VIRTCHNL2_OP_ALLOC_VECTORS:
case VIRTCHNL2_OP_DEALLOC_VECTORS:
case VIRTCHNL2_OP_GET_PTYPE_INFO:
......@@ -227,6 +228,9 @@ static int idpf_find_vport(struct idpf_adapter *adapter,
case VIRTCHNL2_OP_UNMAP_QUEUE_VECTOR:
v_id = le32_to_cpu(((struct virtchnl2_queue_vector_maps *)vc_msg)->vport_id);
break;
case VIRTCHNL2_OP_GET_STATS:
v_id = le32_to_cpu(((struct virtchnl2_vport_stats *)vc_msg)->vport_id);
break;
case VIRTCHNL2_OP_GET_RSS_LUT:
case VIRTCHNL2_OP_SET_RSS_LUT:
v_id = le32_to_cpu(((struct virtchnl2_rss_lut *)vc_msg)->vport_id);
......@@ -238,6 +242,12 @@ static int idpf_find_vport(struct idpf_adapter *adapter,
case VIRTCHNL2_OP_EVENT:
v_id = le32_to_cpu(((struct virtchnl2_event *)vc_msg)->vport_id);
break;
case VIRTCHNL2_OP_LOOPBACK:
v_id = le32_to_cpu(((struct virtchnl2_loopback *)vc_msg)->vport_id);
break;
case VIRTCHNL2_OP_CONFIG_PROMISCUOUS_MODE:
v_id = le32_to_cpu(((struct virtchnl2_promisc_info *)vc_msg)->vport_id);
break;
case VIRTCHNL2_OP_ADD_MAC_ADDR:
case VIRTCHNL2_OP_DEL_MAC_ADDR:
v_id = le32_to_cpu(((struct virtchnl2_mac_addr_list *)vc_msg)->vport_id);
......@@ -491,6 +501,11 @@ int idpf_recv_mb_msg(struct idpf_adapter *adapter, u32 op,
IDPF_VC_UNMAP_IRQ,
IDPF_VC_UNMAP_IRQ_ERR);
break;
case VIRTCHNL2_OP_GET_STATS:
idpf_recv_vchnl_op(adapter, vport, &ctlq_msg,
IDPF_VC_GET_STATS,
IDPF_VC_GET_STATS_ERR);
break;
case VIRTCHNL2_OP_GET_RSS_LUT:
idpf_recv_vchnl_op(adapter, vport, &ctlq_msg,
IDPF_VC_GET_RSS_LUT,
......@@ -511,6 +526,11 @@ int idpf_recv_mb_msg(struct idpf_adapter *adapter, u32 op,
IDPF_VC_SET_RSS_KEY,
IDPF_VC_SET_RSS_KEY_ERR);
break;
case VIRTCHNL2_OP_SET_SRIOV_VFS:
idpf_recv_vchnl_op(adapter, NULL, &ctlq_msg,
IDPF_VC_SET_SRIOV_VFS,
IDPF_VC_SET_SRIOV_VFS_ERR);
break;
case VIRTCHNL2_OP_ALLOC_VECTORS:
idpf_recv_vchnl_op(adapter, NULL, &ctlq_msg,
IDPF_VC_ALLOC_VECTORS,
......@@ -526,6 +546,24 @@ int idpf_recv_mb_msg(struct idpf_adapter *adapter, u32 op,
IDPF_VC_GET_PTYPE_INFO,
IDPF_VC_GET_PTYPE_INFO_ERR);
break;
case VIRTCHNL2_OP_LOOPBACK:
idpf_recv_vchnl_op(adapter, vport, &ctlq_msg,
IDPF_VC_LOOPBACK_STATE,
IDPF_VC_LOOPBACK_STATE_ERR);
break;
case VIRTCHNL2_OP_CONFIG_PROMISCUOUS_MODE:
/* This message can only be sent asynchronously. As
* such we'll have lost the context in which it was
* called and thus can only really report if it looks
* like an error occurred. Don't bother setting ERR bit
* or waking chnl_wq since no work queue will be waiting
* to read the message.
*/
if (ctlq_msg.cookie.mbx.chnl_retval) {
dev_err(&adapter->pdev->dev, "Failed to set promiscuous mode: %d\n",
ctlq_msg.cookie.mbx.chnl_retval);
}
break;
case VIRTCHNL2_OP_ADD_MAC_ADDR:
vport_config = adapter->vport_config[vport->idx];
if (test_and_clear_bit(IDPF_VPORT_ADD_MAC_REQ,
......@@ -2310,6 +2348,110 @@ int idpf_send_dealloc_vectors_msg(struct idpf_adapter *adapter)
return err;
}
/**
* idpf_get_max_vfs - Get max number of vfs supported
* @adapter: Driver specific private structure
*
* Returns max number of VFs
*/
static int idpf_get_max_vfs(struct idpf_adapter *adapter)
{
return le16_to_cpu(adapter->caps.max_sriov_vfs);
}
/**
* idpf_send_set_sriov_vfs_msg - Send virtchnl set sriov vfs message
* @adapter: Driver specific private structure
* @num_vfs: number of virtual functions to be created
*
* Returns 0 on success, negative on failure.
*/
int idpf_send_set_sriov_vfs_msg(struct idpf_adapter *adapter, u16 num_vfs)
{
struct virtchnl2_sriov_vfs_info svi = { };
int err;
svi.num_vfs = cpu_to_le16(num_vfs);
mutex_lock(&adapter->vc_buf_lock);
err = idpf_send_mb_msg(adapter, VIRTCHNL2_OP_SET_SRIOV_VFS,
sizeof(svi), (u8 *)&svi);
if (err)
goto rel_lock;
err = idpf_wait_for_event(adapter, NULL, IDPF_VC_SET_SRIOV_VFS,
IDPF_VC_SET_SRIOV_VFS_ERR);
rel_lock:
mutex_unlock(&adapter->vc_buf_lock);
return err;
}
/**
* idpf_send_get_stats_msg - Send virtchnl get statistics message
* @vport: vport to get stats for
*
* Returns 0 on success, negative on failure.
*/
int idpf_send_get_stats_msg(struct idpf_vport *vport)
{
struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
struct rtnl_link_stats64 *netstats = &np->netstats;
struct idpf_adapter *adapter = vport->adapter;
struct virtchnl2_vport_stats stats_msg = { };
struct virtchnl2_vport_stats *stats;
int err;
/* Don't send get_stats message if the link is down */
if (np->state <= __IDPF_VPORT_DOWN)
return 0;
stats_msg.vport_id = cpu_to_le32(vport->vport_id);
mutex_lock(&vport->vc_buf_lock);
err = idpf_send_mb_msg(adapter, VIRTCHNL2_OP_GET_STATS,
sizeof(struct virtchnl2_vport_stats),
(u8 *)&stats_msg);
if (err)
goto rel_lock;
err = idpf_wait_for_event(adapter, vport, IDPF_VC_GET_STATS,
IDPF_VC_GET_STATS_ERR);
if (err)
goto rel_lock;
stats = (struct virtchnl2_vport_stats *)vport->vc_msg;
spin_lock_bh(&np->stats_lock);
netstats->rx_packets = le64_to_cpu(stats->rx_unicast) +
le64_to_cpu(stats->rx_multicast) +
le64_to_cpu(stats->rx_broadcast);
netstats->rx_bytes = le64_to_cpu(stats->rx_bytes);
netstats->rx_dropped = le64_to_cpu(stats->rx_discards);
netstats->rx_over_errors = le64_to_cpu(stats->rx_overflow_drop);
netstats->rx_length_errors = le64_to_cpu(stats->rx_invalid_frame_length);
netstats->tx_packets = le64_to_cpu(stats->tx_unicast) +
le64_to_cpu(stats->tx_multicast) +
le64_to_cpu(stats->tx_broadcast);
netstats->tx_bytes = le64_to_cpu(stats->tx_bytes);
netstats->tx_errors = le64_to_cpu(stats->tx_errors);
netstats->tx_dropped = le64_to_cpu(stats->tx_discards);
vport->port_stats.vport_stats = *stats;
spin_unlock_bh(&np->stats_lock);
rel_lock:
mutex_unlock(&vport->vc_buf_lock);
return err;
}
/**
* idpf_send_get_set_rss_lut_msg - Send virtchnl get or set rss lut message
* @vport: virtual port data structure
......@@ -2716,6 +2858,38 @@ int idpf_send_get_rx_ptype_msg(struct idpf_vport *vport)
return err;
}
/**
* idpf_send_ena_dis_loopback_msg - Send virtchnl enable/disable loopback
* message
* @vport: virtual port data structure
*
* Returns 0 on success, negative on failure.
*/
int idpf_send_ena_dis_loopback_msg(struct idpf_vport *vport)
{
struct virtchnl2_loopback loopback;
int err;
loopback.vport_id = cpu_to_le32(vport->vport_id);
loopback.enable = idpf_is_feature_ena(vport, NETIF_F_LOOPBACK);
mutex_lock(&vport->vc_buf_lock);
err = idpf_send_mb_msg(vport->adapter, VIRTCHNL2_OP_LOOPBACK,
sizeof(loopback), (u8 *)&loopback);
if (err)
goto rel_lock;
err = idpf_wait_for_event(vport->adapter, vport,
IDPF_VC_LOOPBACK_STATE,
IDPF_VC_LOOPBACK_STATE_ERR);
rel_lock:
mutex_unlock(&vport->vc_buf_lock);
return err;
}
/**
* idpf_find_ctlq - Given a type and id, find ctlq info
* @hw: hardware struct
......@@ -2914,6 +3088,7 @@ int idpf_vc_core_init(struct idpf_adapter *adapter)
msleep(task_delay);
}
pci_sriov_set_totalvfs(adapter->pdev, idpf_get_max_vfs(adapter));
num_max_vports = idpf_get_max_vports(adapter);
adapter->max_vports = num_max_vports;
adapter->vports = kcalloc(num_max_vports, sizeof(*adapter->vports),
......@@ -3581,3 +3756,36 @@ int idpf_add_del_mac_filters(struct idpf_vport *vport,
return err;
}
/**
* idpf_set_promiscuous - set promiscuous and send message to mailbox
* @adapter: Driver specific private structure
* @config_data: Vport specific config data
* @vport_id: Vport identifier
*
* Request to enable promiscuous mode for the vport. Message is sent
* asynchronously and won't wait for response. Returns 0 on success, negative
* on failure;
*/
int idpf_set_promiscuous(struct idpf_adapter *adapter,
struct idpf_vport_user_config_data *config_data,
u32 vport_id)
{
struct virtchnl2_promisc_info vpi;
u16 flags = 0;
int err;
if (test_bit(__IDPF_PROMISC_UC, config_data->user_flags))
flags |= VIRTCHNL2_UNICAST_PROMISC;
if (test_bit(__IDPF_PROMISC_MC, config_data->user_flags))
flags |= VIRTCHNL2_MULTICAST_PROMISC;
vpi.vport_id = cpu_to_le32(vport_id);
vpi.flags = cpu_to_le16(flags);
err = idpf_send_mb_msg(adapter, VIRTCHNL2_OP_CONFIG_PROMISCUOUS_MODE,
sizeof(struct virtchnl2_promisc_info),
(u8 *)&vpi);
return err;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment