Commit 101b40a0 authored by Shannon Nelson's avatar Shannon Nelson Committed by David S. Miller

ionic: change queue count with no reset

Add to our new ionic_reconfigure_queues() to also be able to change
the number of queues in use, and to change the queue interrupt layout
between split and combined.
Signed-off-by: default avatarShannon Nelson <snelson@pensando.io>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a34e25ab
...@@ -561,32 +561,15 @@ static void ionic_get_channels(struct net_device *netdev, ...@@ -561,32 +561,15 @@ static void ionic_get_channels(struct net_device *netdev,
} }
} }
static void ionic_set_queuecount(struct ionic_lif *lif, void *arg)
{
struct ethtool_channels *ch = arg;
if (ch->combined_count) {
lif->nxqs = ch->combined_count;
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) {
clear_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);
lif->tx_coalesce_usecs = lif->rx_coalesce_usecs;
lif->tx_coalesce_hw = lif->rx_coalesce_hw;
netdev_info(lif->netdev, "Sharing queue interrupts\n");
}
} else {
lif->nxqs = ch->rx_count;
if (!test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) {
set_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);
netdev_info(lif->netdev, "Splitting queue interrupts\n");
}
}
}
static int ionic_set_channels(struct net_device *netdev, static int ionic_set_channels(struct net_device *netdev,
struct ethtool_channels *ch) struct ethtool_channels *ch)
{ {
struct ionic_lif *lif = netdev_priv(netdev); struct ionic_lif *lif = netdev_priv(netdev);
int new_cnt; struct ionic_queue_params qparam;
int max_cnt;
int err;
ionic_init_queue_params(lif, &qparam);
if (ch->rx_count != ch->tx_count) { if (ch->rx_count != ch->tx_count) {
netdev_info(netdev, "The rx and tx count must be equal\n"); netdev_info(netdev, "The rx and tx count must be equal\n");
...@@ -594,20 +577,63 @@ static int ionic_set_channels(struct net_device *netdev, ...@@ -594,20 +577,63 @@ static int ionic_set_channels(struct net_device *netdev,
} }
if (ch->combined_count && ch->rx_count) { if (ch->combined_count && ch->rx_count) {
netdev_info(netdev, "Use either combined_count or rx/tx_count, not both\n"); netdev_info(netdev, "Use either combined or rx and tx, not both\n");
return -EINVAL; return -EINVAL;
} }
if (ch->combined_count) max_cnt = lif->ionic->ntxqs_per_lif;
new_cnt = ch->combined_count; if (ch->combined_count) {
else if (ch->combined_count > max_cnt)
new_cnt = ch->rx_count; return -EINVAL;
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
netdev_info(lif->netdev, "Sharing queue interrupts\n");
else if (ch->combined_count == lif->nxqs)
return 0;
if (lif->nxqs != new_cnt) if (lif->nxqs != ch->combined_count)
netdev_info(netdev, "Changing queue count from %d to %d\n", netdev_info(netdev, "Changing queue count from %d to %d\n",
lif->nxqs, new_cnt); lif->nxqs, ch->combined_count);
return ionic_reset_queues(lif, ionic_set_queuecount, ch); qparam.nxqs = ch->combined_count;
qparam.intr_split = 0;
} else {
max_cnt /= 2;
if (ch->rx_count > max_cnt)
return -EINVAL;
if (!test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
netdev_info(lif->netdev, "Splitting queue interrupts\n");
else if (ch->rx_count == lif->nxqs)
return 0;
if (lif->nxqs != ch->rx_count)
netdev_info(netdev, "Changing queue count from %d to %d\n",
lif->nxqs, ch->rx_count);
qparam.nxqs = ch->rx_count;
qparam.intr_split = 1;
}
/* if we're not running, just set the values and return */
if (!netif_running(lif->netdev)) {
lif->nxqs = qparam.nxqs;
if (qparam.intr_split) {
set_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);
} else {
clear_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);
lif->tx_coalesce_usecs = lif->rx_coalesce_usecs;
lif->tx_coalesce_hw = lif->rx_coalesce_hw;
}
return 0;
}
err = ionic_reconfigure_queues(lif, &qparam);
if (err)
netdev_info(netdev, "Queue reconfiguration failed, changes canceled: %d\n", err);
return err;
} }
static u32 ionic_get_priv_flags(struct net_device *netdev) static u32 ionic_get_priv_flags(struct net_device *netdev)
......
...@@ -299,6 +299,18 @@ static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq) ...@@ -299,6 +299,18 @@ static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
qcq->flags &= ~IONIC_QCQ_F_INITED; qcq->flags &= ~IONIC_QCQ_F_INITED;
} }
static void ionic_qcq_intr_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
{
if (!(qcq->flags & IONIC_QCQ_F_INTR) || qcq->intr.vector == 0)
return;
irq_set_affinity_hint(qcq->intr.vector, NULL);
devm_free_irq(lif->ionic->dev, qcq->intr.vector, &qcq->napi);
qcq->intr.vector = 0;
ionic_intr_free(lif->ionic, qcq->intr.index);
qcq->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
}
static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq) static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
{ {
struct device *dev = lif->ionic->dev; struct device *dev = lif->ionic->dev;
...@@ -326,12 +338,7 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq) ...@@ -326,12 +338,7 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
qcq->sg_base_pa = 0; qcq->sg_base_pa = 0;
} }
if (qcq->flags & IONIC_QCQ_F_INTR) { ionic_qcq_intr_free(lif, qcq);
irq_set_affinity_hint(qcq->intr.vector, NULL);
devm_free_irq(dev, qcq->intr.vector, &qcq->napi);
qcq->intr.vector = 0;
ionic_intr_free(lif->ionic, qcq->intr.index);
}
if (qcq->cq.info) { if (qcq->cq.info) {
devm_kfree(dev, qcq->cq.info); devm_kfree(dev, qcq->cq.info);
...@@ -341,7 +348,6 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq) ...@@ -341,7 +348,6 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
devm_kfree(dev, qcq->q.info); devm_kfree(dev, qcq->q.info);
qcq->q.info = NULL; qcq->q.info = NULL;
} }
devm_kfree(dev, qcq);
} }
static void ionic_qcqs_free(struct ionic_lif *lif) static void ionic_qcqs_free(struct ionic_lif *lif)
...@@ -350,11 +356,13 @@ static void ionic_qcqs_free(struct ionic_lif *lif) ...@@ -350,11 +356,13 @@ static void ionic_qcqs_free(struct ionic_lif *lif)
if (lif->notifyqcq) { if (lif->notifyqcq) {
ionic_qcq_free(lif, lif->notifyqcq); ionic_qcq_free(lif, lif->notifyqcq);
devm_kfree(dev, lif->notifyqcq);
lif->notifyqcq = NULL; lif->notifyqcq = NULL;
} }
if (lif->adminqcq) { if (lif->adminqcq) {
ionic_qcq_free(lif, lif->adminqcq); ionic_qcq_free(lif, lif->adminqcq);
devm_kfree(dev, lif->adminqcq);
lif->adminqcq = NULL; lif->adminqcq = NULL;
} }
...@@ -385,6 +393,53 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq, ...@@ -385,6 +393,53 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
n_qcq->intr.index = src_qcq->intr.index; n_qcq->intr.index = src_qcq->intr.index;
} }
static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qcq)
{
int err;
if (!(qcq->flags & IONIC_QCQ_F_INTR)) {
qcq->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
return 0;
}
err = ionic_intr_alloc(lif, &qcq->intr);
if (err) {
netdev_warn(lif->netdev, "no intr for %s: %d\n",
qcq->q.name, err);
goto err_out;
}
err = ionic_bus_get_irq(lif->ionic, qcq->intr.index);
if (err < 0) {
netdev_warn(lif->netdev, "no vector for %s: %d\n",
qcq->q.name, err);
goto err_out_free_intr;
}
qcq->intr.vector = err;
ionic_intr_mask_assert(lif->ionic->idev.intr_ctrl, qcq->intr.index,
IONIC_INTR_MASK_SET);
err = ionic_request_irq(lif, qcq);
if (err) {
netdev_warn(lif->netdev, "irq request failed %d\n", err);
goto err_out_free_intr;
}
/* try to get the irq on the local numa node first */
qcq->intr.cpu = cpumask_local_spread(qcq->intr.index,
dev_to_node(lif->ionic->dev));
if (qcq->intr.cpu != -1)
cpumask_set_cpu(qcq->intr.cpu, &qcq->intr.affinity_mask);
netdev_dbg(lif->netdev, "%s: Interrupt index %d\n", qcq->q.name, qcq->intr.index);
return 0;
err_out_free_intr:
ionic_intr_free(lif->ionic, qcq->intr.index);
err_out:
return err;
}
static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
unsigned int index, unsigned int index,
const char *name, unsigned int flags, const char *name, unsigned int flags,
...@@ -430,39 +485,9 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, ...@@ -430,39 +485,9 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
goto err_out_free_q_info; goto err_out_free_q_info;
} }
if (flags & IONIC_QCQ_F_INTR) { err = ionic_alloc_qcq_interrupt(lif, new);
err = ionic_intr_alloc(lif, &new->intr); if (err)
if (err) {
netdev_warn(lif->netdev, "no intr for %s: %d\n",
new->q.name, err);
goto err_out; goto err_out;
}
err = ionic_bus_get_irq(lif->ionic, new->intr.index);
if (err < 0) {
netdev_warn(lif->netdev, "no vector for %s: %d\n",
new->q.name, err);
goto err_out_free_intr;
}
new->intr.vector = err;
ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
IONIC_INTR_MASK_SET);
err = ionic_request_irq(lif, new);
if (err) {
netdev_warn(lif->netdev, "irq request failed for %s: %d\n",
new->q.name, err);
goto err_out_free_intr;
}
new->intr.cpu = cpumask_local_spread(new->intr.index,
dev_to_node(dev));
if (new->intr.cpu != -1)
cpumask_set_cpu(new->intr.cpu,
&new->intr.affinity_mask);
} else {
new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
}
new->cq.info = devm_kcalloc(dev, num_descs, sizeof(*new->cq.info), new->cq.info = devm_kcalloc(dev, num_descs, sizeof(*new->cq.info),
GFP_KERNEL); GFP_KERNEL);
...@@ -528,11 +553,10 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, ...@@ -528,11 +553,10 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
err_out_free_cq_info: err_out_free_cq_info:
devm_kfree(dev, new->cq.info); devm_kfree(dev, new->cq.info);
err_out_free_irq: err_out_free_irq:
if (flags & IONIC_QCQ_F_INTR) if (flags & IONIC_QCQ_F_INTR) {
devm_free_irq(dev, new->intr.vector, &new->napi); devm_free_irq(dev, new->intr.vector, &new->napi);
err_out_free_intr:
if (flags & IONIC_QCQ_F_INTR)
ionic_intr_free(lif->ionic, new->intr.index); ionic_intr_free(lif->ionic, new->intr.index);
}
err_out_free_q_info: err_out_free_q_info:
devm_kfree(dev, new->q.info); devm_kfree(dev, new->q.info);
err_out_free_qcq: err_out_free_qcq:
...@@ -635,7 +659,7 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq) ...@@ -635,7 +659,7 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
unsigned int intr_index; unsigned int intr_index;
int err; int err;
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) if (qcq->flags & IONIC_QCQ_F_INTR)
intr_index = qcq->intr.index; intr_index = qcq->intr.index;
else else
intr_index = lif->rxqcqs[q->index]->intr.index; intr_index = lif->rxqcqs[q->index]->intr.index;
...@@ -1539,7 +1563,7 @@ static void ionic_txrx_deinit(struct ionic_lif *lif) ...@@ -1539,7 +1563,7 @@ static void ionic_txrx_deinit(struct ionic_lif *lif)
unsigned int i; unsigned int i;
if (lif->txqcqs) { if (lif->txqcqs) {
for (i = 0; i < lif->nxqs; i++) { for (i = 0; i < lif->nxqs && lif->txqcqs[i]; i++) {
ionic_lif_qcq_deinit(lif, lif->txqcqs[i]); ionic_lif_qcq_deinit(lif, lif->txqcqs[i]);
ionic_tx_flush(&lif->txqcqs[i]->cq); ionic_tx_flush(&lif->txqcqs[i]->cq);
ionic_tx_empty(&lif->txqcqs[i]->q); ionic_tx_empty(&lif->txqcqs[i]->q);
...@@ -1547,7 +1571,7 @@ static void ionic_txrx_deinit(struct ionic_lif *lif) ...@@ -1547,7 +1571,7 @@ static void ionic_txrx_deinit(struct ionic_lif *lif)
} }
if (lif->rxqcqs) { if (lif->rxqcqs) {
for (i = 0; i < lif->nxqs; i++) { for (i = 0; i < lif->nxqs && lif->rxqcqs[i]; i++) {
ionic_lif_qcq_deinit(lif, lif->rxqcqs[i]); ionic_lif_qcq_deinit(lif, lif->rxqcqs[i]);
ionic_rx_flush(&lif->rxqcqs[i]->cq); ionic_rx_flush(&lif->rxqcqs[i]->cq);
ionic_rx_empty(&lif->rxqcqs[i]->q); ionic_rx_empty(&lif->rxqcqs[i]->q);
...@@ -1561,15 +1585,17 @@ static void ionic_txrx_free(struct ionic_lif *lif) ...@@ -1561,15 +1585,17 @@ static void ionic_txrx_free(struct ionic_lif *lif)
unsigned int i; unsigned int i;
if (lif->txqcqs) { if (lif->txqcqs) {
for (i = 0; i < lif->nxqs; i++) { for (i = 0; i < lif->ionic->ntxqs_per_lif && lif->txqcqs[i]; i++) {
ionic_qcq_free(lif, lif->txqcqs[i]); ionic_qcq_free(lif, lif->txqcqs[i]);
devm_kfree(lif->ionic->dev, lif->txqcqs[i]);
lif->txqcqs[i] = NULL; lif->txqcqs[i] = NULL;
} }
} }
if (lif->rxqcqs) { if (lif->rxqcqs) {
for (i = 0; i < lif->nxqs; i++) { for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++) {
ionic_qcq_free(lif, lif->rxqcqs[i]); ionic_qcq_free(lif, lif->rxqcqs[i]);
devm_kfree(lif->ionic->dev, lif->rxqcqs[i]);
lif->rxqcqs[i] = NULL; lif->rxqcqs[i] = NULL;
} }
} }
...@@ -2088,20 +2114,22 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2088,20 +2114,22 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
unsigned int i; unsigned int i;
/* allocate temporary qcq arrays to hold new queue structs */ /* allocate temporary qcq arrays to hold new queue structs */
if (qparam->ntxq_descs != lif->ntxq_descs) { if (qparam->nxqs != lif->nxqs || qparam->ntxq_descs != lif->ntxq_descs) {
tx_qcqs = devm_kcalloc(lif->ionic->dev, lif->nxqs, tx_qcqs = devm_kcalloc(lif->ionic->dev, lif->ionic->ntxqs_per_lif,
sizeof(struct ionic_qcq *), GFP_KERNEL); sizeof(struct ionic_qcq *), GFP_KERNEL);
if (!tx_qcqs) if (!tx_qcqs)
goto err_out; goto err_out;
} }
if (qparam->nrxq_descs != lif->nrxq_descs) { if (qparam->nxqs != lif->nxqs || qparam->nrxq_descs != lif->nrxq_descs) {
rx_qcqs = devm_kcalloc(lif->ionic->dev, lif->nxqs, rx_qcqs = devm_kcalloc(lif->ionic->dev, lif->ionic->nrxqs_per_lif,
sizeof(struct ionic_qcq *), GFP_KERNEL); sizeof(struct ionic_qcq *), GFP_KERNEL);
if (!rx_qcqs) if (!rx_qcqs)
goto err_out; goto err_out;
} }
/* allocate new desc_info and rings with no interrupt flag */ /* allocate new desc_info and rings, but leave the interrupt setup
* until later so as to not mess with the still-running queues
*/
if (lif->qtype_info[IONIC_QTYPE_TXQ].version >= 1 && if (lif->qtype_info[IONIC_QTYPE_TXQ].version >= 1 &&
lif->qtype_info[IONIC_QTYPE_TXQ].sg_desc_sz == lif->qtype_info[IONIC_QTYPE_TXQ].sg_desc_sz ==
sizeof(struct ionic_txq_sg_desc_v1)) sizeof(struct ionic_txq_sg_desc_v1))
...@@ -2110,7 +2138,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2110,7 +2138,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
sg_desc_sz = sizeof(struct ionic_txq_sg_desc); sg_desc_sz = sizeof(struct ionic_txq_sg_desc);
if (tx_qcqs) { if (tx_qcqs) {
for (i = 0; i < lif->nxqs; i++) { for (i = 0; i < qparam->nxqs; i++) {
flags = lif->txqcqs[i]->flags & ~IONIC_QCQ_F_INTR; flags = lif->txqcqs[i]->flags & ~IONIC_QCQ_F_INTR;
err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags,
qparam->ntxq_descs, qparam->ntxq_descs,
...@@ -2124,7 +2152,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2124,7 +2152,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
} }
if (rx_qcqs) { if (rx_qcqs) {
for (i = 0; i < lif->nxqs; i++) { for (i = 0; i < qparam->nxqs; i++) {
flags = lif->rxqcqs[i]->flags & ~IONIC_QCQ_F_INTR; flags = lif->rxqcqs[i]->flags & ~IONIC_QCQ_F_INTR;
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
qparam->nrxq_descs, qparam->nrxq_descs,
...@@ -2140,33 +2168,90 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2140,33 +2168,90 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
/* stop and clean the queues */ /* stop and clean the queues */
ionic_stop_queues_reconfig(lif); ionic_stop_queues_reconfig(lif);
if (qparam->nxqs != lif->nxqs) {
err = netif_set_real_num_tx_queues(lif->netdev, qparam->nxqs);
if (err)
goto err_out_reinit_unlock;
err = netif_set_real_num_rx_queues(lif->netdev, qparam->nxqs);
if (err) {
netif_set_real_num_tx_queues(lif->netdev, lif->nxqs);
goto err_out_reinit_unlock;
}
}
/* swap new desc_info and rings, keeping existing interrupt config */ /* swap new desc_info and rings, keeping existing interrupt config */
if (tx_qcqs) { if (tx_qcqs) {
lif->ntxq_descs = qparam->ntxq_descs; lif->ntxq_descs = qparam->ntxq_descs;
for (i = 0; i < lif->nxqs; i++) for (i = 0; i < qparam->nxqs; i++)
ionic_swap_queues(lif->txqcqs[i], tx_qcqs[i]); ionic_swap_queues(lif->txqcqs[i], tx_qcqs[i]);
} }
if (rx_qcqs) { if (rx_qcqs) {
lif->nrxq_descs = qparam->nrxq_descs; lif->nrxq_descs = qparam->nrxq_descs;
for (i = 0; i < lif->nxqs; i++) for (i = 0; i < qparam->nxqs; i++)
ionic_swap_queues(lif->rxqcqs[i], rx_qcqs[i]); ionic_swap_queues(lif->rxqcqs[i], rx_qcqs[i]);
} }
/* re-init the queues */ /* if we need to change the interrupt layout, this is the time */
if (qparam->intr_split != test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state) ||
qparam->nxqs != lif->nxqs) {
if (qparam->intr_split) {
set_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);
} else {
clear_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);
lif->tx_coalesce_usecs = lif->rx_coalesce_usecs;
lif->tx_coalesce_hw = lif->rx_coalesce_hw;
}
/* clear existing interrupt assignments */
for (i = 0; i < lif->ionic->ntxqs_per_lif; i++) {
ionic_qcq_intr_free(lif, lif->txqcqs[i]);
ionic_qcq_intr_free(lif, lif->rxqcqs[i]);
}
/* re-assign the interrupts */
for (i = 0; i < qparam->nxqs; i++) {
lif->rxqcqs[i]->flags |= IONIC_QCQ_F_INTR;
err = ionic_alloc_qcq_interrupt(lif, lif->rxqcqs[i]);
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
lif->rxqcqs[i]->intr.index,
lif->rx_coalesce_hw);
if (qparam->intr_split) {
lif->txqcqs[i]->flags |= IONIC_QCQ_F_INTR;
err = ionic_alloc_qcq_interrupt(lif, lif->txqcqs[i]);
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
lif->txqcqs[i]->intr.index,
lif->tx_coalesce_hw);
} else {
lif->txqcqs[i]->flags &= ~IONIC_QCQ_F_INTR;
ionic_link_qcq_interrupts(lif->rxqcqs[i], lif->txqcqs[i]);
}
}
}
swap(lif->nxqs, qparam->nxqs);
err_out_reinit_unlock:
/* re-init the queues, but don't loose an error code */
if (err)
ionic_start_queues_reconfig(lif);
else
err = ionic_start_queues_reconfig(lif); err = ionic_start_queues_reconfig(lif);
err_out: err_out:
/* free old allocs without cleaning intr */ /* free old allocs without cleaning intr */
for (i = 0; i < lif->nxqs; i++) { for (i = 0; i < qparam->nxqs; i++) {
if (tx_qcqs && tx_qcqs[i]) { if (tx_qcqs && tx_qcqs[i]) {
tx_qcqs[i]->flags &= ~IONIC_QCQ_F_INTR; tx_qcqs[i]->flags &= ~IONIC_QCQ_F_INTR;
ionic_qcq_free(lif, tx_qcqs[i]); ionic_qcq_free(lif, tx_qcqs[i]);
devm_kfree(lif->ionic->dev, tx_qcqs[i]);
tx_qcqs[i] = NULL; tx_qcqs[i] = NULL;
} }
if (rx_qcqs && rx_qcqs[i]) { if (rx_qcqs && rx_qcqs[i]) {
rx_qcqs[i]->flags &= ~IONIC_QCQ_F_INTR; rx_qcqs[i]->flags &= ~IONIC_QCQ_F_INTR;
ionic_qcq_free(lif, rx_qcqs[i]); ionic_qcq_free(lif, rx_qcqs[i]);
devm_kfree(lif->ionic->dev, rx_qcqs[i]);
rx_qcqs[i] = NULL; rx_qcqs[i] = NULL;
} }
} }
...@@ -2181,6 +2266,17 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2181,6 +2266,17 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
tx_qcqs = NULL; tx_qcqs = NULL;
} }
/* clean the unused dma and info allocations when new set is smaller
* than the full array, but leave the qcq shells in place
*/
for (i = lif->nxqs; i < lif->ionic->ntxqs_per_lif; i++) {
lif->txqcqs[i]->flags &= ~IONIC_QCQ_F_INTR;
ionic_qcq_free(lif, lif->txqcqs[i]);
lif->rxqcqs[i]->flags &= ~IONIC_QCQ_F_INTR;
ionic_qcq_free(lif, lif->rxqcqs[i]);
}
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment