/** * hinic_aeq_register_hw_cb - register AEQ callback for specific event * @aeqs: pointer to Async eqs of the chip * @event: aeq event to register callback for it * @handle: private data will be used by the callback * @hwe_handler: callback function
**/ void hinic_aeq_register_hw_cb(struct hinic_aeqs *aeqs, enum hinic_aeq_type event, void *handle, void (*hwe_handler)(void *handle, void *data,
u8 size))
{ struct hinic_hw_event_cb *hwe_cb = &aeqs->hwe_cb[event];
/** * hinic_aeq_unregister_hw_cb - unregister the AEQ callback for specific event * @aeqs: pointer to Async eqs of the chip * @event: aeq event to unregister callback for it
**/ void hinic_aeq_unregister_hw_cb(struct hinic_aeqs *aeqs, enum hinic_aeq_type event)
{ struct hinic_hw_event_cb *hwe_cb = &aeqs->hwe_cb[event];
hwe_cb->hwe_state &= ~HINIC_EQE_ENABLED;
while (hwe_cb->hwe_state & HINIC_EQE_RUNNING)
schedule();
hwe_cb->hwe_handler = NULL;
}
/** * hinic_ceq_register_cb - register CEQ callback for specific event * @ceqs: pointer to Completion eqs part of the chip * @event: ceq event to register callback for it * @handle: private data will be used by the callback * @handler: callback function
**/ void hinic_ceq_register_cb(struct hinic_ceqs *ceqs, enum hinic_ceq_type event, void *handle, void (*handler)(void *handle, u32 ceqe_data))
{ struct hinic_ceq_cb *ceq_cb = &ceqs->ceq_cb[event];
/** * hinic_ceq_unregister_cb - unregister the CEQ callback for specific event * @ceqs: pointer to Completion eqs part of the chip * @event: ceq event to unregister callback for it
**/ void hinic_ceq_unregister_cb(struct hinic_ceqs *ceqs, enum hinic_ceq_type event)
{ struct hinic_ceq_cb *ceq_cb = &ceqs->ceq_cb[event];
ceq_cb->ceqe_state &= ~HINIC_EQE_ENABLED;
while (ceq_cb->ceqe_state & HINIC_EQE_RUNNING)
schedule();
/** * eq_update_ci - update the HW cons idx of event queue * @eq: the event queue to update the cons idx for * @arm_state: the arm bit value of eq's interrupt
**/ staticvoid eq_update_ci(struct hinic_eq *eq, u32 arm_state)
{
u32 val, addr = EQ_CONS_IDX_REG_ADDR(eq);
/* Read Modify Write */
val = hinic_hwif_read_reg(eq->hwif, addr);
/** * ceq_irq_handler - handler for the CEQ event * @eq: the Completion Event Queue that received the event
**/ staticvoid ceq_irq_handler(struct hinic_eq *eq)
{ struct hinic_ceqs *ceqs = ceq_to_ceqs(eq);
u32 ceqe; int i;
for (i = 0; i < eq->q_len; i++) {
ceqe = *(GET_CURR_CEQ_ELEM(eq));
/* Data in HW is in Big endian Format */
ceqe = be32_to_cpu(ceqe);
/* HW toggles the wrapped bit, when it adds eq element event */ if (HINIC_EQ_ELEM_DESC_GET(ceqe, WRAPPED) == eq->wrapped) break;
/** * eq_irq_handler - handler for the EQ event * @data: the Event Queue that received the event
**/ staticvoid eq_irq_handler(void *data)
{ struct hinic_eq *eq = data;
if (eq->type == HINIC_AEQ)
aeq_irq_handler(eq); elseif (eq->type == HINIC_CEQ)
ceq_irq_handler(eq);
eq_update_ci(eq, EQ_ARMED);
}
/** * eq_irq_work - the work of the EQ that received the event * @work: the work struct that is associated with the EQ
**/ staticvoid eq_irq_work(struct work_struct *work)
{ struct hinic_eq_work *aeq_work = work_to_aeq_work(work); struct hinic_eq *aeq;
aeq = aeq_work->data;
eq_irq_handler(aeq);
}
/** * ceq_tasklet - the tasklet of the EQ that received the event * @t: the tasklet struct pointer
**/ staticvoid ceq_tasklet(struct tasklet_struct *t)
{ struct hinic_eq *ceq = from_tasklet(ceq, t, ceq_tasklet);
eq_irq_handler(ceq);
}
/** * aeq_interrupt - aeq interrupt handler * @irq: irq number * @data: the Async Event Queue that collected the event
**/ static irqreturn_t aeq_interrupt(int irq, void *data)
{ struct hinic_eq_work *aeq_work; struct hinic_eq *aeq = data; struct hinic_aeqs *aeqs;
/** * set_eq_ctrls - setting eq's ctrl registers * @eq: the Event Queue for setting
**/ staticint set_eq_ctrls(struct hinic_eq *eq)
{ if (HINIC_IS_VF(eq->hwif) && eq->type == HINIC_CEQ) return set_ceq_ctrl_reg(eq);
set_ctrl0(eq);
set_ctrl1(eq); return 0;
}
/** * aeq_elements_init - initialize all the elements in the aeq * @eq: the Async Event Queue * @init_val: value to initialize the elements with it
**/ staticvoid aeq_elements_init(struct hinic_eq *eq, u32 init_val)
{ struct hinic_aeq_elem *aeqe; int i;
for (i = 0; i < eq->q_len; i++) {
aeqe = GET_AEQ_ELEM(eq, i);
aeqe->desc = cpu_to_be32(init_val);
}
wmb(); /* Write the initilzation values */
}
/** * ceq_elements_init - Initialize all the elements in the ceq * @eq: the event queue * @init_val: value to init the elements with
**/ staticvoid ceq_elements_init(struct hinic_eq *eq, u32 init_val)
{
u32 *ceqe; int i;
for (i = 0; i < eq->q_len; i++) {
ceqe = GET_CEQ_ELEM(eq, i);
*(ceqe) = cpu_to_be32(init_val);
}
wmb(); /* Write the initilzation values */
}
/** * alloc_eq_pages - allocate the pages for the queue * @eq: the event queue * * Return 0 - Success, Negative - Failure
**/ staticint alloc_eq_pages(struct hinic_eq *eq)
{ struct hinic_hwif *hwif = eq->hwif; struct pci_dev *pdev = hwif->pdev;
u32 init_val, addr, val; int err, pg;
eq->dma_addr = devm_kcalloc(&pdev->dev, eq->num_pages, sizeof(*eq->dma_addr), GFP_KERNEL); if (!eq->dma_addr) return -ENOMEM;
/** * init_eq - initialize Event Queue * @eq: the event queue * @hwif: the HW interface of a PCI function device * @type: the type of the event queue, aeq or ceq * @q_id: Queue id number * @q_len: the number of EQ elements * @page_size: the page size of the pages in the event queue * @entry: msix entry associated with the event queue * * Return 0 - Success, Negative - Failure
**/ staticint init_eq(struct hinic_eq *eq, struct hinic_hwif *hwif, enum hinic_eq_type type, int q_id, u32 q_len, u32 page_size, struct msix_entry entry)
{ struct pci_dev *pdev = hwif->pdev; int err;
/* Clear PI and CI, also clear the ARM bit */
hinic_hwif_write_reg(eq->hwif, EQ_CONS_IDX_REG_ADDR(eq), 0);
hinic_hwif_write_reg(eq->hwif, EQ_PROD_IDX_REG_ADDR(eq), 0);
/* set the attributes of the msix entry */
hinic_msix_attr_set(eq->hwif, eq->msix_entry.entry,
HINIC_EQ_MSIX_PENDING_LIMIT_DEFAULT,
HINIC_EQ_MSIX_COALESC_TIMER_DEFAULT,
HINIC_EQ_MSIX_LLI_TIMER_DEFAULT,
HINIC_EQ_MSIX_LLI_CREDIT_LIMIT_DEFAULT,
HINIC_EQ_MSIX_RESEND_TIMER_DEFAULT);
/** * hinic_aeqs_init - initialize all the aeqs * @aeqs: pointer to Async eqs of the chip * @hwif: the HW interface of a PCI function device * @num_aeqs: number of AEQs * @q_len: number of EQ elements * @page_size: the page size of the pages in the event queue * @msix_entries: msix entries associated with the event queues * * Return 0 - Success, negative - Failure
**/ int hinic_aeqs_init(struct hinic_aeqs *aeqs, struct hinic_hwif *hwif, int num_aeqs, u32 q_len, u32 page_size, struct msix_entry *msix_entries)
{ struct pci_dev *pdev = hwif->pdev; int err, i, q_id;
aeqs->workq = create_singlethread_workqueue(HINIC_EQS_WQ_NAME); if (!aeqs->workq) return -ENOMEM;
err_init_aeq: for (i = 0; i < q_id; i++)
remove_eq(&aeqs->aeq[i]);
destroy_workqueue(aeqs->workq); return err;
}
/** * hinic_aeqs_free - free all the aeqs * @aeqs: pointer to Async eqs of the chip
**/ void hinic_aeqs_free(struct hinic_aeqs *aeqs)
{ int q_id;
for (q_id = 0; q_id < aeqs->num_aeqs ; q_id++)
remove_eq(&aeqs->aeq[q_id]);
destroy_workqueue(aeqs->workq);
}
/** * hinic_ceqs_init - init all the ceqs * @ceqs: ceqs part of the chip * @hwif: the hardware interface of a pci function device * @num_ceqs: number of CEQs * @q_len: number of EQ elements * @page_size: the page size of the event queue * @msix_entries: msix entries associated with the event queues * * Return 0 - Success, Negative - Failure
**/ int hinic_ceqs_init(struct hinic_ceqs *ceqs, struct hinic_hwif *hwif, int num_ceqs, u32 q_len, u32 page_size, struct msix_entry *msix_entries)
{ struct pci_dev *pdev = hwif->pdev; int i, q_id, err;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.