net/dpaa2: support link status event

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
This commit is contained in:
Hemant Agrawal 2017-09-16 16:22:28 +05:30 committed by Ferruh Yigit
parent 01d0df35e7
commit c5acbb5ea2
5 changed files with 456 additions and 0 deletions

View File

@ -6,6 +6,7 @@
[Features]
Speed capabilities = P
Link status = Y
Link status event = Y
Queue start/stop = Y
Jumbo frame = Y
MTU update = Y

View File

@ -54,6 +54,8 @@
static struct rte_dpaa2_driver rte_dpaa2_pmd;
static int dpaa2_dev_uninit(struct rte_eth_dev *eth_dev);
static int dpaa2_dev_link_update(struct rte_eth_dev *dev,
int wait_to_complete);
static int dpaa2_dev_set_link_up(struct rte_eth_dev *dev);
static int dpaa2_dev_set_link_down(struct rte_eth_dev *dev);
static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
@ -344,6 +346,10 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev)
return ret;
}
}
/* update the current status */
dpaa2_dev_link_update(dev, 0);
return 0;
}
@ -556,9 +562,87 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev)
return NULL;
}
/**
* Dpaa2 link Interrupt handler
*
* @param param
* The address of parameter (struct rte_eth_dev *) regsitered before.
*
* @return
* void
*/
static void
dpaa2_interrupt_handler(void *param)
{
struct rte_eth_dev *dev = param;
struct dpaa2_dev_priv *priv = dev->data->dev_private;
struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
int ret;
int irq_index = DPNI_IRQ_INDEX;
unsigned int status = 0, clear = 0;
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
RTE_LOG(ERR, PMD, "dpni is NULL");
return;
}
ret = dpni_get_irq_status(dpni, CMD_PRI_LOW, priv->token,
irq_index, &status);
if (unlikely(ret)) {
RTE_LOG(ERR, PMD, "Can't get irq status (err %d)", ret);
clear = 0xffffffff;
goto out;
}
if (status & DPNI_IRQ_EVENT_LINK_CHANGED) {
clear = DPNI_IRQ_EVENT_LINK_CHANGED;
dpaa2_dev_link_update(dev, 0);
/* calling all the apps registered for link status event */
_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
NULL, NULL);
}
out:
ret = dpni_clear_irq_status(dpni, CMD_PRI_LOW, priv->token,
irq_index, clear);
if (unlikely(ret))
RTE_LOG(ERR, PMD, "Can't clear irq status (err %d)", ret);
}
static int
dpaa2_eth_setup_irqs(struct rte_eth_dev *dev, int enable)
{
int err = 0;
struct dpaa2_dev_priv *priv = dev->data->dev_private;
struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
int irq_index = DPNI_IRQ_INDEX;
unsigned int mask = DPNI_IRQ_EVENT_LINK_CHANGED;
PMD_INIT_FUNC_TRACE();
err = dpni_set_irq_mask(dpni, CMD_PRI_LOW, priv->token,
irq_index, mask);
if (err < 0) {
PMD_INIT_LOG(ERR, "Error: dpni_set_irq_mask():%d (%s)", err,
strerror(-err));
return err;
}
err = dpni_set_irq_enable(dpni, CMD_PRI_LOW, priv->token,
irq_index, enable);
if (err < 0)
PMD_INIT_LOG(ERR, "Error: dpni_set_irq_enable():%d (%s)", err,
strerror(-err));
return err;
}
static int
dpaa2_dev_start(struct rte_eth_dev *dev)
{
struct rte_device *rdev = dev->device;
struct rte_dpaa2_device *dpaa2_dev;
struct rte_eth_dev_data *data = dev->data;
struct dpaa2_dev_priv *priv = data->dev_private;
struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
@ -568,6 +652,10 @@ dpaa2_dev_start(struct rte_eth_dev *dev)
struct dpni_queue_id qid;
struct dpaa2_queue *dpaa2_q;
int ret, i;
struct rte_intr_handle *intr_handle;
dpaa2_dev = container_of(rdev, struct rte_dpaa2_device, device);
intr_handle = &dpaa2_dev->intr_handle;
PMD_INIT_FUNC_TRACE();
@ -647,6 +735,24 @@ dpaa2_dev_start(struct rte_eth_dev *dev)
if (priv->max_vlan_filters)
dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
/* if the interrupts were configured on this devices*/
if (intr_handle && (intr_handle->fd) &&
(dev->data->dev_conf.intr_conf.lsc != 0)) {
/* Registering LSC interrupt handler */
rte_intr_callback_register(intr_handle,
dpaa2_interrupt_handler,
(void *)dev);
/* enable vfio intr/eventfd mapping
* Interrupt index 0 is required, so we can not use
* rte_intr_enable.
*/
rte_dpaa2_intr_enable(intr_handle, DPNI_IRQ_INDEX);
/* enable dpni_irqs */
dpaa2_eth_setup_irqs(dev, 1);
}
return 0;
}
@ -661,9 +767,25 @@ dpaa2_dev_stop(struct rte_eth_dev *dev)
struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
int ret;
struct rte_eth_link link;
struct rte_intr_handle *intr_handle = dev->intr_handle;
PMD_INIT_FUNC_TRACE();
/* reset interrupt callback */
if (intr_handle && (intr_handle->fd) &&
(dev->data->dev_conf.intr_conf.lsc != 0)) {
/*disable dpni irqs */
dpaa2_eth_setup_irqs(dev, 0);
/* disable vfio intr before callback unregister */
rte_dpaa2_intr_disable(intr_handle, DPNI_IRQ_INDEX);
/* Unregistering LSC interrupt handler */
rte_intr_callback_unregister(intr_handle,
dpaa2_interrupt_handler,
(void *)dev);
}
dpaa2_dev_set_link_down(dev);
ret = dpni_disable(dpni, CMD_PRI_LOW, priv->token);
@ -1458,6 +1580,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
}
eth_dev->dev_ops = &dpaa2_ethdev_ops;
eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx;
eth_dev->tx_pkt_burst = dpaa2_dev_tx;

