2026-01-29 22:25:33 +08:00

178 lines
3.9 KiB
C

/* SPDX-License-Identifier: GPL-2.0*/
/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#ifndef HINIC_EQS_H
#include <linux/interrupt.h>
#define HINIC_EQS_H
#define HINIC_EQ_PAGE_SIZE 0x00001000
#define HINIC_HW_MAX_AEQS 4
#define HINIC_MAX_AEQS 3
#define HINIC_MAX_CEQS 32
#define HINIC_EQ_MAX_PAGES 8
#define HINIC_AEQE_SIZE 64
#define HINIC_CEQE_SIZE 4
#define HINIC_AEQE_DESC_SIZE 4
#define HINIC_AEQE_DATA_SIZE \
(HINIC_AEQE_SIZE - HINIC_AEQE_DESC_SIZE)
#define HINIC_DEFAULT_AEQ_LEN 0x10000
#define HINIC_DEFAULT_CEQ_LEN 0x10000
#define HINIC_VMGW_DEFAULT_AEQ_LEN 128
#define HINIC_VMGW_DEFAULT_CEQ_LEN 1024
#define HINIC_MIN_AEQ_LEN 64
#define HINIC_MAX_AEQ_LEN (512 * 1024)
#define HINIC_MIN_CEQ_LEN 64
#define HINIC_MAX_CEQ_LEN (1024 * 1024)
#define HINIC_CEQ_ID_CMDQ 0
#define EQ_IRQ_NAME_LEN 64
enum hinic_eq_type {
HINIC_AEQ,
HINIC_CEQ
};
enum hinic_eq_intr_mode {
HINIC_INTR_MODE_ARMED,
HINIC_INTR_MODE_ALWAYS,
};
enum hinic_eq_ci_arm_state {
HINIC_EQ_NOT_ARMED,
HINIC_EQ_ARMED,
};
struct hinic_eq {
struct hinic_hwdev *hwdev;
u16 q_id;
enum hinic_eq_type type;
u32 page_size;
u32 orig_page_size;
u32 eq_len;
u32 cons_idx;
u16 wrapped;
u16 elem_size;
u16 num_pages;
u32 num_elem_in_pg;
struct irq_info eq_irq;
char irq_name[EQ_IRQ_NAME_LEN];
dma_addr_t *dma_addr;
u8 **virt_addr;
dma_addr_t *dma_addr_for_free;
u8 **virt_addr_for_free;
struct work_struct aeq_work;
struct tasklet_struct ceq_tasklet;
u64 hard_intr_jif;
u64 soft_intr_jif;
};
struct hinic_aeq_elem {
u8 aeqe_data[HINIC_AEQE_DATA_SIZE];
u32 desc;
};
enum hinic_aeq_cb_state {
HINIC_AEQ_HW_CB_REG = 0,
HINIC_AEQ_HW_CB_RUNNING,
HINIC_AEQ_SW_CB_REG,
HINIC_AEQ_SW_CB_RUNNING,
};
struct hinic_aeqs {
struct hinic_hwdev *hwdev;
hinic_aeq_hwe_cb aeq_hwe_cb[HINIC_MAX_AEQ_EVENTS];
hinic_aeq_swe_cb aeq_swe_cb[HINIC_MAX_AEQ_SW_EVENTS];
unsigned long aeq_hw_cb_state[HINIC_MAX_AEQ_EVENTS];
unsigned long aeq_sw_cb_state[HINIC_MAX_AEQ_SW_EVENTS];
struct hinic_eq aeq[HINIC_MAX_AEQS];
u16 num_aeqs;
struct workqueue_struct *workq;
};
enum hinic_ceq_cb_state {
HINIC_CEQ_CB_REG = 0,
HINIC_CEQ_CB_RUNNING,
};
struct hinic_ceqs {
struct hinic_hwdev *hwdev;
hinic_ceq_event_cb ceq_cb[HINIC_MAX_CEQ_EVENTS];
void *ceq_data[HINIC_MAX_CEQ_EVENTS];
unsigned long ceq_cb_state[HINIC_MAX_CEQ_EVENTS];
struct hinic_eq ceq[HINIC_MAX_CEQS];
u16 num_ceqs;
};
enum hinic_msg_pipe_state {
PIPE_STATE_IDLE,
PIPE_STATE_BUSY,
PIPE_STATE_SUSPEND,
};
#define PIPE_CYCLE_MAX 10000
u32 hinic_func_busy_state_get(struct hinic_hwdev *hwdev);
void hinic_func_busy_state_set(struct hinic_hwdev *hwdev, u32 cfg);
u32 hinic_func_own_bit_get(struct hinic_hwdev *hwdev);
void hinic_func_own_bit_set(struct hinic_hwdev *hwdev, u32 cfg);
int hinic_aeqs_init(struct hinic_hwdev *hwdev, u16 num_aeqs,
struct irq_info *msix_entries);
void hinic_aeqs_free(struct hinic_hwdev *hwdev);
int hinic_ceqs_init(struct hinic_hwdev *hwdev, u16 num_ceqs,
struct irq_info *msix_entries);
void hinic_ceqs_free(struct hinic_hwdev *hwdev);
void hinic_get_ceq_irqs(struct hinic_hwdev *hwdev, struct irq_info *irqs,
u16 *num_irqs);
void hinic_get_aeq_irqs(struct hinic_hwdev *hwdev, struct irq_info *irqs,
u16 *num_irqs);
void hinic_dump_ceq_info(struct hinic_hwdev *hwdev);
void hinic_dump_aeq_info(struct hinic_hwdev *hwdev);
int hinic_reschedule_eq(struct hinic_hwdev *hwdev, enum hinic_eq_type type,
u16 eq_id);
#endif