* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that 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.
*/
#include "ka_pci_pub.h"
#include "ka_common_pub.h"
#include "ka_kernel_def_pub.h"
#include "ka_task_pub.h"
#include "ka_base_pub.h"
#include "ka_dfx_pub.h"
#include "adapter_api.h"
#include "adpater_def.h"
#ifdef CFG_HOST_ENV
#define PCIE_KO_NAME "drv_pcie_host"
#else
#define PCIE_KO_NAME "drv_pcie"
#endif
#define UB_KO_NAME "asdrv_ub"
#define PCI_VENDOR_ID_HUAWEI 0x19e5
#define DEVDRV_DIVERSITY_PCIE_VENDOR_ID 0xFFFF
struct bus_adpater_stu g_pcie_adpat = {0};
struct bus_adpater_stu g_ubbus_adpat = {0};
struct symbol_list pcie_ops[] = {
{"hal_kernel_devdrv_dma_alloc_coherent", (ka_offsetof(struct bus_adpater_stu, dma)\
+ ka_offsetof(struct dma_ops_stu, alloc_coherent))},
{"hal_kernel_devdrv_dma_free_coherent", (ka_offsetof(struct bus_adpater_stu, dma)\
+ ka_offsetof(struct dma_ops_stu, free_coherent))},
{"devdrv_dma_link_free", (ka_offsetof(struct bus_adpater_stu, dma)\
+ ka_offsetof(struct dma_ops_stu, link_free))},
{"devdrv_dma_link_prepare", (ka_offsetof(struct bus_adpater_stu, dma)\
+ ka_offsetof(struct dma_ops_stu, link_prepare))},
{"hal_kernel_devdrv_dma_map_single", (ka_offsetof(struct bus_adpater_stu, dma)\
+ ka_offsetof(struct dma_ops_stu, map_single))},
{"hal_kernel_devdrv_dma_sync_copy", (ka_offsetof(struct bus_adpater_stu, dma)\
+ ka_offsetof(struct dma_ops_stu, sync_copy))},
{"hal_kernel_devdrv_dma_unmap_single", (ka_offsetof(struct bus_adpater_stu, dma)\
+ ka_offsetof(struct dma_ops_stu, unmap_single))},
{"devdrv_enable_p2p", (ka_offsetof(struct bus_adpater_stu, p2p)\
+ ka_offsetof(struct p2p_ops_stu, enable))},
{"devdrv_disable_p2p", (ka_offsetof(struct bus_adpater_stu, p2p)\
+ ka_offsetof(struct p2p_ops_stu, disable))},
{"devdrv_is_p2p_enabled", (ka_offsetof(struct bus_adpater_stu, p2p)\
+ ka_offsetof(struct p2p_ops_stu, is_enabled))},
{"devdrv_flush_p2p", (ka_offsetof(struct bus_adpater_stu, p2p)\
+ ka_offsetof(struct p2p_ops_stu, flush))},
{"devdrv_get_p2p_capability", (ka_offsetof(struct bus_adpater_stu, p2p)\
+ ka_offsetof(struct p2p_ops_stu, getcapability))},
{"devdrv_get_p2p_access_status", (ka_offsetof(struct bus_adpater_stu, p2p)\
+ ka_offsetof(struct p2p_ops_stu, get_access_status))},
{"devdrv_get_hccs_link_status_and_group_id", (ka_offsetof(struct bus_adpater_stu, hccs)\
+ ka_offsetof(struct hccs_ops_stu, get_hccs_link_status_and_group_id))},
{"devdrv_get_pci_dev_info", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, get_pci_dev_info))},
{"devdrv_get_pcie_id_info", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, get_pcie_id_info))},
{"devdrv_get_dev_topology", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, get_dev_topology))},
{"devdrv_hot_reset_device", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, hot_reset_device))},
{"devdrv_hot_pre_reset", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, prereset))},
{"devdrv_pcie_read_proc", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, read_proc))},
{"devdrv_get_addr_info", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, get_addr_info))},
{"devdrv_get_bbox_reservd_mem", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, get_bbox_reservd_mem))},
{"devdrv_register_black_callback", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, register_black_callback))},
{"devdrv_unregister_black_callback", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, unregister_black_callback))},
{"devdrv_dev_state_notifier_unregister", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, notifier_unregister))},
{"drvdrv_dev_state_notifier_register", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, notifier_register))},
{"devdrv_set_module_init_finish", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, set_module_init_finish))},
{"drvdrv_dev_startup_register", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, startup_register))},
{"devdrv_get_host_type", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, get_host_type))},
{"devdrv_get_master_devid_in_the_same_os", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, get_master_devid_in_the_same_os))},
{"devdrv_pcie_reinit", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, reinit))},
{"devdrv_get_pci_enabled_vf_num", (ka_offsetof(struct bus_adpater_stu, pcie)\
+ ka_offsetof(struct pcie_ops_stu, get_pci_enabled_vf_num))},
};
struct symbol_list ubbus_ops[] = {
{"ubdrv_flush_p2p", (ka_offsetof(struct bus_adpater_stu, p2p)\
+ ka_offsetof(struct p2p_ops_stu, flush))},
};
struct module_adapter_cb adap_cb[] = {
{PCIE_KO_NAME, pcie_ops, (sizeof(pcie_ops)/sizeof(struct symbol_list)), &g_pcie_adpat},
{UB_KO_NAME, ubbus_ops, (sizeof(ubbus_ops)/sizeof(struct symbol_list)), &g_ubbus_adpat},
};
static const ka_pci_device_id_t devdrv_driver_tbl[] = {
{ KA_PCI_VDEVICE(HUAWEI, 0xd806), 0 },
{ KA_PCI_VDEVICE(HUAWEI, 0xd807), 0 },
{ DEVDRV_DIVERSITY_PCIE_VENDOR_ID, 0xd500, KA_PCI_ANY_ID, KA_PCI_ANY_ID, 0, 0, 0 },
{}};
KA_MODULE_DEVICE_TABLE(pci, devdrv_driver_tbl);
struct bus_adpater_stu *get_adapter_by_dev_id(unsigned int dev_id)
{
struct bus_adpater_stu *adap[] = {&g_pcie_adpat, &g_ubbus_adpat};
int connect_type = CONNECT_PROTOCOL_UNKNOWN;
#if (defined CFG_HOST_ENV) && (!defined CFG_FEATURE_ASCEND910_96_STUB)
#ifdef CFG_FEATURE_UB
connect_type = CONNECT_PROTOCOL_UB;
#else
connect_type = CONNECT_PROTOCOL_PCIE;
#endif
#else
connect_type = devdrv_get_connect_protocol(dev_id);
#endif
if ((connect_type == CONNECT_PROTOCOL_PCIE) || (connect_type == CONNECT_PROTOCOL_HCCS)) {
ka_task_down_read(&adap[ADAPTER_PCIE_BUS]->rw_lock);
return adap[ADAPTER_PCIE_BUS];
} else {
ka_task_down_read(&adap[ADAPTER_UB_BUS]->rw_lock);
return adap[ADAPTER_UB_BUS];
}
}
struct bus_adpater_stu *get_adapter_by_module(unsigned int index)
{
struct bus_adpater_stu *adap[] = {&g_pcie_adpat, &g_ubbus_adpat};
if (index > ADAPTER_UB_BUS) {
ka_task_down_read(&adap[0]->rw_lock);
return adap[0];
}
ka_task_down_read(&adap[index]->rw_lock);
return adap[index];
}
void put_adapter(struct bus_adpater_stu *adap)
{
ka_task_up_read(&adap->rw_lock);
}
static void init_module_function(ka_module_t *mod)
{
int i;
for (i=0; i < (sizeof(adap_cb)/sizeof(struct module_adapter_cb)); i++) {
if (ka_base_strcmp(mod->name, adap_cb[i].mod_name) != 0) {
continue;
}
init_module_func(mod, adap_cb[i].sym_list, adap_cb[i].sym_count, adap_cb[i].adap);
}
}
static void uninit_module_function(ka_module_t *mod)
{
int i;
for (i=0; i < (sizeof(adap_cb)/sizeof(struct module_adapter_cb)); i++) {
if (ka_base_strcmp(mod->name, adap_cb[i].mod_name) != 0) {
continue;
}
uninit_module_func(adap_cb[i].sym_list, adap_cb[i].sym_count, adap_cb[i].adap);
}
}
static int adapter_module_callback(ka_notifier_block_t *nb,
unsigned long val, void *data)
{
ka_module_t *mod = data;
if (mod == NULL) {
return KA_NOTIFY_DONE;
}
switch (val) {
case MODULE_STATE_GOING:
uninit_module_function(mod);
break;
case MODULE_STATE_LIVE:
init_module_function(mod);
break;
default:
break;
}
return KA_NOTIFY_DONE;
}
static ka_notifier_block_t g_adapter_module_nb = {
.notifier_call = adapter_module_callback,
.priority = 0
};
int KA_MODULE_INIT ascend_adapter_init(void)
{
int err, i;
for (i = 0; i < (sizeof(adap_cb)/sizeof(struct module_adapter_cb)); i++) {
ka_task_init_rwsem(&adap_cb[i].adap->rw_lock);
}
err = ka_dfx_register_module_notifier(&g_adapter_module_nb);
return err;
}
void KA_MODULE_EXIT ascend_adapter_exit(void)
{
ka_dfx_unregister_module_notifier(&g_adapter_module_nb);
return;
}
ka_module_init(ascend_adapter_init);
ka_module_exit(ascend_adapter_exit);
KA_MODULE_LICENSE("GPL");
KA_MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
KA_MODULE_DESCRIPTION("DAVINCI DMS Manager driver");
KA_MODULE_SOFTDEP("pre: asdrv_pbl post: drv_pcie_host");