ethdev: add NIC reset operation

This patch adds a new eth_dev layer API function rte_eth_dev_reset(),
which a DPDK application can call to reset a NIC and keep its port id
afterwards. It means that all software resources allocated in the ethdev
layer are kept, and software & hardware resources of the NIC within the
NIC's PMD are reset to a state simular to that obtained by calling the
PCI dev_uninit() and then dev_init(). This effective sequence of
dev_uninit() and dev_init() is packed into a single API function
rte_eth_dev_reset().

Please see the comments before the declaration of rte_eht_dev_reset()
in lib/librte_ether/rte_ethdev.h to get more details on why this
function is needed, what it does, when it should be called
and what an application should do after calling this function.
See also detailed explanations in the programmer's guide.

Signed-off-by: Wei Dai <wei.dai@intel.com>
Reviewed-by: Remy Horton <remy.horton@intel.com>
This commit is contained in:
Wei Dai 2017-07-23 17:15:09 +08:00 committed by Thomas Monjalon
parent 06791a4bce
commit 514302ff6e
4 changed files with 98 additions and 0 deletions

@ -536,3 +536,43 @@ call. As an end result, the application is able to achieve its goal of
monitoring a single statistic ("rx_errors" in this case), and if that shows
packets being dropped, it can easily retrieve a "set" of statistics using the
IDs array parameter to ``rte_eth_xstats_get_by_id`` function.
NIC Reset API
~~~~~~~~~~~~~
.. code-block:: c
int rte_eth_dev_reset(uint8_t port_id);
Sometimes a port has to be reset passively. For example when a PF is
reset, all its VFs should also be reset by the application to make them
consistent with the PF. A DPDK application also can call this function
to trigger a port reset. Normally, a DPDK application would invokes this
function when an RTE_ETH_EVENT_INTR_RESET event is detected.
It is the duty of the PMD to trigger RTE_ETH_EVENT_INTR_RESET events and
the application should register a callback function to handle these
events. When a PMD needs to trigger a reset, it can trigger an
RTE_ETH_EVENT_INTR_RESET event. On receiving an RTE_ETH_EVENT_INTR_RESET
event, applications can handle it as follows: Stop working queues, stop
calling Rx and Tx functions, and then call rte_eth_dev_reset(). For
thread safety all these operations should be called from the same thread.
For example when PF is reset, the PF sends a message to notify VFs of
this event and also trigger an interrupt to VFs. Then in the interrupt
service routine the VFs detects this notification message and calls
_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, NULL,
NULL). This means that a PF reset triggers an RTE_ETH_EVENT_INTR_RESET
event within VFs. The function _rte_eth_dev_callback_process() will
call the registered callback function. The callback function can trigger
the application to handle all operations the VF reset requires including
stopping Rx/Tx queues and calling rte_eth_dev_reset().
The rte_eth_dev_reset() itself is a generic function which only does
some hardware reset operations through calling dev_unint() and
dev_init(), and itself does not handle synchronization, which is handled
by application.
The PMD itself should not call rte_eth_dev_reset(). The PMD can trigger
the application to handle reset event. It is duty of application to
handle all synchronization before it calls rte_eth_dev_reset().

@ -994,6 +994,23 @@ rte_eth_dev_close(uint8_t port_id)
dev->data->tx_queues = NULL;
}
int
rte_eth_dev_reset(uint8_t port_id)
{
struct rte_eth_dev *dev;
int ret;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
dev = &rte_eth_devices[port_id];
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_reset, -ENOTSUP);
rte_eth_dev_stop(port_id);
ret = dev->dev_ops->dev_reset(dev);
return ret;
}
int
rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id,
uint16_t nb_rx_desc, unsigned int socket_id,

@ -1115,6 +1115,9 @@ typedef int (*eth_dev_set_link_down_t)(struct rte_eth_dev *dev);
typedef void (*eth_dev_close_t)(struct rte_eth_dev *dev);
/**< @internal Function used to close a configured Ethernet device. */
typedef int (*eth_dev_reset_t)(struct rte_eth_dev *dev);
/** <@internal Function used to reset a configured Ethernet device. */
typedef void (*eth_promiscuous_enable_t)(struct rte_eth_dev *dev);
/**< @internal Function used to enable the RX promiscuous mode of an Ethernet device. */
@ -1435,6 +1438,7 @@ struct eth_dev_ops {
eth_dev_set_link_up_t dev_set_link_up; /**< Device link up. */
eth_dev_set_link_down_t dev_set_link_down; /**< Device link down. */
eth_dev_close_t dev_close; /**< Close device. */
eth_dev_reset_t dev_reset; /**< Reset device. */
eth_link_update_t link_update; /**< Get device link state. */
eth_promiscuous_enable_t promiscuous_enable; /**< Promiscuous ON. */
@ -2140,6 +2144,36 @@ int rte_eth_dev_set_link_down(uint8_t port_id);
*/
void rte_eth_dev_close(uint8_t port_id);
/**
* Reset a Ethernet device and keep its port id.
*
* When a port has to be reset passively, the DPDK application can invoke
* this function. For example when a PF is reset, all its VFs should also
* be reset. Normally a DPDK application can invoke this function when
* RTE_ETH_EVENT_INTR_RESET event is detected, but can also use it to start
* a port reset in other circumstances.
*
* When this function is called, it first stops the port and then calls the
* PMD specific dev_uninit( ) and dev_init( ) to return the port to initial
* state, in which no Tx and Rx queues are setup, as if the port has been
* reset and not started. The port keeps the port id it had before the
* function call.
*
* After calling rte_eth_dev_reset( ), the application should use
* rte_eth_dev_configure( ), rte_eth_rx_queue_setup( ),
* rte_eth_tx_queue_setup( ), and rte_eth_dev_start( )
* to reconfigure the device as appropriate.
*
* Note: To avoid unexpected behavior, the application should stop calling
* Tx and Rx functions before calling rte_eth_dev_reset( ). For thread
* safety, all these controlling functions should be called from the same
* thread.
*
* @param port_id
* The port identifier of the Ethernet device.
*/
int rte_eth_dev_reset(uint8_t port_id);
/**
* Enable receipt in promiscuous mode for an Ethernet device.
*

@ -187,3 +187,10 @@ DPDK_17.08 {
rte_tm_wred_profile_delete;
} DPDK_17.05;
DPDK_17.11 {
global:
rte_eth_dev_reset;
} DPDK_17.08;