static void mlxsw_pci_eq_tasklet(unsigned long data) { struct mlxsw_pci_queue *q = (struct mlxsw_pci_queue *) data; struct mlxsw_pci *mlxsw_pci = q->pci; u8 cq_count = mlxsw_pci_cq_count(mlxsw_pci); unsigned long active_cqns[BITS_TO_LONGS(MLXSW_PCI_CQS_MAX)]; char *eqe; u8 cqn; bool cq_handle = false; int items = 0; int credits = q->count >> 1; memset(&active_cqns, 0, sizeof(active_cqns)); while ((eqe = mlxsw_pci_eq_sw_eqe_get(q))) { /* Command interface completion events are always received on * queue MLXSW_PCI_EQ_ASYNC_NUM (EQ0) and completion events * are mapped to queue MLXSW_PCI_EQ_COMP_NUM (EQ1). */ switch (q->num) { case MLXSW_PCI_EQ_ASYNC_NUM: mlxsw_pci_eq_cmd_event(mlxsw_pci, eqe); q->u.eq.ev_cmd_count++; break; case MLXSW_PCI_EQ_COMP_NUM: cqn = mlxsw_pci_eqe_cqn_get(eqe); set_bit(cqn, active_cqns); cq_handle = true; q->u.eq.ev_comp_count++; break; default: q->u.eq.ev_other_count++; } if (++items == credits) break; } if (items) { mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q); mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q); } if (!cq_handle) return; for_each_set_bit(cqn, active_cqns, cq_count) { q = mlxsw_pci_cq_get(mlxsw_pci, cqn); mlxsw_pci_queue_tasklet_schedule(q); }
static void mlxsw_pci_eq_tasklet(unsigned long data) { struct mlxsw_pci_queue *q = (struct mlxsw_pci_queue *) data; struct mlxsw_pci *mlxsw_pci = q->pci; u8 cq_count = mlxsw_pci_cq_count(mlxsw_pci); unsigned long active_cqns[BITS_TO_LONGS(MLXSW_PCI_CQS_MAX)]; char *eqe; u8 cqn; bool cq_handle = false; int items = 0; int credits = q->count >> 1; memset(&active_cqns, 0, sizeof(active_cqns)); while ((eqe = mlxsw_pci_eq_sw_eqe_get(q))) { u8 event_type = mlxsw_pci_eqe_event_type_get(eqe); switch (event_type) { case MLXSW_PCI_EQE_EVENT_TYPE_CMD: mlxsw_pci_eq_cmd_event(mlxsw_pci, eqe); q->u.eq.ev_cmd_count++; break; case MLXSW_PCI_EQE_EVENT_TYPE_COMP: cqn = mlxsw_pci_eqe_cqn_get(eqe); set_bit(cqn, active_cqns); cq_handle = true; q->u.eq.ev_comp_count++; break; default: q->u.eq.ev_other_count++; } if (++items == credits) break; } if (items) { mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q); mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q); } if (!cq_handle) return; for_each_set_bit(cqn, active_cqns, cq_count) { q = mlxsw_pci_cq_get(mlxsw_pci, cqn); mlxsw_pci_queue_tasklet_schedule(q); }
static int mlxsw_pci_cq_dbg_read(struct seq_file *file, void *data) { struct mlxsw_pci *mlxsw_pci = dev_get_drvdata(file->private); struct mlxsw_pci_queue *q; int i; static const char hdr[] = "NUM CONS_INDEX SDQ_COUNT RDQ_COUNT COUNT\n"; seq_printf(file, hdr); for (i = 0; i < mlxsw_pci_cq_count(mlxsw_pci); i++) { q = mlxsw_pci_cq_get(mlxsw_pci, i); spin_lock_bh(&q->lock); seq_printf(file, "%3d %10d %10d %10d %5d\n", i, q->consumer_counter, q->u.cq.comp_sdq_count, q->u.cq.comp_rdq_count, q->count); spin_unlock_bh(&q->lock); } return 0; }