static int mlxsw_pci_eq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, struct mlxsw_pci_queue *q) { int i; int err; q->consumer_counter = 0; for (i = 0; i < q->count; i++) { char *elem = mlxsw_pci_queue_elem_get(q, i); mlxsw_pci_eqe_owner_set(elem, 1); } mlxsw_cmd_mbox_sw2hw_eq_int_msix_set(mbox, 1); /* MSI-X used */ mlxsw_cmd_mbox_sw2hw_eq_oi_set(mbox, 0); mlxsw_cmd_mbox_sw2hw_eq_st_set(mbox, 1); /* armed */ mlxsw_cmd_mbox_sw2hw_eq_log_eq_size_set(mbox, ilog2(q->count)); for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) { dma_addr_t mapaddr = __mlxsw_pci_queue_page_get(q, i); mlxsw_cmd_mbox_sw2hw_eq_pa_set(mbox, i, mapaddr); } err = mlxsw_cmd_sw2hw_eq(mlxsw_pci->core, mbox, q->num); if (err) return err; mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q); mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q); return 0; }
static int mlxsw_pci_sdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, struct mlxsw_pci_queue *q) { int i; int err; q->producer_counter = 0; q->consumer_counter = 0; /* Set CQ of same number of this SDQ. */ mlxsw_cmd_mbox_sw2hw_dq_cq_set(mbox, q->num); mlxsw_cmd_mbox_sw2hw_dq_sdq_tclass_set(mbox, 7); mlxsw_cmd_mbox_sw2hw_dq_log2_dq_sz_set(mbox, 3); /* 8 pages */ for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) { dma_addr_t mapaddr = __mlxsw_pci_queue_page_get(q, i); mlxsw_cmd_mbox_sw2hw_dq_pa_set(mbox, i, mapaddr); } err = mlxsw_cmd_sw2hw_sdq(mlxsw_pci->core, mbox, q->num); if (err) return err; mlxsw_pci_queue_doorbell_producer_ring(mlxsw_pci, q); return 0; }
static int mlxsw_pci_rdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, struct mlxsw_pci_queue *q) { struct mlxsw_pci_queue_elem_info *elem_info; u8 sdq_count = mlxsw_pci_sdq_count(mlxsw_pci); int i; int err; q->producer_counter = 0; q->consumer_counter = 0; /* Set CQ of same number of this RDQ with base * above SDQ count as the lower ones are assigned to SDQs. */ mlxsw_cmd_mbox_sw2hw_dq_cq_set(mbox, sdq_count + q->num); mlxsw_cmd_mbox_sw2hw_dq_log2_dq_sz_set(mbox, 3); /* 8 pages */ for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) { dma_addr_t mapaddr = __mlxsw_pci_queue_page_get(q, i); mlxsw_cmd_mbox_sw2hw_dq_pa_set(mbox, i, mapaddr); } err = mlxsw_cmd_sw2hw_rdq(mlxsw_pci->core, mbox, q->num); if (err) return err; mlxsw_pci_queue_doorbell_producer_ring(mlxsw_pci, q); for (i = 0; i < q->count; i++) { elem_info = mlxsw_pci_queue_elem_info_producer_get(q); BUG_ON(!elem_info); err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info); if (err) goto rollback; /* Everything is set up, ring doorbell to pass elem to HW */ q->producer_counter++; mlxsw_pci_queue_doorbell_producer_ring(mlxsw_pci, q); } return 0; rollback: for (i--; i >= 0; i--) { elem_info = mlxsw_pci_queue_elem_info_get(q, i); mlxsw_pci_rdq_skb_free(mlxsw_pci, elem_info); } mlxsw_cmd_hw2sw_rdq(mlxsw_pci->core, q->num); return err; }
static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, struct mlxsw_pci_queue *q) { int i; int err; q->consumer_counter = 0; for (i = 0; i < q->count; i++) { char *elem = mlxsw_pci_queue_elem_get(q, i); mlxsw_pci_cqe_owner_set(q->u.cq.v, elem, 1); } if (q->u.cq.v == MLXSW_PCI_CQE_V1) mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox, MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1); else if (q->u.cq.v == MLXSW_PCI_CQE_V2) mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox, MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2); mlxsw_cmd_mbox_sw2hw_cq_c_eqn_set(mbox, MLXSW_PCI_EQ_COMP_NUM); mlxsw_cmd_mbox_sw2hw_cq_st_set(mbox, 0); mlxsw_cmd_mbox_sw2hw_cq_log_cq_size_set(mbox, ilog2(q->count)); for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) { dma_addr_t mapaddr = __mlxsw_pci_queue_page_get(q, i); mlxsw_cmd_mbox_sw2hw_cq_pa_set(mbox, i, mapaddr); } err = mlxsw_cmd_sw2hw_cq(mlxsw_pci->core, mbox, q->num); if (err) return err; mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q); mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q); return 0; }