Skip to content

Commit 77ceb68

Browse files
emuslndavem330
authored andcommitted
ionic: Add notifyq support
The AdminQ is fine for sending messages and requests to the NIC, but we also need to have events published from the NIC to the driver. The NotifyQ handles this for us, using the same interrupt as AdminQ. Signed-off-by: Shannon Nelson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 938962d commit 77ceb68

File tree

3 files changed

+186
-2
lines changed

3 files changed

+186
-2
lines changed

drivers/net/ethernet/pensando/ionic/ionic_debugfs.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ static const struct debugfs_reg32 intr_ctrl_regs[] = {
112112

113113
void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq)
114114
{
115-
struct dentry *q_dentry, *cq_dentry, *intr_dentry;
115+
struct dentry *q_dentry, *cq_dentry, *intr_dentry, *stats_dentry;
116116
struct ionic_dev *idev = &lif->ionic->idev;
117117
struct debugfs_regset32 *intr_ctrl_regset;
118118
struct ionic_intr_info *intr = &qcq->intr;
@@ -201,6 +201,19 @@ void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq)
201201
debugfs_create_regset32("intr_ctrl", 0400, intr_dentry,
202202
intr_ctrl_regset);
203203
}
204+
205+
if (qcq->flags & IONIC_QCQ_F_NOTIFYQ) {
206+
stats_dentry = debugfs_create_dir("notifyblock", qcq->dentry);
207+
208+
debugfs_create_u64("eid", 0400, stats_dentry,
209+
(u64 *)&lif->info->status.eid);
210+
debugfs_create_u16("link_status", 0400, stats_dentry,
211+
(u16 *)&lif->info->status.link_status);
212+
debugfs_create_u32("link_speed", 0400, stats_dentry,
213+
(u32 *)&lif->info->status.link_speed);
214+
debugfs_create_u16("link_down_count", 0400, stats_dentry,
215+
(u16 *)&lif->info->status.link_down_count);
216+
}
204217
}
205218

206219
static int netdev_show(struct seq_file *seq, void *v)

drivers/net/ethernet/pensando/ionic/ionic_lif.c

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,29 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
110110

111111
static void ionic_qcqs_free(struct ionic_lif *lif)
112112
{
113+
if (lif->notifyqcq) {
114+
ionic_qcq_free(lif, lif->notifyqcq);
115+
lif->notifyqcq = NULL;
116+
}
117+
113118
if (lif->adminqcq) {
114119
ionic_qcq_free(lif, lif->adminqcq);
115120
lif->adminqcq = NULL;
116121
}
117122
}
118123

124+
static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
125+
struct ionic_qcq *n_qcq)
126+
{
127+
if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) {
128+
ionic_intr_free(n_qcq->cq.lif, n_qcq->intr.index);
129+
n_qcq->flags &= ~IONIC_QCQ_F_INTR;
130+
}
131+
132+
n_qcq->intr.vector = src_qcq->intr.vector;
133+
n_qcq->intr.index = src_qcq->intr.index;
134+
}
135+
119136
static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
120137
unsigned int index,
121138
const char *name, unsigned int flags,
@@ -269,7 +286,91 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
269286
if (err)
270287
return err;
271288

289+
if (lif->ionic->nnqs_per_lif) {
290+
flags = IONIC_QCQ_F_NOTIFYQ;
291+
err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notifyq",
292+
flags, IONIC_NOTIFYQ_LENGTH,
293+
sizeof(struct ionic_notifyq_cmd),
294+
sizeof(union ionic_notifyq_comp),
295+
0, lif->kern_pid, &lif->notifyqcq);
296+
if (err)
297+
goto err_out_free_adminqcq;
298+
299+
/* Let the notifyq ride on the adminq interrupt */
300+
ionic_link_qcq_interrupts(lif->adminqcq, lif->notifyqcq);
301+
}
302+
272303
return 0;
304+
305+
err_out_free_adminqcq:
306+
ionic_qcq_free(lif, lif->adminqcq);
307+
lif->adminqcq = NULL;
308+
309+
return err;
310+
}
311+
312+
static bool ionic_notifyq_service(struct ionic_cq *cq,
313+
struct ionic_cq_info *cq_info)
314+
{
315+
union ionic_notifyq_comp *comp = cq_info->cq_desc;
316+
struct net_device *netdev;
317+
struct ionic_queue *q;
318+
struct ionic_lif *lif;
319+
u64 eid;
320+
321+
q = cq->bound_q;
322+
lif = q->info[0].cb_arg;
323+
netdev = lif->netdev;
324+
eid = le64_to_cpu(comp->event.eid);
325+
326+
/* Have we run out of new completions to process? */
327+
if (eid <= lif->last_eid)
328+
return false;
329+
330+
lif->last_eid = eid;
331+
332+
dev_dbg(lif->ionic->dev, "notifyq event:\n");
333+
dynamic_hex_dump("event ", DUMP_PREFIX_OFFSET, 16, 1,
334+
comp, sizeof(*comp), true);
335+
336+
switch (le16_to_cpu(comp->event.ecode)) {
337+
case IONIC_EVENT_LINK_CHANGE:
338+
netdev_info(netdev, "Notifyq IONIC_EVENT_LINK_CHANGE eid=%lld\n",
339+
eid);
340+
netdev_info(netdev,
341+
" link_status=%d link_speed=%d\n",
342+
le16_to_cpu(comp->link_change.link_status),
343+
le32_to_cpu(comp->link_change.link_speed));
344+
break;
345+
case IONIC_EVENT_RESET:
346+
netdev_info(netdev, "Notifyq IONIC_EVENT_RESET eid=%lld\n",
347+
eid);
348+
netdev_info(netdev, " reset_code=%d state=%d\n",
349+
comp->reset.reset_code,
350+
comp->reset.state);
351+
break;
352+
default:
353+
netdev_warn(netdev, "Notifyq unknown event ecode=%d eid=%lld\n",
354+
comp->event.ecode, eid);
355+
break;
356+
}
357+
358+
return true;
359+
}
360+
361+
static int ionic_notifyq_clean(struct ionic_lif *lif, int budget)
362+
{
363+
struct ionic_dev *idev = &lif->ionic->idev;
364+
struct ionic_cq *cq = &lif->notifyqcq->cq;
365+
u32 work_done;
366+
367+
work_done = ionic_cq_service(cq, budget, ionic_notifyq_service,
368+
NULL, NULL);
369+
if (work_done)
370+
ionic_intr_credits(idev->intr_ctrl, cq->bound_intr->index,
371+
work_done, IONIC_INTR_CRED_RESET_COALESCE);
372+
373+
return work_done;
273374
}
274375

275376
static bool ionic_adminq_service(struct ionic_cq *cq,
@@ -287,7 +388,15 @@ static bool ionic_adminq_service(struct ionic_cq *cq,
287388

288389
static int ionic_adminq_napi(struct napi_struct *napi, int budget)
289390
{
290-
return ionic_napi(napi, budget, ionic_adminq_service, NULL, NULL);
391+
struct ionic_lif *lif = napi_to_cq(napi)->lif;
392+
int n_work = 0;
393+
int a_work = 0;
394+
395+
if (likely(lif->notifyqcq && lif->notifyqcq->flags & IONIC_QCQ_F_INITED))
396+
n_work = ionic_notifyq_clean(lif, budget);
397+
a_work = ionic_napi(napi, budget, ionic_adminq_service, NULL, NULL);
398+
399+
return max(n_work, a_work);
291400
}
292401

293402
static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index)
@@ -417,6 +526,7 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
417526
clear_bit(IONIC_LIF_INITED, lif->state);
418527

419528
napi_disable(&lif->adminqcq->napi);
529+
ionic_lif_qcq_deinit(lif, lif->notifyqcq);
420530
ionic_lif_qcq_deinit(lif, lif->adminqcq);
421531

422532
ionic_lif_reset(lif);
@@ -486,6 +596,55 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif)
486596
return 0;
487597
}
488598