View File

@ -350,6 +350,239 @@ int dpni_reset(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
/**
* dpni_set_irq_enable() - Set overall interrupt state.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPNI object
* @irq_index: The interrupt index to configure
* @en: Interrupt state: - enable = 1, disable = 0
*
* Allows GPP software to control when interrupts are generated.
* Each interrupt can have up to 32 causes. The enable/disable control's the
* overall interrupt state. if the interrupt is disabled no causes will cause
* an interrupt.
*
* Return: '0' on Success; Error code otherwise.
*/
int dpni_set_irq_enable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint8_t en)
{
struct mc_command cmd = { 0 };
struct dpni_cmd_set_irq_enable *cmd_params;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_ENABLE,
cmd_flags,
token);
cmd_params = (struct dpni_cmd_set_irq_enable *)cmd.params;
dpni_set_field(cmd_params->enable, ENABLE, en);
cmd_params->irq_index = irq_index;
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
/**
* dpni_get_irq_enable() - Get overall interrupt state
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPNI object
* @irq_index: The interrupt index to configure
* @en: Returned interrupt state - enable = 1, disable = 0
*
* Return: '0' on Success; Error code otherwise.
*/
int dpni_get_irq_enable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint8_t *en)
{
struct mc_command cmd = { 0 };
struct dpni_cmd_get_irq_enable *cmd_params;
struct dpni_rsp_get_irq_enable *rsp_params;
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_ENABLE,
cmd_flags,
token);
cmd_params = (struct dpni_cmd_get_irq_enable *)cmd.params;
cmd_params->irq_index = irq_index;
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
rsp_params = (struct dpni_rsp_get_irq_enable *)cmd.params;
*en = dpni_get_field(rsp_params->enabled, ENABLE);
return 0;
}
/**
* dpni_set_irq_mask() - Set interrupt mask.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPNI object
* @irq_index: The interrupt index to configure
* @mask: Event mask to trigger interrupt;
* each bit:
* 0 = ignore event
* 1 = consider event for asserting IRQ
*
* Every interrupt can have up to 32 causes and the interrupt model supports
* masking/unmasking each cause independently
*
* Return: '0' on Success; Error code otherwise.
*/
int dpni_set_irq_mask(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint32_t mask)
{
struct mc_command cmd = { 0 };
struct dpni_cmd_set_irq_mask *cmd_params;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_MASK,
cmd_flags,
token);
cmd_params = (struct dpni_cmd_set_irq_mask *)cmd.params;
cmd_params->mask = cpu_to_le32(mask);
cmd_params->irq_index = irq_index;
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
/**
* dpni_get_irq_mask() - Get interrupt mask.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPNI object
* @irq_index: The interrupt index to configure
* @mask: Returned event mask to trigger interrupt
*
* Every interrupt can have up to 32 causes and the interrupt model supports
* masking/unmasking each cause independently
*
* Return: '0' on Success; Error code otherwise.
*/
int dpni_get_irq_mask(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint32_t *mask)
{
struct mc_command cmd = { 0 };
struct dpni_cmd_get_irq_mask *cmd_params;
struct dpni_rsp_get_irq_mask *rsp_params;
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_MASK,
cmd_flags,
token);
cmd_params = (struct dpni_cmd_get_irq_mask *)cmd.params;
cmd_params->irq_index = irq_index;
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
rsp_params = (struct dpni_rsp_get_irq_mask *)cmd.params;
*mask = le32_to_cpu(rsp_params->mask);
return 0;
}
/**
* dpni_get_irq_status() - Get the current status of any pending interrupts.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPNI object
* @irq_index: The interrupt index to configure
* @status: Returned interrupts status - one bit per cause:
* 0 = no interrupt pending
* 1 = interrupt pending
*
* Return: '0' on Success; Error code otherwise.
*/
int dpni_get_irq_status(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint32_t *status)
{
struct mc_command cmd = { 0 };
struct dpni_cmd_get_irq_status *cmd_params;
struct dpni_rsp_get_irq_status *rsp_params;
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_STATUS,
cmd_flags,
token);
cmd_params = (struct dpni_cmd_get_irq_status *)cmd.params;
cmd_params->status = cpu_to_le32(*status);
cmd_params->irq_index = irq_index;
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
rsp_params = (struct dpni_rsp_get_irq_status *)cmd.params;
*status = le32_to_cpu(rsp_params->status);
return 0;
}
/**
* dpni_clear_irq_status() - Clear a pending interrupt's status
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPNI object
* @irq_index: The interrupt index to configure
* @status: bits to clear (W1C) - one bit per cause:
* 0 = don't change
* 1 = clear status bit
*
* Return: '0' on Success; Error code otherwise.
*/
int dpni_clear_irq_status(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint32_t status)
{
struct mc_command cmd = { 0 };
struct dpni_cmd_clear_irq_status *cmd_params;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLEAR_IRQ_STATUS,
cmd_flags,
token);
cmd_params = (struct dpni_cmd_clear_irq_status *)cmd.params;
cmd_params->irq_index = irq_index;
cmd_params->status = cpu_to_le32(status);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
/**
* dpni_get_attributes() - Retrieve DPNI attributes.
* @mc_io: Pointer to MC portal's I/O object

View File

@ -246,6 +246,55 @@ int dpni_reset(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token);
/**
* DPNI IRQ Index and Events
*/
/**
* IRQ index
*/
#define DPNI_IRQ_INDEX 0
/**
* IRQ event - indicates a change in link state
*/
#define DPNI_IRQ_EVENT_LINK_CHANGED 0x00000001
int dpni_set_irq_enable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint8_t en);
int dpni_get_irq_enable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint8_t *en);
int dpni_set_irq_mask(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint32_t mask);
int dpni_get_irq_mask(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint32_t *mask);
int dpni_get_irq_status(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint32_t *status);
int dpni_clear_irq_status(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t irq_index,
uint32_t status);
/**
* struct dpni_attr - Structure representing DPNI attributes
* @options: Any combination of the following options:

View File

@ -64,6 +64,13 @@
#define DPNI_CMDID_RESET DPNI_CMD(0x005)
#define DPNI_CMDID_IS_ENABLED DPNI_CMD(0x006)
#define DPNI_CMDID_SET_IRQ_ENABLE DPNI_CMD(0x012)
#define DPNI_CMDID_GET_IRQ_ENABLE DPNI_CMD(0x013)
#define DPNI_CMDID_SET_IRQ_MASK DPNI_CMD(0x014)
#define DPNI_CMDID_GET_IRQ_MASK DPNI_CMD(0x015)
#define DPNI_CMDID_GET_IRQ_STATUS DPNI_CMD(0x016)
#define DPNI_CMDID_CLEAR_IRQ_STATUS DPNI_CMD(0x017)
#define DPNI_CMDID_SET_POOLS DPNI_CMD_V2(0x200)
#define DPNI_CMDID_SET_ERRORS_BEHAVIOR DPNI_CMD(0x20B)
@ -169,6 +176,49 @@ struct dpni_rsp_is_enabled {
uint8_t enabled;
};
struct dpni_cmd_set_irq_enable {
uint8_t enable;
uint8_t pad[3];
uint8_t irq_index;
};
struct dpni_cmd_get_irq_enable {
uint32_t pad;
uint8_t irq_index;
};
struct dpni_rsp_get_irq_enable {
uint8_t enabled;
};
struct dpni_cmd_set_irq_mask {
uint32_t mask;
uint8_t irq_index;
};
struct dpni_cmd_get_irq_mask {
uint32_t pad;
uint8_t irq_index;
};
struct dpni_rsp_get_irq_mask {
uint32_t mask;
};
struct dpni_cmd_get_irq_status {
uint32_t status;
uint8_t irq_index;
};
struct dpni_rsp_get_irq_status {
uint32_t status;
};
struct dpni_cmd_clear_irq_status {
uint32_t status;
uint8_t irq_index;
};
struct dpni_rsp_get_attr {
/* response word 0 */
uint32_t options;