ionic: remove the cq_info to save more memory

With a little simple math we don't need another struct array to
find the completion structs, so we can remove the ionic_cq_info
altogether.  This doesn't really save anything in the ionic_cq
since it gets padded out to the cacheline, but it does remove
the parallel array allocation of 8 * num_descriptors, or about
8 Kbytes per queue in a default configuration.

Suggested-by: Neel Patel <npatel2@amd.com>
Reviewed-by: Brett Creeley <brett.creeley@amd.com>
Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Shannon Nelson 2024-03-06 15:29:50 -08:00 committed by David S. Miller
parent ae24a8f88b
commit 65e548f6b0
7 changed files with 38 additions and 89 deletions

View file

@ -76,8 +76,8 @@ int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);
int ionic_adminq_post_wait_nomsg(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);
void ionic_adminq_netdev_err_print(struct ionic_lif *lif, u8 opcode,
u8 status, int err);
bool ionic_notifyq_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info);
bool ionic_adminq_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info);
bool ionic_notifyq_service(struct ionic_cq *cq);
bool ionic_adminq_service(struct ionic_cq *cq);
int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_wait);
int ionic_dev_cmd_wait_nomsg(struct ionic *ionic, unsigned long max_wait);

View file

@ -633,39 +633,20 @@ int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
return 0;
}
void ionic_cq_map(struct ionic_cq *cq, void *base, dma_addr_t base_pa)
{
struct ionic_cq_info *cur;
unsigned int i;
cq->base = base;
cq->base_pa = base_pa;
for (i = 0, cur = cq->info; i < cq->num_descs; i++, cur++)
cur->cq_desc = base + (i * cq->desc_size);
}
void ionic_cq_bind(struct ionic_cq *cq, struct ionic_queue *q)
{
cq->bound_q = q;
}
unsigned int ionic_cq_service(struct ionic_cq *cq, unsigned int work_to_do,
ionic_cq_cb cb, ionic_cq_done_cb done_cb,
void *done_arg)
{
struct ionic_cq_info *cq_info;
unsigned int work_done = 0;
if (work_to_do == 0)
return 0;
cq_info = &cq->info[cq->tail_idx];
while (cb(cq, cq_info)) {
while (cb(cq)) {
if (cq->tail_idx == cq->num_descs - 1)
cq->done_color = !cq->done_color;
cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1);
cq_info = &cq->info[cq->tail_idx];
if (++work_done >= work_to_do)
break;

View file

@ -177,14 +177,6 @@ struct ionic_dev {
struct ionic_devinfo dev_info;
};
struct ionic_cq_info {
union {
void *cq_desc;
struct ionic_admin_comp *admincq;
struct ionic_notifyq_event *notifyq;
};
};
struct ionic_queue;
struct ionic_qcq;
struct ionic_desc_info;
@ -282,7 +274,6 @@ struct ionic_intr_info {
struct ionic_cq {
struct ionic_lif *lif;
struct ionic_cq_info *info;
struct ionic_queue *bound_q;
struct ionic_intr_info *bound_intr;
u16 tail_idx;
@ -365,7 +356,7 @@ int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
unsigned int num_descs, size_t desc_size);
void ionic_cq_map(struct ionic_cq *cq, void *base, dma_addr_t base_pa);
void ionic_cq_bind(struct ionic_cq *cq, struct ionic_queue *q);
typedef bool (*ionic_cq_cb)(struct ionic_cq *cq, struct ionic_cq_info *cq_info);
typedef bool (*ionic_cq_cb)(struct ionic_cq *cq);
typedef void (*ionic_cq_done_cb)(void *done_arg);
unsigned int ionic_cq_service(struct ionic_cq *cq, unsigned int work_to_do,
ionic_cq_cb cb, ionic_cq_done_cb done_cb,

View file

@ -433,8 +433,6 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
ionic_xdp_unregister_rxq_info(&qcq->q);
ionic_qcq_intr_free(lif, qcq);
vfree(qcq->cq.info);
qcq->cq.info = NULL;
vfree(qcq->q.info);
qcq->q.info = NULL;
}
@ -542,9 +540,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
{
struct ionic_dev *idev = &lif->ionic->idev;
struct device *dev = lif->ionic->dev;
dma_addr_t cq_base_pa = 0;
struct ionic_qcq *new;
void *cq_base;
int err;
*qcq = NULL;
@ -578,19 +574,12 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
err = ionic_alloc_qcq_interrupt(lif, new);
if (err)
goto err_out;
new->cq.info = vcalloc(num_descs, sizeof(*new->cq.info));
if (!new->cq.info) {
netdev_err(lif->netdev, "Cannot allocate completion queue info\n");
err = -ENOMEM;
goto err_out_free_irq;
}
goto err_out_free_q_info;
err = ionic_cq_init(lif, &new->cq, &new->intr, num_descs, cq_desc_size);
if (err) {
netdev_err(lif->netdev, "Cannot initialize completion queue\n");
goto err_out_free_cq_info;
goto err_out_free_irq;
}
if (flags & IONIC_QCQ_F_NOTIFYQ) {
@ -608,15 +597,15 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
if (!new->q_base) {
netdev_err(lif->netdev, "Cannot allocate qcq DMA memory\n");
err = -ENOMEM;
goto err_out_free_cq_info;
goto err_out_free_irq;
}
new->q.base = PTR_ALIGN(new->q_base, PAGE_SIZE);
new->q.base_pa = ALIGN(new->q_base_pa, PAGE_SIZE);
cq_base = PTR_ALIGN(new->q_base + q_size, PAGE_SIZE);
cq_base_pa = ALIGN(new->q_base_pa + q_size, PAGE_SIZE);
ionic_cq_map(&new->cq, cq_base, cq_base_pa);
ionic_cq_bind(&new->cq, &new->q);
/* Base the NotifyQ cq.base off of the ALIGNed q.base */
new->cq.base = PTR_ALIGN(new->q.base + q_size, PAGE_SIZE);
new->cq.base_pa = ALIGN(new->q_base_pa + q_size, PAGE_SIZE);
new->cq.bound_q = &new->q;
} else {
/* regular DMA q descriptors */
new->q_size = PAGE_SIZE + (num_descs * desc_size);
@ -625,7 +614,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
if (!new->q_base) {
netdev_err(lif->netdev, "Cannot allocate queue DMA memory\n");
err = -ENOMEM;
goto err_out_free_cq_info;
goto err_out_free_irq;
}
new->q.base = PTR_ALIGN(new->q_base, PAGE_SIZE);
new->q.base_pa = ALIGN(new->q_base_pa, PAGE_SIZE);
@ -666,10 +655,9 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
err = -ENOMEM;
goto err_out_free_q;
}
cq_base = PTR_ALIGN(new->cq_base, PAGE_SIZE);
cq_base_pa = ALIGN(new->cq_base_pa, PAGE_SIZE);
ionic_cq_map(&new->cq, cq_base, cq_base_pa);
ionic_cq_bind(&new->cq, &new->q);
new->cq.base = PTR_ALIGN(new->cq_base, PAGE_SIZE);
new->cq.base_pa = ALIGN(new->cq_base_pa, PAGE_SIZE);
new->cq.bound_q = &new->q;
}
if (flags & IONIC_QCQ_F_SG) {
@ -700,8 +688,6 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
ionic_put_cmb(lif, new->cmb_pgid, new->cmb_order);
}
dma_free_coherent(dev, new->q_size, new->q_base, new->q_base_pa);
err_out_free_cq_info:
vfree(new->cq.info);
err_out_free_irq:
if (flags & IONIC_QCQ_F_INTR) {
devm_free_irq(dev, new->intr.vector, &new->napi);
@ -2889,7 +2875,6 @@ static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b)
swap(a->cq.desc_size, b->cq.desc_size);
swap(a->cq.base, b->cq.base);
swap(a->cq.base_pa, b->cq.base_pa);
swap(a->cq.info, b->cq.info);
swap(a->cq_base, b->cq_base);
swap(a->cq_base_pa, b->cq_base_pa);
swap(a->cq_size, b->cq_size);

View file

@ -249,16 +249,13 @@ static int ionic_adminq_check_err(struct ionic_lif *lif,
static void ionic_adminq_clean(struct ionic_queue *q,
struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info)
struct ionic_admin_comp *comp)
{
struct ionic_admin_ctx *ctx = desc_info->arg;
struct ionic_admin_comp *comp;
if (!ctx)
return;
comp = cq_info->cq_desc;
memcpy(&ctx->comp, comp, sizeof(*comp));
dev_dbg(q->dev, "comp admin queue command:\n");
@ -268,16 +265,17 @@ static void ionic_adminq_clean(struct ionic_queue *q,
complete_all(&ctx->work);
}
bool ionic_notifyq_service(struct ionic_cq *cq,
struct ionic_cq_info *cq_info)
bool ionic_notifyq_service(struct ionic_cq *cq)
{
union ionic_notifyq_comp *comp = cq_info->cq_desc;
struct ionic_deferred_work *work;
union ionic_notifyq_comp *comp;
struct net_device *netdev;
struct ionic_queue *q;
struct ionic_lif *lif;
u64 eid;
comp = &((union ionic_notifyq_comp *)cq->base)[cq->tail_idx];
q = cq->bound_q;
lif = q->info[0].arg;
netdev = lif->netdev;
@ -320,14 +318,14 @@ bool ionic_notifyq_service(struct ionic_cq *cq,
return true;
}
bool ionic_adminq_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
bool ionic_adminq_service(struct ionic_cq *cq)
{
struct ionic_queue *q = cq->bound_q;
struct ionic_desc_info *desc_info;
struct ionic_admin_comp *comp;
u16 index;
comp = cq_info->cq_desc;
comp = &((struct ionic_admin_comp *)cq->base)[cq->tail_idx];
if (!color_match(comp->color, cq->done_color))
return false;
@ -341,7 +339,7 @@ bool ionic_adminq_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
index = q->tail_idx;
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
if (likely(desc_info->arg))
ionic_adminq_clean(q, desc_info, cq_info);
ionic_adminq_clean(q, desc_info, comp);
desc_info->arg = NULL;
} while (index != le16_to_cpu(comp->comp_index));

View file

@ -23,7 +23,7 @@ static void ionic_tx_desc_unmap_bufs(struct ionic_queue *q,
static void ionic_tx_clean(struct ionic_queue *q,
struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info);
struct ionic_txq_comp *comp);
static inline void ionic_txq_post(struct ionic_queue *q, bool ring_dbell,
void *arg)
@ -635,19 +635,16 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
static void ionic_rx_clean(struct ionic_queue *q,
struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info)
struct ionic_rxq_comp *comp)
{
struct net_device *netdev = q->lif->netdev;
struct ionic_qcq *qcq = q_to_qcq(q);
struct ionic_rx_stats *stats;
struct ionic_rxq_comp *comp;
struct bpf_prog *xdp_prog;
unsigned int headroom;
struct sk_buff *skb;
u16 len;
comp = cq_info->cq_desc + qcq->cq.desc_size - sizeof(*comp);
stats = q_to_rx_stats(q);
if (comp->status) {
@ -722,7 +719,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
u64 hwstamp;
cq_desc_hwstamp =
cq_info->cq_desc +
(void *)comp +
qcq->cq.desc_size -
sizeof(struct ionic_rxq_comp) -
IONIC_HWSTAMP_CQ_NEGOFFSET;
@ -743,13 +740,13 @@ static void ionic_rx_clean(struct ionic_queue *q,
napi_gro_frags(&qcq->napi);
}
bool ionic_rx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
bool ionic_rx_service(struct ionic_cq *cq)
{
struct ionic_queue *q = cq->bound_q;
struct ionic_desc_info *desc_info;
struct ionic_rxq_comp *comp;
comp = cq_info->cq_desc + cq->desc_size - sizeof(*comp);
comp = &((struct ionic_rxq_comp *)cq->base)[cq->tail_idx];
if (!color_match(comp->pkt_type_color, cq->done_color))
return false;
@ -765,7 +762,7 @@ bool ionic_rx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
/* clean the related q entry, only one per qc completion */
ionic_rx_clean(q, desc_info, cq_info);
ionic_rx_clean(q, desc_info, comp);
desc_info->arg = NULL;
@ -1181,7 +1178,7 @@ static void ionic_tx_desc_unmap_bufs(struct ionic_queue *q,
static void ionic_tx_clean(struct ionic_queue *q,
struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info)
struct ionic_txq_comp *comp)
{
struct ionic_tx_stats *stats = q_to_tx_stats(q);
struct ionic_qcq *qcq = q_to_qcq(q);
@ -1204,13 +1201,13 @@ static void ionic_tx_clean(struct ionic_queue *q,
return;
if (unlikely(ionic_txq_hwstamp_enabled(q))) {
if (cq_info) {
if (comp) {
struct skb_shared_hwtstamps hwts = {};
__le64 *cq_desc_hwstamp;
u64 hwstamp;
cq_desc_hwstamp =
cq_info->cq_desc +
(void *)comp +
qcq->cq.desc_size -
sizeof(struct ionic_txq_comp) -
IONIC_HWSTAMP_CQ_NEGOFFSET;
@ -1236,7 +1233,7 @@ static void ionic_tx_clean(struct ionic_queue *q,
napi_consume_skb(skb, 1);
}
static bool ionic_tx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info,
static bool ionic_tx_service(struct ionic_cq *cq,
unsigned int *total_pkts, unsigned int *total_bytes)
{
struct ionic_queue *q = cq->bound_q;
@ -1246,7 +1243,7 @@ static bool ionic_tx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info,
unsigned int pkts = 0;
u16 index;
comp = cq_info->cq_desc + cq->desc_size - sizeof(*comp);
comp = &((struct ionic_txq_comp *)cq->base)[cq->tail_idx];
if (!color_match(comp->color, cq->done_color))
return false;
@ -1259,7 +1256,7 @@ static bool ionic_tx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info,
desc_info->bytes = 0;
index = q->tail_idx;
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
ionic_tx_clean(q, desc_info, cq_info);
ionic_tx_clean(q, desc_info, comp);
if (desc_info->arg) {
pkts++;
bytes += desc_info->bytes;
@ -1275,7 +1272,6 @@ static bool ionic_tx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info,
unsigned int ionic_tx_cq_service(struct ionic_cq *cq, unsigned int work_to_do)
{
struct ionic_cq_info *cq_info;
unsigned int work_done = 0;
unsigned int bytes = 0;
unsigned int pkts = 0;
@ -1283,12 +1279,10 @@ unsigned int ionic_tx_cq_service(struct ionic_cq *cq, unsigned int work_to_do)
if (work_to_do == 0)
return 0;
cq_info = &cq->info[cq->tail_idx];
while (ionic_tx_service(cq, cq_info, &pkts, &bytes)) {
while (ionic_tx_service(cq, &pkts, &bytes)) {
if (cq->tail_idx == cq->num_descs - 1)
cq->done_color = !cq->done_color;
cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1);
cq_info = &cq->info[cq->tail_idx];
if (++work_done >= work_to_do)
break;

View file

@ -14,7 +14,7 @@ int ionic_tx_napi(struct napi_struct *napi, int budget);
int ionic_txrx_napi(struct napi_struct *napi, int budget);
netdev_tx_t ionic_start_xmit(struct sk_buff *skb, struct net_device *netdev);
bool ionic_rx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info);
bool ionic_rx_service(struct ionic_cq *cq);
int ionic_xdp_xmit(struct net_device *netdev, int n, struct xdp_frame **xdp, u32 flags);
#endif /* _IONIC_TXRX_H_ */