599+
static int ionic_lif_notifyq_init(struct ionic_lif *lif)
600+
{
601+
struct ionic_qcq *qcq = lif->notifyqcq;
602+
struct device *dev = lif->ionic->dev;
603+
struct ionic_queue *q = &qcq->q;
604+
int err;
605+
606+
struct ionic_admin_ctx ctx = {
607+
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
608+
.cmd.q_init = {
609+
.opcode = IONIC_CMD_Q_INIT,
610+
.lif_index = cpu_to_le16(lif->index),
611+
.type = q->type,
612+
.index = cpu_to_le32(q->index),
613+
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
614+
IONIC_QINIT_F_ENA),
615+
.intr_index = cpu_to_le16(lif->adminqcq->intr.index),
616+
.pid = cpu_to_le16(q->pid),
617+
.ring_size = ilog2(q->num_descs),
618+
.ring_base = cpu_to_le64(q->base_pa),
619+
}
620+
};
621+
622+
dev_dbg(dev, "notifyq_init.pid %d\n", ctx.cmd.q_init.pid);
623+
dev_dbg(dev, "notifyq_init.index %d\n", ctx.cmd.q_init.index);
624+
dev_dbg(dev, "notifyq_init.ring_base 0x%llx\n", ctx.cmd.q_init.ring_base);
625+
dev_dbg(dev, "notifyq_init.ring_size %d\n", ctx.cmd.q_init.ring_size);
626+
627+
err = ionic_adminq_post_wait(lif, &ctx);
628+
if (err)
629+
return err;
630+
631+
q->hw_type = ctx.comp.q_init.hw_type;
632+
q->hw_index = le32_to_cpu(ctx.comp.q_init.hw_index);
633+
q->dbval = IONIC_DBELL_QID(q->hw_index);
634+
635+
dev_dbg(dev, "notifyq->hw_type %d\n", q->hw_type);
636+
dev_dbg(dev, "notifyq->hw_index %d\n", q->hw_index);
637+
638+
/* preset the callback info */
639+
q->info[0].cb_arg = lif;
640+
641+
qcq->flags |= IONIC_QCQ_F_INITED;
642+
643+
ionic_debugfs_add_qcq(lif, qcq);
644+
645+
return 0;
646+
}
647+
489648
static int ionic_lif_init(struct ionic_lif *lif)
490649
{
491650
struct ionic_dev *idev = &lif->ionic->idev;
@@ -535,10 +694,18 @@ static int ionic_lif_init(struct ionic_lif *lif)
535694
if (err)
536695
goto err_out_adminq_deinit;
537696

697+
if (lif->ionic->nnqs_per_lif) {
698+
err = ionic_lif_notifyq_init(lif);
699+
if (err)
700+
goto err_out_notifyq_deinit;
701+
}
702+
538703
set_bit(IONIC_LIF_INITED, lif->state);
539704

540705
return 0;
541706

707+
err_out_notifyq_deinit:
708+
ionic_lif_qcq_deinit(lif, lif->notifyqcq);
542709
err_out_adminq_deinit:
543710
ionic_lif_qcq_deinit(lif, lif->adminqcq);
544711
ionic_lif_reset(lif);

drivers/net/ethernet/pensando/ionic/ionic_lif.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/pci.h>
88

99
#define IONIC_ADMINQ_LENGTH 16 /* must be a power of two */
10+
#define IONIC_NOTIFYQ_LENGTH 64 /* must be a power of two */
1011

1112
#define IONIC_MAX_NUM_NAPI_CNTR (NAPI_POLL_WEIGHT + 1)
1213
#define IONIC_MAX_NUM_SG_CNTR (IONIC_TX_MAX_SG_ELEMS + 1)
@@ -24,6 +25,7 @@ struct ionic_rx_stats {
2425
#define IONIC_QCQ_F_INITED BIT(0)
2526
#define IONIC_QCQ_F_SG BIT(1)
2627
#define IONIC_QCQ_F_INTR BIT(2)
28+
#define IONIC_QCQ_F_NOTIFYQ BIT(5)
2729

2830
struct ionic_napi_stats {
2931
u64 poll_count;
@@ -76,6 +78,8 @@ struct ionic_lif {
7678
u64 __iomem *kern_dbpage;
7779
spinlock_t adminq_lock; /* lock for AdminQ operations */
7880
struct ionic_qcq *adminqcq;
81+
struct ionic_qcq *notifyqcq;
82+
u64 last_eid;
7983
unsigned int neqs;
8084
unsigned int nxqs;
8185

0 commit comments

Comments
 (0)