// SPDX-License-Identifier: GPL-2.0-only /* * Huawei HiNIC PCI Express Linux driver * Copyright(c) 2017 Huawei Technologies Co., Ltd */ #include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/pci.h> #include <linux/device.h> #include <linux/workqueue.h> #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/dma-mapping.h> #include <linux/log2.h> #include <asm/byteorder.h> #include <asm/barrier.h> #include "hinic_hw_dev.h" #include "hinic_hw_csr.h" #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" #define HINIC_EQS_WQ_NAME … #define GET_EQ_NUM_PAGES(eq, pg_size) … #define GET_EQ_NUM_ELEMS_IN_PG(eq, pg_size) … #define EQ_CONS_IDX_REG_ADDR(eq) … #define EQ_PROD_IDX_REG_ADDR(eq) … #define EQ_HI_PHYS_ADDR_REG(eq, pg_num) … #define EQ_LO_PHYS_ADDR_REG(eq, pg_num) … #define GET_EQ_ELEMENT(eq, idx) … #define GET_AEQ_ELEM(eq, idx) … #define GET_CEQ_ELEM(eq, idx) … #define GET_CURR_AEQ_ELEM(eq) … #define GET_CURR_CEQ_ELEM(eq) … #define PAGE_IN_4K(page_size) … #define EQ_SET_HW_PAGE_SIZE_VAL(eq) … #define ELEMENT_SIZE_IN_32B(eq) … #define EQ_SET_HW_ELEM_SIZE_VAL(eq) … #define EQ_MAX_PAGES … #define CEQE_TYPE_SHIFT … #define CEQE_TYPE_MASK … #define CEQE_TYPE(ceqe) … #define CEQE_DATA_MASK … #define CEQE_DATA(ceqe) … #define aeq_to_aeqs(eq) … #define ceq_to_ceqs(eq) … #define work_to_aeq_work(work) … #define DMA_ATTR_AEQ_DEFAULT … #define DMA_ATTR_CEQ_DEFAULT … /* No coalescence */ #define THRESH_CEQ_DEFAULT … enum eq_int_mode { … }; enum eq_arm_state { … }; /** * 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)) { … } /** * 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) { … } /** * 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)) { … } /** * 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) { … } static u8 eq_cons_idx_checksum_set(u32 val) { … } /** * 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 **/ static void eq_update_ci(struct hinic_eq *eq, u32 arm_state) { … } /** * aeq_irq_handler - handler for the AEQ event * @eq: the Async Event Queue that received the event **/ static void aeq_irq_handler(struct hinic_eq *eq) { … } /** * ceq_event_handler - handler for the ceq events * @ceqs: ceqs part of the chip * @ceqe: ceq element that describes the event **/ static void ceq_event_handler(struct hinic_ceqs *ceqs, u32 ceqe) { … } /** * ceq_irq_handler - handler for the CEQ event * @eq: the Completion Event Queue that received the event **/ static void ceq_irq_handler(struct hinic_eq *eq) { … } /** * eq_irq_handler - handler for the EQ event * @data: the Event Queue that received the event **/ static void eq_irq_handler(void *data) { … } /** * eq_irq_work - the work of the EQ that received the event * @work: the work struct that is associated with the EQ **/ static void eq_irq_work(struct work_struct *work) { … } /** * ceq_tasklet - the tasklet of the EQ that received the event * @t: the tasklet struct pointer **/ static void ceq_tasklet(struct tasklet_struct *t) { … } /** * 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) { … } /** * ceq_interrupt - ceq interrupt handler * @irq: irq number * @data: the Completion Event Queue that collected the event **/ static irqreturn_t ceq_interrupt(int irq, void *data) { … } static u32 get_ctrl0_val(struct hinic_eq *eq, u32 addr) { … } static void set_ctrl0(struct hinic_eq *eq) { … } static u32 get_ctrl1_val(struct hinic_eq *eq, u32 addr) { … } static void set_ctrl1(struct hinic_eq *eq) { … } static int set_ceq_ctrl_reg(struct hinic_eq *eq) { … } /** * set_eq_ctrls - setting eq's ctrl registers * @eq: the Event Queue for setting **/ static int set_eq_ctrls(struct hinic_eq *eq) { … } /** * aeq_elements_init - initialize all the elements in the aeq * @eq: the Async Event Queue * @init_val: value to initialize the elements with it **/ static void aeq_elements_init(struct hinic_eq *eq, u32 init_val) { … } /** * ceq_elements_init - Initialize all the elements in the ceq * @eq: the event queue * @init_val: value to init with it the elements **/ static void ceq_elements_init(struct hinic_eq *eq, u32 init_val) { … } /** * alloc_eq_pages - allocate the pages for the queue * @eq: the event queue * * Return 0 - Success, Negative - Failure **/ static int alloc_eq_pages(struct hinic_eq *eq) { … } /** * free_eq_pages - free the pages of the queue * @eq: the Event Queue **/ static void free_eq_pages(struct hinic_eq *eq) { … } /** * 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 **/ static int 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) { … } /** * remove_eq - remove Event Queue * @eq: the event queue **/ static void remove_eq(struct hinic_eq *eq) { … } /** * 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) { … } /** * hinic_aeqs_free - free all the aeqs * @aeqs: pointer to Async eqs of the chip **/ void hinic_aeqs_free(struct hinic_aeqs *aeqs) { … } /** * 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) { … } /** * hinic_ceqs_free - free all the ceqs * @ceqs: ceqs part of the chip **/ void hinic_ceqs_free(struct hinic_ceqs *ceqs) { … } void hinic_dump_ceq_info(struct hinic_hwdev *hwdev) { … } void hinic_dump_aeq_info(struct hinic_hwdev *hwdev) { … }