From a2186b91b9f426bff966cccee24186a21e2c9bd5 Mon Sep 17 00:00:00 2001 From: Shijith Thotton Date: Sat, 25 Mar 2017 11:54:55 +0530 Subject: [PATCH] net/liquidio: add API to close device Signed-off-by: Shijith Thotton Signed-off-by: Jerin Jacob Signed-off-by: Derek Chickles Signed-off-by: Venkat Koppula Signed-off-by: Srisivasubramanian S Signed-off-by: Mallesham Jatharakonda --- drivers/net/liquidio/lio_ethdev.c | 68 ++++++++++++++++++++++++++++++- drivers/net/liquidio/lio_ethdev.h | 5 +++ drivers/net/liquidio/lio_rxtx.c | 57 ++++++++++++++++++++++++++ drivers/net/liquidio/lio_rxtx.h | 2 + 4 files changed, 130 insertions(+), 2 deletions(-) diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c index 76d775d19b..60dfa6194e 100644 --- a/drivers/net/liquidio/lio_ethdev.c +++ b/drivers/net/liquidio/lio_ethdev.c @@ -1109,7 +1109,7 @@ lio_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t q_no, * @return * - nothing */ -static void +void lio_dev_rx_queue_release(void *rxq) { struct lio_droq *droq = rxq; @@ -1204,7 +1204,7 @@ lio_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t q_no, * @return * - nothing */ -static void +void lio_dev_tx_queue_release(void *txq) { struct lio_instr_queue *tq = txq; @@ -1432,6 +1432,68 @@ lio_dev_set_link_down(struct rte_eth_dev *eth_dev) return 0; } +/** + * Reset and stop the device. This occurs on the first + * call to this routine. Subsequent calls will simply + * return. NB: This will require the NIC to be rebooted. + * + * @param eth_dev + * Pointer to the structure rte_eth_dev + * + * @return + * - nothing + */ +static void +lio_dev_close(struct rte_eth_dev *eth_dev) +{ + struct lio_device *lio_dev = LIO_DEV(eth_dev); + uint32_t i; + + lio_dev_info(lio_dev, "closing port %d\n", eth_dev->data->port_id); + + if (lio_dev->intf_open) + lio_dev_stop(eth_dev); + + lio_wait_for_instr_fetch(lio_dev); + + lio_dev->fn_list.disable_io_queues(lio_dev); + + cn23xx_vf_set_io_queues_off(lio_dev); + + /* Reset iq regs (IQ_DBELL). + * Clear sli_pktx_cnts (OQ_PKTS_SENT). + */ + for (i = 0; i < lio_dev->nb_rx_queues; i++) { + struct lio_droq *droq = lio_dev->droq[i]; + + if (droq == NULL) + break; + + uint32_t pkt_count = rte_read32(droq->pkts_sent_reg); + + lio_dev_dbg(lio_dev, + "pending oq count %u\n", pkt_count); + rte_write32(pkt_count, droq->pkts_sent_reg); + } + + /* Do FLR for the VF */ + cn23xx_vf_ask_pf_to_do_flr(lio_dev); + + /* lio_free_mbox */ + lio_dev->fn_list.free_mbox(lio_dev); + + /* Free glist resources */ + rte_free(lio_dev->glist_head); + rte_free(lio_dev->glist_lock); + lio_dev->glist_head = NULL; + lio_dev->glist_lock = NULL; + + lio_dev->port_configured = 0; + + /* Delete all queues */ + lio_dev_clear_queues(eth_dev); +} + /** * Enable tunnel rx checksum verification from firmware. */ @@ -1678,6 +1740,7 @@ static const struct eth_dev_ops liovf_eth_dev_ops = { .dev_stop = lio_dev_stop, .dev_set_link_up = lio_dev_set_link_up, .dev_set_link_down = lio_dev_set_link_down, + .dev_close = lio_dev_close, .allmulticast_enable = lio_dev_allmulticast_enable, .allmulticast_disable = lio_dev_allmulticast_disable, .link_update = lio_dev_link_update, @@ -1839,6 +1902,7 @@ lio_eth_dev_uninit(struct rte_eth_dev *eth_dev) rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; + eth_dev->dev_ops = NULL; eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; diff --git a/drivers/net/liquidio/lio_ethdev.h b/drivers/net/liquidio/lio_ethdev.h index 150e9c940a..ee30615682 100644 --- a/drivers/net/liquidio/lio_ethdev.h +++ b/drivers/net/liquidio/lio_ethdev.h @@ -196,4 +196,9 @@ struct lio_rss_set { uint8_t itable[LIO_RSS_MAX_TABLE_SZ]; uint8_t key[LIO_RSS_MAX_KEY_SZ]; }; + +void lio_dev_rx_queue_release(void *rxq); + +void lio_dev_tx_queue_release(void *txq); + #endif /* _LIO_ETHDEV_H_ */ diff --git a/drivers/net/liquidio/lio_rxtx.c b/drivers/net/liquidio/lio_rxtx.c index 470131c490..9533015c38 100644 --- a/drivers/net/liquidio/lio_rxtx.c +++ b/drivers/net/liquidio/lio_rxtx.c @@ -918,6 +918,40 @@ release_lio_iq: return -1; } +int +lio_wait_for_instr_fetch(struct lio_device *lio_dev) +{ + int pending, instr_cnt; + int i, retry = 1000; + + do { + instr_cnt = 0; + + for (i = 0; i < LIO_MAX_INSTR_QUEUES(lio_dev); i++) { + if (!(lio_dev->io_qmask.iq & (1ULL << i))) + continue; + + if (lio_dev->instr_queue[i] == NULL) + break; + + pending = rte_atomic64_read( + &lio_dev->instr_queue[i]->instr_pending); + if (pending) + lio_flush_iq(lio_dev, lio_dev->instr_queue[i]); + + instr_cnt += pending; + } + + if (instr_cnt == 0) + break; + + rte_delay_ms(1); + + } while (retry-- && instr_cnt); + + return instr_cnt; +} + static inline void lio_ring_doorbell(struct lio_device *lio_dev, struct lio_instr_queue *iq) @@ -1826,3 +1860,26 @@ xmit_failed: return processed; } +void +lio_dev_clear_queues(struct rte_eth_dev *eth_dev) +{ + struct lio_instr_queue *txq; + struct lio_droq *rxq; + uint16_t i; + + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { + txq = eth_dev->data->tx_queues[i]; + if (txq != NULL) { + lio_dev_tx_queue_release(txq); + eth_dev->data->tx_queues[i] = NULL; + } + } + + for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { + rxq = eth_dev->data->rx_queues[i]; + if (rxq != NULL) { + lio_dev_rx_queue_release(rxq); + eth_dev->data->rx_queues[i] = NULL; + } + } +} diff --git a/drivers/net/liquidio/lio_rxtx.h b/drivers/net/liquidio/lio_rxtx.h index d5aed6a7b5..85685dc7d7 100644 --- a/drivers/net/liquidio/lio_rxtx.h +++ b/drivers/net/liquidio/lio_rxtx.h @@ -752,6 +752,7 @@ int lio_setup_sglists(struct lio_device *lio_dev, int iq_no, int fw_mapped_iq, int num_descs, unsigned int socket_id); uint16_t lio_dev_xmit_pkts(void *tx_queue, struct rte_mbuf **pkts, uint16_t nb_pkts); +int lio_wait_for_instr_fetch(struct lio_device *lio_dev); int lio_setup_iq(struct lio_device *lio_dev, int q_index, union octeon_txpciq iq_no, uint32_t num_descs, void *app_ctx, unsigned int socket_id); @@ -764,4 +765,5 @@ void lio_delete_instruction_queue(struct lio_device *lio_dev, int iq_no); */ int lio_setup_instr_queue0(struct lio_device *lio_dev); void lio_free_instr_queue0(struct lio_device *lio_dev); +void lio_dev_clear_queues(struct rte_eth_dev *eth_dev); #endif /* _LIO_RXTX_H_ */ -- 2.20.1