mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 02:50:43 +00:00
sfc: make tx_queues_per_channel variable at runtime
Siena needs four TX queues (csum * highpri), EF10 needs two (csum), and EF100 only needs one (as checksumming is controlled entirely by the transmit descriptor). Rather than having various bits of ad-hoc code to decide which queues to set up etc., put the knowledge of how many TXQs a channel has in one place. Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
67e6398e2e
commit
f9cac93e5b
6 changed files with 30 additions and 31 deletions
|
@ -600,6 +600,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
|
||||||
* However, until we use TX option descriptors we need two TX queues
|
* However, until we use TX option descriptors we need two TX queues
|
||||||
* per channel.
|
* per channel.
|
||||||
*/
|
*/
|
||||||
|
efx->tx_queues_per_channel = 2;
|
||||||
efx->max_vis = efx_ef10_mem_map_size(efx) / efx->vi_stride;
|
efx->max_vis = efx_ef10_mem_map_size(efx) / efx->vi_stride;
|
||||||
if (!efx->max_vis) {
|
if (!efx->max_vis) {
|
||||||
netif_err(efx, drv, efx->net_dev, "error determining max VIs\n");
|
netif_err(efx, drv, efx->net_dev, "error determining max VIs\n");
|
||||||
|
@ -607,7 +608,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
|
||||||
goto fail5;
|
goto fail5;
|
||||||
}
|
}
|
||||||
efx->max_channels = min_t(unsigned int, EFX_MAX_CHANNELS,
|
efx->max_channels = min_t(unsigned int, EFX_MAX_CHANNELS,
|
||||||
efx->max_vis / EFX_TXQ_TYPES);
|
efx->max_vis / efx->tx_queues_per_channel);
|
||||||
efx->max_tx_channels = efx->max_channels;
|
efx->max_tx_channels = efx->max_channels;
|
||||||
if (WARN_ON(efx->max_channels == 0)) {
|
if (WARN_ON(efx->max_channels == 0)) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
|
@ -1120,17 +1121,17 @@ static int efx_ef10_alloc_vis(struct efx_nic *efx,
|
||||||
*/
|
*/
|
||||||
static int efx_ef10_dimension_resources(struct efx_nic *efx)
|
static int efx_ef10_dimension_resources(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
unsigned int min_vis = max_t(unsigned int, efx->tx_queues_per_channel,
|
||||||
unsigned int uc_mem_map_size, wc_mem_map_size;
|
|
||||||
unsigned int min_vis = max(EFX_TXQ_TYPES,
|
|
||||||
efx_separate_tx_channels ? 2 : 1);
|
efx_separate_tx_channels ? 2 : 1);
|
||||||
unsigned int channel_vis, pio_write_vi_base, max_vis;
|
unsigned int channel_vis, pio_write_vi_base, max_vis;
|
||||||
|
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
||||||
|
unsigned int uc_mem_map_size, wc_mem_map_size;
|
||||||
void __iomem *membase;
|
void __iomem *membase;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
channel_vis = max(efx->n_channels,
|
channel_vis = max(efx->n_channels,
|
||||||
((efx->n_tx_channels + efx->n_extra_tx_channels) *
|
((efx->n_tx_channels + efx->n_extra_tx_channels) *
|
||||||
EFX_TXQ_TYPES) +
|
efx->tx_queues_per_channel) +
|
||||||
efx->n_xdp_channels * efx->xdp_tx_per_channel);
|
efx->n_xdp_channels * efx->xdp_tx_per_channel);
|
||||||
if (efx->max_vis && efx->max_vis < channel_vis) {
|
if (efx->max_vis && efx->max_vis < channel_vis) {
|
||||||
netif_dbg(efx, drv, efx->net_dev,
|
netif_dbg(efx, drv, efx->net_dev,
|
||||||
|
@ -1219,7 +1220,7 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
|
||||||
*/
|
*/
|
||||||
efx->max_channels = nic_data->n_allocated_vis;
|
efx->max_channels = nic_data->n_allocated_vis;
|
||||||
efx->max_tx_channels =
|
efx->max_tx_channels =
|
||||||
nic_data->n_allocated_vis / EFX_TXQ_TYPES;
|
nic_data->n_allocated_vis / efx->tx_queues_per_channel;
|
||||||
|
|
||||||
efx_mcdi_free_vis(efx);
|
efx_mcdi_free_vis(efx);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
|
@ -726,7 +726,7 @@ void efx_remove_channel(struct efx_channel *channel)
|
||||||
|
|
||||||
efx_for_each_channel_rx_queue(rx_queue, channel)
|
efx_for_each_channel_rx_queue(rx_queue, channel)
|
||||||
efx_remove_rx_queue(rx_queue);
|
efx_remove_rx_queue(rx_queue);
|
||||||
efx_for_each_possible_channel_tx_queue(tx_queue, channel)
|
efx_for_each_channel_tx_queue(tx_queue, channel)
|
||||||
efx_remove_tx_queue(tx_queue);
|
efx_remove_tx_queue(tx_queue);
|
||||||
efx_remove_eventq(channel);
|
efx_remove_eventq(channel);
|
||||||
channel->type->post_remove(channel);
|
channel->type->post_remove(channel);
|
||||||
|
@ -1090,7 +1090,7 @@ void efx_stop_channels(struct efx_nic *efx)
|
||||||
efx_for_each_channel(channel, efx) {
|
efx_for_each_channel(channel, efx) {
|
||||||
efx_for_each_channel_rx_queue(rx_queue, channel)
|
efx_for_each_channel_rx_queue(rx_queue, channel)
|
||||||
efx_fini_rx_queue(rx_queue);
|
efx_fini_rx_queue(rx_queue);
|
||||||
efx_for_each_possible_channel_tx_queue(tx_queue, channel)
|
efx_for_each_channel_tx_queue(tx_queue, channel)
|
||||||
efx_fini_tx_queue(tx_queue);
|
efx_fini_tx_queue(tx_queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1036,6 +1036,7 @@ int efx_init_struct(struct efx_nic *efx,
|
||||||
INIT_WORK(&efx->mac_work, efx_mac_work);
|
INIT_WORK(&efx->mac_work, efx_mac_work);
|
||||||
init_waitqueue_head(&efx->flush_wq);
|
init_waitqueue_head(&efx->flush_wq);
|
||||||
|
|
||||||
|
efx->tx_queues_per_channel = 1;
|
||||||
efx->rxq_entries = EFX_DEFAULT_DMAQ_SIZE;
|
efx->rxq_entries = EFX_DEFAULT_DMAQ_SIZE;
|
||||||
efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
|
efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
|
||||||
|
|
||||||
|
|
|
@ -867,6 +867,7 @@ struct efx_async_filter_insertion {
|
||||||
* @n_rx_channels: Number of channels used for RX (= number of RX queues)
|
* @n_rx_channels: Number of channels used for RX (= number of RX queues)
|
||||||
* @n_tx_channels: Number of channels used for TX
|
* @n_tx_channels: Number of channels used for TX
|
||||||
* @n_extra_tx_channels: Number of extra channels with TX queues
|
* @n_extra_tx_channels: Number of extra channels with TX queues
|
||||||
|
* @tx_queues_per_channel: number of TX queues probed on each channel
|
||||||
* @n_xdp_channels: Number of channels used for XDP TX
|
* @n_xdp_channels: Number of channels used for XDP TX
|
||||||
* @xdp_channel_offset: Offset of zeroth channel used for XPD TX.
|
* @xdp_channel_offset: Offset of zeroth channel used for XPD TX.
|
||||||
* @xdp_tx_per_channel: Max number of TX queues on an XDP TX channel.
|
* @xdp_tx_per_channel: Max number of TX queues on an XDP TX channel.
|
||||||
|
@ -1031,6 +1032,7 @@ struct efx_nic {
|
||||||
unsigned tx_channel_offset;
|
unsigned tx_channel_offset;
|
||||||
unsigned n_tx_channels;
|
unsigned n_tx_channels;
|
||||||
unsigned n_extra_tx_channels;
|
unsigned n_extra_tx_channels;
|
||||||
|
unsigned int tx_queues_per_channel;
|
||||||
unsigned int n_xdp_channels;
|
unsigned int n_xdp_channels;
|
||||||
unsigned int xdp_channel_offset;
|
unsigned int xdp_channel_offset;
|
||||||
unsigned int xdp_tx_per_channel;
|
unsigned int xdp_tx_per_channel;
|
||||||
|
@ -1529,7 +1531,7 @@ static inline struct efx_tx_queue *
|
||||||
efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
|
efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
|
||||||
{
|
{
|
||||||
EFX_WARN_ON_ONCE_PARANOID(index >= efx->n_tx_channels ||
|
EFX_WARN_ON_ONCE_PARANOID(index >= efx->n_tx_channels ||
|
||||||
type >= EFX_TXQ_TYPES);
|
type >= efx->tx_queues_per_channel);
|
||||||
return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
|
return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1551,38 +1553,28 @@ static inline bool efx_channel_has_tx_queues(struct efx_channel *channel)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int efx_channel_num_tx_queues(struct efx_channel *channel)
|
||||||
|
{
|
||||||
|
if (efx_channel_is_xdp_tx(channel))
|
||||||
|
return channel->efx->xdp_tx_per_channel;
|
||||||
|
return channel->efx->tx_queues_per_channel;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct efx_tx_queue *
|
static inline struct efx_tx_queue *
|
||||||
efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
|
efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
|
||||||
{
|
{
|
||||||
EFX_WARN_ON_ONCE_PARANOID(!efx_channel_has_tx_queues(channel) ||
|
EFX_WARN_ON_ONCE_PARANOID(type >= efx_channel_num_tx_queues(channel));
|
||||||
type >= EFX_TXQ_TYPES);
|
|
||||||
return &channel->tx_queue[type];
|
return &channel->tx_queue[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
|
|
||||||
{
|
|
||||||
return !(tx_queue->efx->net_dev->num_tc < 2 &&
|
|
||||||
tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterate over all TX queues belonging to a channel */
|
/* Iterate over all TX queues belonging to a channel */
|
||||||
#define efx_for_each_channel_tx_queue(_tx_queue, _channel) \
|
#define efx_for_each_channel_tx_queue(_tx_queue, _channel) \
|
||||||
if (!efx_channel_has_tx_queues(_channel)) \
|
if (!efx_channel_has_tx_queues(_channel)) \
|
||||||
; \
|
; \
|
||||||
else \
|
else \
|
||||||
for (_tx_queue = (_channel)->tx_queue; \
|
for (_tx_queue = (_channel)->tx_queue; \
|
||||||
_tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES && \
|
_tx_queue < (_channel)->tx_queue + \
|
||||||
(efx_tx_queue_used(_tx_queue) || \
|
efx_channel_num_tx_queues(_channel); \
|
||||||
efx_channel_is_xdp_tx(_channel)); \
|
|
||||||
_tx_queue++)
|
|
||||||
|
|
||||||
/* Iterate over all possible TX queues belonging to a channel */
|
|
||||||
#define efx_for_each_possible_channel_tx_queue(_tx_queue, _channel) \
|
|
||||||
if (!efx_channel_has_tx_queues(_channel)) \
|
|
||||||
; \
|
|
||||||
else \
|
|
||||||
for (_tx_queue = (_channel)->tx_queue; \
|
|
||||||
_tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
|
|
||||||
_tx_queue++)
|
_tx_queue++)
|
||||||
|
|
||||||
static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
|
static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
|
||||||
|
|
|
@ -279,6 +279,7 @@ static int siena_probe_nic(struct efx_nic *efx)
|
||||||
efx->max_channels = EFX_MAX_CHANNELS;
|
efx->max_channels = EFX_MAX_CHANNELS;
|
||||||
efx->max_vis = EFX_MAX_CHANNELS;
|
efx->max_vis = EFX_MAX_CHANNELS;
|
||||||
efx->max_tx_channels = EFX_MAX_CHANNELS;
|
efx->max_tx_channels = EFX_MAX_CHANNELS;
|
||||||
|
efx->tx_queues_per_channel = 2;
|
||||||
|
|
||||||
efx_reado(efx, ®, FR_AZ_CS_DEBUG);
|
efx_reado(efx, ®, FR_AZ_CS_DEBUG);
|
||||||
efx->port_num = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
|
efx->port_num = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
|
||||||
|
|
|
@ -569,6 +569,10 @@ int efx_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
|
||||||
if (type != TC_SETUP_QDISC_MQPRIO)
|
if (type != TC_SETUP_QDISC_MQPRIO)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Only Siena supported highpri queues */
|
||||||
|
if (efx_nic_rev(efx) > EFX_REV_SIENA_A0)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
num_tc = mqprio->num_tc;
|
num_tc = mqprio->num_tc;
|
||||||
|
|
||||||
if (num_tc > EFX_MAX_TX_TC)
|
if (num_tc > EFX_MAX_TX_TC)
|
||||||
|
@ -585,10 +589,10 @@ int efx_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_tc > net_dev->num_tc) {
|
if (num_tc > net_dev->num_tc) {
|
||||||
|
efx->tx_queues_per_channel = 4;
|
||||||
/* Initialise high-priority queues as necessary */
|
/* Initialise high-priority queues as necessary */
|
||||||
efx_for_each_channel(channel, efx) {
|
efx_for_each_channel(channel, efx) {
|
||||||
efx_for_each_possible_channel_tx_queue(tx_queue,
|
efx_for_each_channel_tx_queue(tx_queue, channel) {
|
||||||
channel) {
|
|
||||||
if (!(tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI))
|
if (!(tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI))
|
||||||
continue;
|
continue;
|
||||||
if (!tx_queue->buffer) {
|
if (!tx_queue->buffer) {
|
||||||
|
|
Loading…
Reference in a new issue