cxgbe: add device related operations
Adds dev_start(), dev_stop(), and dev_close() eth_dev_ops for cxgbe poll mode driver. Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com> Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
This commit is contained in:
parent
4a01078b4f
commit
0462d11544
@ -44,6 +44,10 @@
|
||||
#define CXGBE_DEFAULT_RX_DESC_SIZE 1024 /* Default RX ring size */
|
||||
|
||||
int cxgbe_probe(struct adapter *adapter);
|
||||
int cxgbe_up(struct adapter *adap);
|
||||
int cxgbe_down(struct port_info *pi);
|
||||
void cxgbe_close(struct adapter *adapter);
|
||||
int link_start(struct port_info *pi);
|
||||
void init_rspq(struct adapter *adap, struct sge_rspq *q, unsigned int us,
|
||||
unsigned int cnt, unsigned int size, unsigned int iqe_size);
|
||||
int setup_sge_fwevtq(struct adapter *adapter);
|
||||
|
@ -171,6 +171,117 @@ static int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev,
|
||||
static void cxgbe_dev_tx_queue_release(void *q);
|
||||
static void cxgbe_dev_rx_queue_release(void *q);
|
||||
|
||||
/*
|
||||
* Stop device.
|
||||
*/
|
||||
static void cxgbe_dev_close(struct rte_eth_dev *eth_dev)
|
||||
{
|
||||
struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private);
|
||||
struct adapter *adapter = pi->adapter;
|
||||
int i, dev_down = 0;
|
||||
|
||||
CXGBE_FUNC_TRACE();
|
||||
|
||||
if (!(adapter->flags & FULL_INIT_DONE))
|
||||
return;
|
||||
|
||||
cxgbe_down(pi);
|
||||
|
||||
/*
|
||||
* We clear queues only if both tx and rx path of the port
|
||||
* have been disabled
|
||||
*/
|
||||
t4_sge_eth_clear_queues(pi);
|
||||
|
||||
/* See if all ports are down */
|
||||
for_each_port(adapter, i) {
|
||||
pi = adap2pinfo(adapter, i);
|
||||
/*
|
||||
* Skip first port of the adapter since it will be closed
|
||||
* by DPDK
|
||||
*/
|
||||
if (i == 0)
|
||||
continue;
|
||||
dev_down += (pi->eth_dev->data->dev_started == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* If rest of the ports are stopped, then free up resources */
|
||||
if (dev_down == (adapter->params.nports - 1))
|
||||
cxgbe_close(adapter);
|
||||
}
|
||||
|
||||
/* Start the device.
|
||||
* It returns 0 on success.
|
||||
*/
|
||||
static int cxgbe_dev_start(struct rte_eth_dev *eth_dev)
|
||||
{
|
||||
struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private);
|
||||
struct adapter *adapter = pi->adapter;
|
||||
int err = 0, i;
|
||||
|
||||
CXGBE_FUNC_TRACE();
|
||||
|
||||
/*
|
||||
* If we don't have a connection to the firmware there's nothing we
|
||||
* can do.
|
||||
*/
|
||||
if (!(adapter->flags & FW_OK)) {
|
||||
err = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(adapter->flags & FULL_INIT_DONE)) {
|
||||
err = cxgbe_up(adapter);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = setup_rss(pi);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < pi->n_tx_qsets; i++) {
|
||||
err = cxgbe_dev_tx_queue_start(eth_dev, i);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < pi->n_rx_qsets; i++) {
|
||||
err = cxgbe_dev_rx_queue_start(eth_dev, i);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = link_start(pi);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop device: disable rx and tx functions to allow for reconfiguring.
|
||||
*/
|
||||
static void cxgbe_dev_stop(struct rte_eth_dev *eth_dev)
|
||||
{
|
||||
struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private);
|
||||
struct adapter *adapter = pi->adapter;
|
||||
|
||||
CXGBE_FUNC_TRACE();
|
||||
|
||||
if (!(adapter->flags & FULL_INIT_DONE))
|
||||
return;
|
||||
|
||||
cxgbe_down(pi);
|
||||
|
||||
/*
|
||||
* We clear queues only if both tx and rx path of the port
|
||||
* have been disabled
|
||||
*/
|
||||
t4_sge_eth_clear_queues(pi);
|
||||
}
|
||||
|
||||
static int cxgbe_dev_configure(struct rte_eth_dev *eth_dev)
|
||||
{
|
||||
struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private);
|
||||
@ -390,6 +501,9 @@ static void cxgbe_dev_rx_queue_release(void *q)
|
||||
}
|
||||
|
||||
static struct eth_dev_ops cxgbe_eth_dev_ops = {
|
||||
.dev_start = cxgbe_dev_start,
|
||||
.dev_stop = cxgbe_dev_stop,
|
||||
.dev_close = cxgbe_dev_close,
|
||||
.dev_configure = cxgbe_dev_configure,
|
||||
.dev_infos_get = cxgbe_dev_info_get,
|
||||
.tx_queue_setup = cxgbe_dev_tx_queue_setup,
|
||||
|
@ -826,6 +826,50 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id)
|
||||
pi->port_id, pi->mod_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* link_start - enable a port
|
||||
* @dev: the port to enable
|
||||
*
|
||||
* Performs the MAC and PHY actions needed to enable a port.
|
||||
*/
|
||||
int link_start(struct port_info *pi)
|
||||
{
|
||||
struct adapter *adapter = pi->adapter;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* We do not set address filters and promiscuity here, the stack does
|
||||
* that step explicitly.
|
||||
*/
|
||||
ret = t4_set_rxmode(adapter, adapter->mbox, pi->viid, 1500, -1, -1,
|
||||
-1, 1, true);
|
||||
if (ret == 0) {
|
||||
ret = t4_change_mac(adapter, adapter->mbox, pi->viid,
|
||||
pi->xact_addr_filt,
|
||||
(u8 *)&pi->eth_dev->data->mac_addrs[0],
|
||||
true, true);
|
||||
if (ret >= 0) {
|
||||
pi->xact_addr_filt = ret;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if (ret == 0)
|
||||
ret = t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan,
|
||||
&pi->link_cfg);
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* Enabling a Virtual Interface can result in an interrupt
|
||||
* during the processing of the VI Enable command and, in some
|
||||
* paths, result in an attempt to issue another command in the
|
||||
* interrupt context. Thus, we disable interrupts during the
|
||||
* course of the VI Enable command ...
|
||||
*/
|
||||
ret = t4_enable_vi_params(adapter, adapter->mbox, pi->viid,
|
||||
true, true, false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cxgb4_write_rss - write the RSS table for a given port
|
||||
* @pi: the port
|
||||
@ -907,6 +951,101 @@ int setup_rss(struct port_info *pi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable NAPI scheduling and interrupt generation for all Rx queues.
|
||||
*/
|
||||
static void enable_rx(struct adapter *adap)
|
||||
{
|
||||
struct sge *s = &adap->sge;
|
||||
struct sge_rspq *q = &s->fw_evtq;
|
||||
int i, j;
|
||||
|
||||
/* 0-increment GTS to start the timer and enable interrupts */
|
||||
t4_write_reg(adap, MYPF_REG(A_SGE_PF_GTS),
|
||||
V_SEINTARM(q->intr_params) |
|
||||
V_INGRESSQID(q->cntxt_id));
|
||||
|
||||
for_each_port(adap, i) {
|
||||
const struct port_info *pi = &adap->port[i];
|
||||
struct rte_eth_dev *eth_dev = pi->eth_dev;
|
||||
|
||||
for (j = 0; j < eth_dev->data->nb_rx_queues; j++) {
|
||||
q = eth_dev->data->rx_queues[j];
|
||||
|
||||
/*
|
||||
* 0-increment GTS to start the timer and enable
|
||||
* interrupts
|
||||
*/
|
||||
t4_write_reg(adap, MYPF_REG(A_SGE_PF_GTS),
|
||||
V_SEINTARM(q->intr_params) |
|
||||
V_INGRESSQID(q->cntxt_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cxgb_up - enable the adapter
|
||||
* @adap: adapter being enabled
|
||||
*
|
||||
* Called when the first port is enabled, this function performs the
|
||||
* actions necessary to make an adapter operational, such as completing
|
||||
* the initialization of HW modules, and enabling interrupts.
|
||||
*/
|
||||
int cxgbe_up(struct adapter *adap)
|
||||
{
|
||||
enable_rx(adap);
|
||||
t4_sge_tx_monitor_start(adap);
|
||||
t4_intr_enable(adap);
|
||||
adap->flags |= FULL_INIT_DONE;
|
||||
|
||||
/* TODO: deadman watchdog ?? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the port
|
||||
*/
|
||||
int cxgbe_down(struct port_info *pi)
|
||||
{
|
||||
struct adapter *adapter = pi->adapter;
|
||||
int err = 0;
|
||||
|
||||
err = t4_enable_vi(adapter, adapter->mbox, pi->viid, false, false);
|
||||
if (err) {
|
||||
dev_err(adapter, "%s: disable_vi failed: %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
t4_reset_link_config(adapter, pi->port_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release resources when all the ports have been stopped.
|
||||
*/
|
||||
void cxgbe_close(struct adapter *adapter)
|
||||
{
|
||||
struct port_info *pi;
|
||||
int i;
|
||||
|
||||
if (adapter->flags & FULL_INIT_DONE) {
|
||||
t4_intr_disable(adapter);
|
||||
t4_sge_tx_monitor_stop(adapter);
|
||||
t4_free_sge_resources(adapter);
|
||||
for_each_port(adapter, i) {
|
||||
pi = adap2pinfo(adapter, i);
|
||||
if (pi->viid != 0)
|
||||
t4_free_vi(adapter, adapter->mbox,
|
||||
adapter->pf, 0, pi->viid);
|
||||
rte_free(pi->eth_dev->data->mac_addrs);
|
||||
}
|
||||
adapter->flags &= ~FULL_INIT_DONE;
|
||||
}
|
||||
|
||||
if (adapter->flags & FW_OK)
|
||||
t4_fw_bye(adapter, adapter->mbox);
|
||||
}
|
||||
|
||||
int cxgbe_probe(struct adapter *adapter)
|
||||
{
|
||||
struct port_info *pi;
|
||||
|
@ -1959,6 +1959,35 @@ static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all queues of the port
|
||||
*
|
||||
* Note: This function must only be called after rx and tx path
|
||||
* of the port have been disabled.
|
||||
*/
|
||||
void t4_sge_eth_clear_queues(struct port_info *pi)
|
||||
{
|
||||
int i;
|
||||
struct adapter *adap = pi->adapter;
|
||||
struct sge_eth_rxq *rxq = &adap->sge.ethrxq[pi->first_qset];
|
||||
struct sge_eth_txq *txq = &adap->sge.ethtxq[pi->first_qset];
|
||||
|
||||
for (i = 0; i < pi->n_rx_qsets; i++, rxq++) {
|
||||
if (rxq->rspq.desc)
|
||||
t4_sge_eth_rxq_stop(adap, &rxq->rspq);
|
||||
}
|
||||
for (i = 0; i < pi->n_tx_qsets; i++, txq++) {
|
||||
if (txq->q.desc) {
|
||||
struct sge_txq *q = &txq->q;
|
||||
|
||||
t4_sge_eth_txq_stop(txq);
|
||||
reclaim_completed_tx(q);
|
||||
free_tx_desc(q, q->size);
|
||||
q->equeidx = q->pidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void t4_sge_eth_rxq_release(struct adapter *adap, struct sge_eth_rxq *rxq)
|
||||
{
|
||||
if (rxq->rspq.desc) {
|
||||
@ -1989,6 +2018,35 @@ void t4_sge_tx_monitor_stop(struct adapter *adap)
|
||||
rte_eal_alarm_cancel(tx_timer_cb, (void *)adap);
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_free_sge_resources - free SGE resources
|
||||
* @adap: the adapter
|
||||
*
|
||||
* Frees resources used by the SGE queue sets.
|
||||
*/
|
||||
void t4_free_sge_resources(struct adapter *adap)
|
||||
{
|
||||
int i;
|
||||
struct sge_eth_rxq *rxq = &adap->sge.ethrxq[0];
|
||||
struct sge_eth_txq *txq = &adap->sge.ethtxq[0];
|
||||
|
||||
/* clean up Ethernet Tx/Rx queues */
|
||||
for (i = 0; i < adap->sge.max_ethqsets; i++, rxq++, txq++) {
|
||||
/* Free only the queues allocated */
|
||||
if (rxq->rspq.desc) {
|
||||
t4_sge_eth_rxq_release(adap, rxq);
|
||||
rxq->rspq.eth_dev = NULL;
|
||||
}
|
||||
if (txq->q.desc) {
|
||||
t4_sge_eth_txq_release(adap, txq);
|
||||
txq->eth_dev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (adap->sge.fw_evtq.desc)
|
||||
free_rspq_fl(adap, &adap->sge.fw_evtq, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_sge_init - initialize SGE
|
||||
* @adap: the adapter
|
||||
|
Loading…
Reference in New Issue
Block a user