net/cxgbe: rework queue allocation between ports

Firmware returns the max queues that can be allocated on the entire
PF. The driver evenly distributes them across all the ports belonging
to the PF. However, some ports may need more queues than others and
this equal distribution scheme prevents accessing these other ports
unused queues. So, remove the equal distribution scheme and allow the
ports to allocate as many queues as they need.

Also remove the hardcoded 64 max limit on queue allocation. Instead,
use the max limit given by firmware.

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
This commit is contained in:
Rahul Lakkireddy 2020-09-12 05:22:08 +05:30 committed by Ferruh Yigit
parent 11df4a688d
commit 7b3d52989a
10 changed files with 126 additions and 113 deletions

View File

@ -19,7 +19,6 @@
#include "t4_regs_values.h"
enum {
MAX_ETH_QSETS = 64, /* # of Ethernet Tx/Rx queue sets */
MAX_CTRL_QUEUES = NCHAN, /* # of control Tx queues */
};
@ -47,9 +46,10 @@ struct port_info {
u8 pidx; /* port index for this PF */
u8 tx_chan; /* associated channel */
u8 n_rx_qsets; /* # of rx qsets */
u8 n_tx_qsets; /* # of tx qsets */
u8 first_qset; /* index of first qset */
u16 n_rx_qsets; /* # of rx qsets */
u16 n_tx_qsets; /* # of tx qsets */
u16 first_rxqset; /* index of first rxqset */
u16 first_txqset; /* index of first txqset */
u16 *rss; /* rss table */
u8 rss_mode; /* rss mode */
@ -274,8 +274,8 @@ struct sge_ctrl_txq { /* State for an SGE control Tx queue */
} __rte_cache_aligned;
struct sge {
struct sge_eth_txq ethtxq[MAX_ETH_QSETS];
struct sge_eth_rxq ethrxq[MAX_ETH_QSETS];
struct sge_eth_txq *ethtxq;
struct sge_eth_rxq *ethrxq;
struct sge_rspq fw_evtq __rte_cache_aligned;
struct sge_ctrl_txq ctrlq[MAX_CTRL_QUEUES];

View File

@ -218,6 +218,7 @@ struct rss_params {
*/
struct pf_resources {
unsigned int neq; /* N egress Qs */
unsigned int nethctrl; /* N egress ETH or CTRL Qs */
unsigned int niqflint; /* N ingress Qs/w free list(s) & intr */
};

View File

@ -2517,6 +2517,10 @@ int t4_get_pfres(struct adapter *adapter)
word = be32_to_cpu(rpl.type_to_neq);
pfres->neq = G_FW_PFVF_CMD_NEQ(word);
word = be32_to_cpu(rpl.r_caps_to_nethctrl);
pfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word);
return 0;
}

View File

@ -98,7 +98,8 @@ int cxgbe_poll_for_completion(struct sge_rspq *q, unsigned int us,
int cxgbe_link_start(struct port_info *pi);
int cxgbe_setup_sge_fwevtq(struct adapter *adapter);
int cxgbe_setup_sge_ctrl_txq(struct adapter *adapter);
void cxgbe_cfg_queues(struct rte_eth_dev *eth_dev);
int cxgbe_cfg_queues(struct rte_eth_dev *eth_dev);
void cxgbe_cfg_queues_free(struct adapter *adapter);
int cxgbe_cfg_queue_count(struct rte_eth_dev *eth_dev);
int cxgbe_init_rss(struct adapter *adap);
int cxgbe_setup_rss(struct port_info *pi);

View File

@ -116,7 +116,6 @@ int cxgbe_dev_info_get(struct rte_eth_dev *eth_dev,
{
struct port_info *pi = eth_dev->data->dev_private;
struct adapter *adapter = pi->adapter;
int max_queues = adapter->sge.max_ethqsets / adapter->params.nports;
static const struct rte_eth_desc_lim cxgbe_desc_lim = {
.nb_max = CXGBE_MAX_RING_DESC_SIZE,
@ -126,8 +125,8 @@ int cxgbe_dev_info_get(struct rte_eth_dev *eth_dev,
device_info->min_rx_bufsize = CXGBE_MIN_RX_BUFSIZE;
device_info->max_rx_pktlen = CXGBE_MAX_RX_PKTLEN;
device_info->max_rx_queues = max_queues;
device_info->max_tx_queues = max_queues;
device_info->max_rx_queues = adapter->sge.max_ethqsets;
device_info->max_tx_queues = adapter->sge.max_ethqsets;
device_info->max_mac_addrs = 1;
/* XXX: For now we support one MAC/port */
device_info->max_vfs = adapter->params.arch.vfcount;
@ -501,13 +500,14 @@ int cxgbe_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
struct port_info *pi = eth_dev->data->dev_private;
struct adapter *adapter = pi->adapter;
struct sge *s = &adapter->sge;
struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset + queue_idx];
int err = 0;
unsigned int temp_nb_desc;
struct sge_eth_txq *txq;
int err = 0;
txq = &s->ethtxq[pi->first_txqset + queue_idx];
dev_debug(adapter, "%s: eth_dev->data->nb_tx_queues = %d; queue_idx = %d; nb_desc = %d; socket_id = %d; pi->first_qset = %u\n",
__func__, eth_dev->data->nb_tx_queues, queue_idx, nb_desc,
socket_id, pi->first_qset);
socket_id, pi->first_txqset);
/* Free up the existing queue */
if (eth_dev->data->tx_queues[queue_idx]) {
@ -603,16 +603,16 @@ int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
const struct rte_eth_rxconf *rx_conf __rte_unused,
struct rte_mempool *mp)
{
unsigned int pkt_len = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len;
struct port_info *pi = eth_dev->data->dev_private;
struct adapter *adapter = pi->adapter;
struct sge *s = &adapter->sge;
struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset + queue_idx];
int err = 0;
int msi_idx = 0;
unsigned int temp_nb_desc;
struct rte_eth_dev_info dev_info;
unsigned int pkt_len = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len;
struct sge *s = &adapter->sge;
unsigned int temp_nb_desc;
int err = 0, msi_idx = 0;
struct sge_eth_rxq *rxq;
rxq = &s->ethrxq[pi->first_rxqset + queue_idx];
dev_debug(adapter, "%s: eth_dev->data->nb_rx_queues = %d; queue_idx = %d; nb_desc = %d; socket_id = %d; mp = %p\n",
__func__, eth_dev->data->nb_rx_queues, queue_idx, nb_desc,
socket_id, mp);
@ -685,11 +685,10 @@ int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
void cxgbe_dev_rx_queue_release(void *q)
{
struct sge_eth_rxq *rxq = (struct sge_eth_rxq *)q;
struct sge_rspq *rq = &rxq->rspq;
if (rq) {
if (rxq) {
struct port_info *pi = (struct port_info *)
(rq->eth_dev->data->dev_private);
(rxq->rspq.eth_dev->data->dev_private);
struct adapter *adap = pi->adapter;
dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n",
@ -729,7 +728,7 @@ static int cxgbe_dev_stats_get(struct rte_eth_dev *eth_dev,
for (i = 0; i < pi->n_rx_qsets; i++) {
struct sge_eth_rxq *rxq =
&s->ethrxq[pi->first_qset + i];
&s->ethrxq[pi->first_rxqset + i];
eth_stats->q_ipackets[i] = rxq->stats.pkts;
eth_stats->q_ibytes[i] = rxq->stats.rx_bytes;
@ -739,7 +738,7 @@ static int cxgbe_dev_stats_get(struct rte_eth_dev *eth_dev,
for (i = 0; i < pi->n_tx_qsets; i++) {
struct sge_eth_txq *txq =
&s->ethtxq[pi->first_qset + i];
&s->ethtxq[pi->first_txqset + i];
eth_stats->q_opackets[i] = txq->stats.pkts;
eth_stats->q_obytes[i] = txq->stats.tx_bytes;
@ -760,14 +759,14 @@ static int cxgbe_dev_stats_reset(struct rte_eth_dev *eth_dev)
cxgbe_stats_reset(pi);
for (i = 0; i < pi->n_rx_qsets; i++) {
struct sge_eth_rxq *rxq =
&s->ethrxq[pi->first_qset + i];
&s->ethrxq[pi->first_rxqset + i];
rxq->stats.pkts = 0;
rxq->stats.rx_bytes = 0;
}
for (i = 0; i < pi->n_tx_qsets; i++) {
struct sge_eth_txq *txq =
&s->ethtxq[pi->first_qset + i];
&s->ethtxq[pi->first_txqset + i];
txq->stats.pkts = 0;
txq->stats.tx_bytes = 0;

View File

@ -145,7 +145,7 @@ static unsigned int get_filter_steerq(struct rte_eth_dev *dev,
* then assume it is an absolute qid.
*/
if (fs->iq < pi->n_rx_qsets)
iq = adapter->sge.ethrxq[pi->first_qset +
iq = adapter->sge.ethrxq[pi->first_rxqset +
fs->iq].rspq.abs_id;
else
iq = fs->iq;

View File

@ -526,22 +526,6 @@ static int tid_init(struct tid_info *t)
return 0;
}
static inline bool is_x_1g_port(const struct link_config *lc)
{
return (lc->pcaps & FW_PORT_CAP32_SPEED_1G) != 0;
}
static inline bool is_x_10g_port(const struct link_config *lc)
{
unsigned int speeds, high_speeds;
speeds = V_FW_PORT_CAP32_SPEED(G_FW_PORT_CAP32_SPEED(lc->pcaps));
high_speeds = speeds &
~(FW_PORT_CAP32_SPEED_100M | FW_PORT_CAP32_SPEED_1G);
return high_speeds != 0;
}
static inline void init_rspq(struct adapter *adap, struct sge_rspq *q,
unsigned int us, unsigned int cnt,
unsigned int size, unsigned int iqe_size)
@ -554,20 +538,35 @@ static inline void init_rspq(struct adapter *adap, struct sge_rspq *q,
int cxgbe_cfg_queue_count(struct rte_eth_dev *eth_dev)
{
struct port_info *pi = eth_dev->data->dev_private;
struct port_info *temp_pi, *pi = eth_dev->data->dev_private;
struct adapter *adap = pi->adapter;
u16 first_txq = 0, first_rxq = 0;
struct sge *s = &adap->sge;
unsigned int max_queues = s->max_ethqsets / adap->params.nports;
u16 i, max_rxqs, max_txqs;
max_rxqs = s->max_ethqsets;
max_txqs = s->max_ethqsets;
for_each_port(adap, i) {
temp_pi = adap2pinfo(adap, i);
if (i == pi->port_id)
break;
if (max_rxqs <= temp_pi->n_rx_qsets ||
max_txqs <= temp_pi->n_tx_qsets)
return -ENOMEM;
first_rxq += temp_pi->n_rx_qsets;
first_txq += temp_pi->n_tx_qsets;
max_rxqs -= temp_pi->n_rx_qsets;
max_txqs -= temp_pi->n_tx_qsets;
}
if ((eth_dev->data->nb_rx_queues < 1) ||
(eth_dev->data->nb_tx_queues < 1))
return -EINVAL;
if ((eth_dev->data->nb_rx_queues > max_queues) ||
(eth_dev->data->nb_tx_queues > max_queues))
return -EINVAL;
if (eth_dev->data->nb_rx_queues > pi->rss_size)
if (eth_dev->data->nb_rx_queues > max_rxqs ||
eth_dev->data->nb_tx_queues > max_txqs)
return -EINVAL;
/* We must configure RSS, since config has changed*/
@ -575,68 +574,66 @@ int cxgbe_cfg_queue_count(struct rte_eth_dev *eth_dev)
pi->n_rx_qsets = eth_dev->data->nb_rx_queues;
pi->n_tx_qsets = eth_dev->data->nb_tx_queues;
pi->first_rxqset = first_rxq;
pi->first_txqset = first_txq;
return 0;
}
void cxgbe_cfg_queues(struct rte_eth_dev *eth_dev)
void cxgbe_cfg_queues_free(struct adapter *adap)
{
if (adap->sge.ethtxq) {
rte_free(adap->sge.ethtxq);
adap->sge.ethtxq = NULL;
}
if (adap->sge.ethrxq) {
rte_free(adap->sge.ethrxq);
adap->sge.ethrxq = NULL;
}
adap->flags &= ~CFG_QUEUES;
}
int cxgbe_cfg_queues(struct rte_eth_dev *eth_dev)
{
struct port_info *pi = eth_dev->data->dev_private;
struct adapter *adap = pi->adapter;
struct sge *s = &adap->sge;
unsigned int i, nb_ports = 0, qidx = 0;
unsigned int q_per_port = 0;
u16 i;
if (!(adap->flags & CFG_QUEUES)) {
for_each_port(adap, i) {
struct port_info *tpi = adap2pinfo(adap, i);
s->ethrxq = rte_calloc_socket(NULL, s->max_ethqsets,
sizeof(struct sge_eth_rxq), 0,
rte_socket_id());
if (!s->ethrxq)
return -ENOMEM;
nb_ports += (is_x_10g_port(&tpi->link_cfg)) ||
is_x_1g_port(&tpi->link_cfg) ? 1 : 0;
s->ethtxq = rte_calloc_socket(NULL, s->max_ethqsets,
sizeof(struct sge_eth_txq), 0,
rte_socket_id());
if (!s->ethtxq) {
rte_free(s->ethrxq);
s->ethrxq = NULL;
return -ENOMEM;
}
/*
* We default up to # of cores queues per 1G/10G port.
*/
if (nb_ports)
q_per_port = (s->max_ethqsets -
(adap->params.nports - nb_ports)) /
nb_ports;
if (q_per_port > rte_lcore_count())
q_per_port = rte_lcore_count();
for_each_port(adap, i) {
struct port_info *pi = adap2pinfo(adap, i);
pi->first_qset = qidx;
/* Initially n_rx_qsets == n_tx_qsets */
pi->n_rx_qsets = (is_x_10g_port(&pi->link_cfg) ||
is_x_1g_port(&pi->link_cfg)) ?
q_per_port : 1;
pi->n_tx_qsets = pi->n_rx_qsets;
if (pi->n_rx_qsets > pi->rss_size)
pi->n_rx_qsets = pi->rss_size;
qidx += pi->n_rx_qsets;
}
for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) {
for (i = 0; i < s->max_ethqsets; i++) {
struct sge_eth_rxq *r = &s->ethrxq[i];
struct sge_eth_txq *t = &s->ethtxq[i];
init_rspq(adap, &r->rspq, 5, 32, 1024, 64);
r->usembufs = 1;
r->fl.size = (r->usembufs ? 1024 : 72);
}
for (i = 0; i < ARRAY_SIZE(s->ethtxq); i++)
s->ethtxq[i].q.size = 1024;
t->q.size = 1024;
}
init_rspq(adap, &adap->sge.fw_evtq, 0, 0, 1024, 64);
adap->flags |= CFG_QUEUES;
}
return 0;
}
void cxgbe_stats_get(struct port_info *pi, struct port_stats *stats)
@ -1043,34 +1040,31 @@ static void configure_pcie_ext_tag(struct adapter *adapter)
/* Figure out how many Queue Sets we can support */
void cxgbe_configure_max_ethqsets(struct adapter *adapter)
{
unsigned int ethqsets;
unsigned int ethqsets, reserved;
/*
* We need to reserve an Ingress Queue for the Asynchronous Firmware
* Event Queue.
/* We need to reserve an Ingress Queue for the Asynchronous Firmware
* Event Queue and 1 Control Queue per port.
*
* For each Queue Set, we'll need the ability to allocate two Egress
* Contexts -- one for the Ingress Queue Free List and one for the TX
* Ethernet Queue.
*/
reserved = max(adapter->params.nports, 1);
if (is_pf4(adapter)) {
struct pf_resources *pfres = &adapter->params.pfres;
ethqsets = pfres->niqflint - 1;
if (pfres->neq < ethqsets * 2)
ethqsets = min(pfres->niqflint, pfres->nethctrl);
if (ethqsets > (pfres->neq / 2))
ethqsets = pfres->neq / 2;
} else {
struct vf_resources *vfres = &adapter->params.vfres;
ethqsets = vfres->niqflint - 1;
if (vfres->nethctrl != ethqsets)
ethqsets = min(vfres->nethctrl, ethqsets);
if (vfres->neq < ethqsets * 2)
ethqsets = min(vfres->niqflint, vfres->nethctrl);
if (ethqsets > (vfres->neq / 2))
ethqsets = vfres->neq / 2;
}
if (ethqsets > MAX_ETH_QSETS)
ethqsets = MAX_ETH_QSETS;
ethqsets -= reserved;
adapter->sge.max_ethqsets = ethqsets;
}
@ -1707,7 +1701,7 @@ int cxgbe_write_rss_conf(const struct port_info *pi, uint64_t rss_hf)
F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN |
F_FW_RSS_VI_CONFIG_CMD_UDPEN;
rxq = &adapter->sge.ethrxq[pi->first_qset];
rxq = &adapter->sge.ethrxq[pi->first_rxqset];
rss = rxq[0].rspq.abs_id;
/* If Tunnel All Lookup isn't specified in the global RSS
@ -1738,7 +1732,7 @@ int cxgbe_write_rss(const struct port_info *pi, const u16 *queues)
/* Should never be called before setting up sge eth rx queues */
BUG_ON(!(adapter->flags & FULL_INIT_DONE));
rxq = &adapter->sge.ethrxq[pi->first_qset];
rxq = &adapter->sge.ethrxq[pi->first_rxqset];
rss = rte_zmalloc(NULL, pi->rss_size * sizeof(u16), 0);
if (!rss)
return -ENOMEM;
@ -1810,7 +1804,7 @@ void cxgbe_enable_rx_queues(struct port_info *pi)
unsigned int i;
for (i = 0; i < pi->n_rx_qsets; i++)
enable_rx(adap, &s->ethrxq[pi->first_qset + i].rspq);
enable_rx(adap, &s->ethrxq[pi->first_rxqset + i].rspq);
}
/**
@ -1988,6 +1982,8 @@ void cxgbe_close(struct adapter *adapter)
adapter->flags &= ~FULL_INIT_DONE;
}
cxgbe_cfg_queues_free(adapter);
if (is_pf4(adapter) && (adapter->flags & FW_OK))
t4_fw_bye(adapter, adapter->mbox);
}
@ -2163,7 +2159,9 @@ int cxgbe_probe(struct adapter *adapter)
}
}
cxgbe_cfg_queues(adapter->eth_dev);
err = cxgbe_cfg_queues(adapter->eth_dev);
if (err)
goto out_free;
cxgbe_print_adapter_info(adapter);
cxgbe_print_port_info(adapter);
@ -2222,6 +2220,8 @@ int cxgbe_probe(struct adapter *adapter)
return 0;
out_free:
cxgbe_cfg_queues_free(adapter);
for_each_port(adapter, i) {
pi = adap2pinfo(adapter, i);
if (pi->viid != 0)

View File

@ -55,7 +55,7 @@ static int cxgbevf_dev_stats_get(struct rte_eth_dev *eth_dev,
for (i = 0; i < pi->n_rx_qsets; i++) {
struct sge_eth_rxq *rxq =
&s->ethrxq[pi->first_qset + i];
&s->ethrxq[pi->first_rxqset + i];
eth_stats->q_ipackets[i] = rxq->stats.pkts;
eth_stats->q_ibytes[i] = rxq->stats.rx_bytes;
@ -65,7 +65,7 @@ static int cxgbevf_dev_stats_get(struct rte_eth_dev *eth_dev,
for (i = 0; i < pi->n_tx_qsets; i++) {
struct sge_eth_txq *txq =
&s->ethtxq[pi->first_qset + i];
&s->ethtxq[pi->first_txqset + i];
eth_stats->q_opackets[i] = txq->stats.pkts;
eth_stats->q_obytes[i] = txq->stats.tx_bytes;

View File

@ -278,7 +278,10 @@ int cxgbevf_probe(struct adapter *adapter)
}
}
cxgbe_cfg_queues(adapter->eth_dev);
err = cxgbe_cfg_queues(adapter->eth_dev);
if (err)
goto out_free;
cxgbe_print_adapter_info(adapter);
cxgbe_print_port_info(adapter);
@ -293,6 +296,8 @@ int cxgbevf_probe(struct adapter *adapter)
return 0;
out_free:
cxgbe_cfg_queues_free(adapter);
for_each_port(adapter, i) {
pi = adap2pinfo(adapter, i);
if (pi->viid != 0)

View File

@ -2193,15 +2193,18 @@ static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
*/
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];
struct sge_eth_rxq *rxq;
struct sge_eth_txq *txq;
int i;
rxq = &adap->sge.ethrxq[pi->first_rxqset];
for (i = 0; i < pi->n_rx_qsets; i++, rxq++) {
if (rxq->rspq.desc)
t4_sge_eth_rxq_stop(adap, &rxq->rspq);
}
txq = &adap->sge.ethtxq[pi->first_txqset];
for (i = 0; i < pi->n_tx_qsets; i++, txq++) {
if (txq->q.desc) {
struct sge_txq *q = &txq->q;
@ -2241,7 +2244,7 @@ void t4_sge_eth_release_queues(struct port_info *pi)
struct sge_eth_txq *txq;
unsigned int i;
rxq = &adap->sge.ethrxq[pi->first_qset];
rxq = &adap->sge.ethrxq[pi->first_rxqset];
/* clean up Ethernet Tx/Rx queues */
for (i = 0; i < pi->n_rx_qsets; i++, rxq++) {
/* Free only the queues allocated */
@ -2253,7 +2256,7 @@ void t4_sge_eth_release_queues(struct port_info *pi)
}
}
txq = &adap->sge.ethtxq[pi->first_qset];
txq = &adap->sge.ethtxq[pi->first_txqset];
for (i = 0; i < pi->n_tx_qsets; i++, txq++) {
/* Free only the queues allocated */
if (txq->q.desc) {