// SPDX-License-Identifier: GPL-2.0 /** * Copyright (c) 2024-2025 CALCULET Technologies Ltd. All rights reserved. */ #ifndef _CALCULET_DMA_H_ #define _CALCULET_DMA_H_ #include "ioctl.h" #include #include #include #include #include #include #include #include #include #include #include #include #define DESC_MAGIC 0x0UL #define DESC_MAX_COUNT (1024) #define DMA_TRANSFER_MAX_DESC (2048) #define DMA_CHANNEL_MAX_SIZE (8 * 1024 * 1024) /* 获取64位地址的高32位和低32位 */ #define PCI_DMA_H(addr) ((addr >> 16) >> 16) #define PCI_DMA_L(addr) (addr & 0xffffffffUL) // DMA寄存器偏移定义 #define DMA_CHANNEL_BASE_OFF(i) ((i) * 2 * 0x100) #define DMA_WRITE_ENGINE_EN_OFF 0xc #define DMA_WRITE_DOORBELL_OFF 0x10 #define DMA_WRCH_CONTROL1_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x200) #define DMA_WRCH_SIZE_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x208) #define DMA_WRCH_SAR_LOW_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x20c) #define DMA_WRCH_SAR_HIGH_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x210) #define DMA_WRCH_DAR_LOW_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x214) #define DMA_WRCH_DAR_HIGH_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x218) #define DMA_READ_ENGINE_EN_OFF 0x2c #define DMA_READ_DOORBELL_OFF 0x30 #define DMA_RDCH_CONTROL1_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x300) #define DMA_RDCH_SIZE_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x308) #define DMA_RDCH_SAR_LOW_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x30c) #define DMA_RDCH_SAR_HIGH_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x310) #define DMA_RDCH_DAR_LOW_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x314) #define DMA_RDCH_DAR_HIGH_OFF(i) (DMA_CHANNEL_BASE_OFF(i) + 0x318) // 前向声明 struct calculet_resource; // DMA通道状态枚举 enum calculet_dma_channel_state { DMA_CHANNEL_IDLE = 0, DMA_CHANNEL_BUSY, DMA_CHANNEL_COMPLETING, DMA_CHANNEL_ERROR, DMA_CHANNEL_DISABLED }; // DMA IO回调结构体 struct calculet_dma_io_cb { void __user *buf; size_t len; unsigned int pages_nr; struct sg_table sgt; struct page **pages; }; // DMA传输上下文 struct calculet_dma_transfer_context { struct completion completion; int result; ktime_t start_time; ktime_t end_time; pid_t requester_pid; atomic_t ref_count; }; // DMA通道结构体 struct calculet_dma_channel { u8 channel_index; u8 vector_index; int msi_irq_line; u32 irq_bitmask; // 改进的状态管理 enum calculet_dma_channel_state state; atomic_t transfer_finish; spinlock_t state_lock; resource_size_t dma_regs; size_t dma_channel_size; uint8_t *buffer; uint64_t dst_address; wait_queue_head_t channel_wq; struct calculet_dma_io_cb *desc_io_cb; // 改进的缓冲区管理 void *kernel_buf; size_t dma_len; dma_addr_t dma_handle; struct mutex buffer_mutex; atomic_t buffer_users; // 传输统计和监控 atomic64_t transfer_count; atomic64_t transfer_bytes; ktime_t last_used; // 当前传输上下文 struct calculet_dma_transfer_context *current_transfer; struct mutex transfer_mutex; }; // DMA轮询结构体 struct calculet_dma_poll { dma_addr_t status_region_phys; uint32_t *status_region; uint32_t channel_status[CALCULET_TOTAL_CHANNELS]; uint32_t channel_data[CALCULET_TOTAL_CHANNELS]; spinlock_t poll_lock; atomic_t poll_active; }; // DMA内核线程结构体 struct calculet_dma_kthread { struct calculet_dma_poll *dma_poll; struct task_struct *poll_thread; u32 poll_interval_ms; char thread_name[24]; atomic_t should_stop; struct completion thread_completion; }; // DMA控制器结构体 struct calculet_dma_controller { struct device *dev; struct calculet_dma_channel dma_rdch_s[CALCULET_READ_CHANNELS]; struct calculet_dma_channel dma_wrch_s[CALCULET_WRITE_CHANNELS]; struct calculet_dma_channel msi_req[CALCULET_TOTAL_CHANNELS]; // struct calculet_dma_channel soft_reset; struct calculet_dma_kthread *dma_kthread; // 控制器级别的锁和状态 struct mutex controller_mutex; atomic_t active_transfers; bool controller_enabled; // 通道分配管理 unsigned long read_channels_bitmap; // 读通道分配位图 unsigned long write_channels_bitmap; // 写通道分配位图 struct mutex allocation_mutex; }; // 通道分配和释放 int calculet_dma_allocate_channel(struct calculet_dma_controller *controller, enum calculet_transfer_direction direction, int *channel_id); void calculet_dma_release_channel(struct calculet_dma_controller *controller, enum calculet_transfer_direction direction, int channel_id); // DMA通道状态管理 void calculet_dma_channel_set_state(struct calculet_dma_channel *channel, enum calculet_dma_channel_state state); enum calculet_dma_channel_state calculet_dma_channel_get_state(struct calculet_dma_channel *channel); bool calculet_dma_channel_is_available(struct calculet_dma_channel *channel); // 传输上下文管理 struct calculet_dma_transfer_context* calculet_dma_create_transfer_context(pid_t pid); void calculet_dma_destroy_transfer_context(struct calculet_dma_transfer_context *ctx); void calculet_dma_transfer_context_get(struct calculet_dma_transfer_context *ctx); void calculet_dma_transfer_context_put(struct calculet_dma_transfer_context *ctx); // 函数声明 int calculet_dma_controller_init(struct calculet_dma_controller *controller, struct device *dev, bool poll_en); void calculet_dma_controller_deinit(struct calculet_dma_controller *controller, bool poll_en); long calculet_dma_ioctl(struct calculet_resource *resource, struct calculet_dma_controller *controller, unsigned int cmd, unsigned long arg); int calculet_dma_poll_ioctl(struct calculet_dma_controller *controller); // DMA传输函数(改进版本) long calculet_dma_h2c_transfer(struct device *dev, struct calculet_dma_channel *channel, struct calculet_resource *resource); long calculet_dma_c2h_transfer(struct device *dev, struct calculet_dma_channel *channel, struct calculet_resource *resource); // 新增:安全的DMA传输函数 long calculet_dma_safe_transfer(struct calculet_dma_controller *controller, struct calculet_dma_transfer_channels_params *params, struct calculet_resource *resource); // 超时处理 void calculet_dma_timeout_handler(struct timer_list *timer); int calculet_dma_set_timeout(struct calculet_dma_channel *channel, unsigned int timeout_ms); // 中断处理函数 irqreturn_t calculet_irqhandler(int irq, void* dev_id); int calculet_poll_handler(void *data); // 错误恢复 void calculet_dma_error_recovery_work(struct work_struct *work); int calculet_dma_channel_recovery(struct calculet_dma_channel *channel); // 统计和监控 void calculet_dma_update_channel_stats(struct calculet_dma_channel *channel, size_t bytes, bool success); void calculet_dma_dump_channel_stats(struct calculet_dma_controller *controller); // 调试和诊断 int calculet_dma_validate_transfer_params(struct calculet_dma_transfer_channels_params *params); void calculet_dma_dump_controller_state(struct calculet_dma_controller *controller); #endif /* _CALCULET_DMA_H_ */