diff --git a/README.md b/README.md index 6c1ee71..e897951 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +DEPRECATED +========== + +As of Linux version 6.15, the functionality provided by this module is now provided by the upstream `AMDGPU` kernel driver. For more information see the [patch series](https://lists.freedesktop.org/archives/amd-gfx/2025-January/118399.html) + Before Installing ================= @@ -18,7 +23,7 @@ sudo pacman -S linux53-headers To Install ========== -Clone the repo into a github directory in your home folder: +Clone the repo into a GitHub directory in your home folder: ``` mkdir github cd github @@ -72,3 +77,49 @@ It should output all clients available on that bus: 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: 70 -- -- -- -- -- -- -- ``` +If the output it's only dashes, the driver is not working. + +Troubleshooting +=============== + +Some C knowledge may be needed. + +### Device not detected by the driver + +If the device is not being detected, `sudo i2cdetect -l` will not show any "AURA GPU adapter", and running `sudo dmesg` you should see "Failed to find any valid device". + +In this case, the pci id of your device is probably missing. Check the file "pci_ids.h", the id of your device can be found using the command `lspci -vnn`. + +### Device is detected by the driver but won't work (not detected by OpenRGB) + +In this case `sudo i2cdetect -l` will show the device, but `sudo i2cdetect -y ` will show only dashes, like so: +``` + 0 1 2 3 4 5 6 7 8 9 a b c d e f +00: -- -- -- -- -- -- -- -- -- -- -- -- -- +10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +70: -- -- -- -- -- -- -- -- +``` +This usually means that the driver is not using the correct line. The known lines are `6` for Polaris cards, and `7` for +Vega cards, but we can only test the cards we have. +Check the function `line_number_from_asic_type` in file `aura-gpu-hw.c`. + +If the line for your asic is unknown, the driver will default to line `6` and you will find "Unknown uc line for asic, +defaulting to line " in the output of `sudo dmesg`. + +Although that's been the case up to now, it is possible that the type of card is not enough to choose line, in that case +some work will be needed to select line based on pci_id. + +### Multiple GPUs + +This driver *should* work with multiple gpus, even of different generations, and allow to configure each one. +Due to limitations (e.g. not having two GPUs) this is not tested. If having multiple GPUs causes real issues, you can +set `MAX_AURA_DEVICES` (currently 4, as you won't usually see more than 4 cards in a system) to `1` so that it behaves +as it did before multi-GPU support. + +You can also increase the value if you have more than 4 GPUs. Increasing the number has a cost, don't do it if not +needed, and don't put unrealistic values, `4` should be enough for anyone. diff --git a/VERSION b/VERSION index 284b32c..4983d62 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -14.12445ef +20.7ce9965 \ No newline at end of file diff --git a/atom/atom.c b/atom/atom.c index 7f1bfb2..f4cbe6c 100644 --- a/atom/atom.c +++ b/atom/atom.c @@ -33,6 +33,7 @@ #include "atom.h" #include "atom-names.h" #include "atom-bits.h" +#include "../debug.h" #define ATOM_COND_ABOVE 0 #define ATOM_COND_ABOVEOREQUAL 1 @@ -1305,7 +1306,8 @@ struct atom_context *atom_parse(struct card_info *card, void const *bios) str = CSTR(idx); if (*str != '\0') { pr_info("ATOM BIOS: %s\n", str); - strlcpy(ctx->vbios_version, str, sizeof(ctx->vbios_version)); + if (strscpy(ctx->vbios_version, str, sizeof(ctx->vbios_version)) == -E2BIG) + AURA_WARN("Bios version string too long"); } return ctx; diff --git a/aura-gpu-bios.c b/aura-gpu-bios.c index c31edf1..f0c2335 100644 --- a/aura-gpu-bios.c +++ b/aura-gpu-bios.c @@ -1236,7 +1236,8 @@ static void _aura_gpu_bios_read_name( name_str = get_str(context, name_offset, sizeof(context->bios.name) - 1); if (*name_str != '\0') - strlcpy(context->bios.name, name_str, sizeof(context->bios.name)); + if (strscpy(context->bios.name, name_str, sizeof(context->bios.name)) == -E2BIG) + AURA_WARN("Bios name too long"); } static bool _aura_gpu_bios_is_atom( diff --git a/aura-gpu-hw.c b/aura-gpu-hw.c index 5d63436..1aa5b5b 100644 --- a/aura-gpu-hw.c +++ b/aura-gpu-hw.c @@ -7,6 +7,7 @@ #include "aura-gpu-bios.h" #include "aura-gpu-reg.h" #include "atom/atom.h" +#include "main.h" struct ATOM_MASTER_LIST_OF_COMMAND_TABLES { uint16_t ASIC_Init; //Function Table, used by various SW components,latest version 1.1 @@ -113,6 +114,11 @@ struct hw_i2c_context { container_of(ptr, struct hw_i2c_context, atom_card_info) \ ) +static struct pci_device_info { + struct pci_dev* device; + struct pci_device_id id; +}; + static uint32_t __invalid_read ( struct card_info *info, uint32_t reg @@ -160,7 +166,10 @@ static void mm_write ( #define HW_I2C_READ 0 #define HW_ASSISTED_I2C_STATUS_FAILURE 2 #define HW_ASSISTED_I2C_STATUS_SUCCESS 1 -#define UC_LINE_NUMBER 7 +#define UC_LINE_NUMBER_POLARIS 6 +#define UC_LINE_NUMBER_VEGA 7 +#define UC_LINE_NUMBER_DEFAULT 6 +#define UC_LINE_NUMBER_DEFAULT_STR "6 (Polaris)" // Default as string, to be used in messages struct transaction_parameters { uint8_t ucI2CSpeed; @@ -175,6 +184,22 @@ struct transaction_parameters { uint8_t ucLineNumber; }; +/* + * Returns the line number + */ +static uint8_t line_number_from_asic_type(enum aura_asic_type type){ + switch (type) { + case CHIP_POLARIS10: + case CHIP_POLARIS11: + return UC_LINE_NUMBER_POLARIS; + case CHIP_VEGA10: + return UC_LINE_NUMBER_VEGA; + default: + AURA_WARN("Unknown uc line for asic, defaulting to line " UC_LINE_NUMBER_DEFAULT_STR); + return UC_LINE_NUMBER_DEFAULT; + } +} + static error_t aura_gpu_i2c_process_i2c_ch( struct hw_i2c_context *context, uint8_t slave_addr, @@ -202,7 +227,10 @@ static error_t aura_gpu_i2c_process_i2c_ch( args.ucTransBytes = 1; args.ucSlaveAddr = slave_addr << 1; args.ucRegIndex = offset; - args.ucLineNumber = UC_LINE_NUMBER; + + // Find the line tu use for this particular device + enum aura_asic_type type = aura_i2c_adapter_asic_type(&context->adapter); + args.ucLineNumber = line_number_from_asic_type(type); AURA_DBG("Pre Transaction: addr = %x, offset = %x, rw = %s, count = %d, out = %x", args.ucSlaveAddr >> 1, @@ -411,7 +439,11 @@ static struct hw_i2c_context *aura_gpu_i2c_create ( context->atom_context->scratch = (uint32_t*)context->scratch; context->atom_context->scratch_size_bytes = sizeof(context->scratch); context->adapter.owner = THIS_MODULE; - context->adapter.class = I2C_CLASS_DDC; + context->adapter.class = I2C_CLASS_DEPRECATED; /* I2C_CLASS_DDC was removed in kernel version 6.8 + * it only appeared in the radeon_i2c kernel driver + * no in-tree module used it + * and class based device detection is discouraged */ + context->adapter.dev.parent = &pci_dev->dev; i2c_set_adapdata(&context->adapter, context); @@ -433,37 +465,56 @@ static struct hw_i2c_context *aura_gpu_i2c_create ( return ERR_PTR(err); } -static struct pci_dev *find_pci_dev ( - void +/* + * Stores pci device and id for at most MAX_AURA_DEVICES devices + */ +void find_pci_devs ( + struct pci_device_info pci_devs[MAX_AURA_DEVICES] ){ - struct pci_dev *pci_dev = NULL; - const struct pci_device_id *match; - - while (NULL != (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev))) { + struct pci_dev* pci_dev; + struct pci_device_id *match; + int matched = 0; + + while ( + NULL != (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) && + matched < MAX_AURA_DEVICES + ) { match = pci_match_id(pciidlist, pci_dev); - if (match) - return pci_dev; + if (match) { + pci_devs[matched].device = pci_dev; + pci_devs[matched].id = *match; + ++matched; + } } - - return NULL; } -struct i2c_adapter *aura_i2c_bios_create ( - void +void aura_i2c_bios_create ( + struct aura_adapter adapters[MAX_AURA_DEVICES] ){ - struct pci_dev *pci_dev = find_pci_dev(); - struct hw_i2c_context *context; + // Finds compatible devices + struct pci_device_info pci_devs[] = { + [ 0 ... MAX_AURA_DEVICES ] = { NULL, {0, 0, 0} } + }; + find_pci_devs(pci_devs); - if (!pci_dev) { - AURA_ERR("Failed to find a valid pci device"); - return NULL; + // check the first slot for failure + if (!pci_devs[0].device) { + AURA_ERR("Failed to find any valid pci device"); } - context = aura_gpu_i2c_create(pci_dev); - if (IS_ERR_OR_NULL(context)) - return ERR_PTR(CLEAR_ERR(context)); - - return &context->adapter; + // Create and stores a context for every device + struct hw_i2c_context *context; + for(int i = 0; i < MAX_AURA_DEVICES; ++i) { + if(pci_devs[i].device) { + context = aura_gpu_i2c_create(pci_devs[i].device); + if (IS_ERR_OR_NULL(context)) + adapters[i].adapter = ERR_PTR(CLEAR_ERR(context)); + + // Stores device and asic type + adapters[i].asic_type = pci_devs[i].id.driver_data; + adapters[i].adapter = &context->adapter; + } + } } void aura_i2c_bios_destroy ( diff --git a/aura-gpu-hw.h b/aura-gpu-hw.h index 5435f4b..26e7669 100644 --- a/aura-gpu-hw.h +++ b/aura-gpu-hw.h @@ -2,9 +2,11 @@ #define _UAPI_AURA_GPU_HW_I2C_H #include +#include "include/types.h" +#include "main.h" -struct i2c_adapter *aura_i2c_bios_create ( - void +void aura_i2c_bios_create ( + struct aura_adapter adapters[MAX_AURA_DEVICES] ); void aura_i2c_bios_destroy ( diff --git a/aura-gpu-i2c.c b/aura-gpu-i2c.c index e536f63..c4fbdb3 100644 --- a/aura-gpu-i2c.c +++ b/aura-gpu-i2c.c @@ -640,8 +640,12 @@ static struct aura_i2c_context* aura_gpu_i2c_context_create ( context->timeout_interval = GPU_I2C_TIMEOUT_INTERVAL; context->i2c_adapter.owner = THIS_MODULE; - context->i2c_adapter.class = I2C_CLASS_DDC; context->i2c_adapter.algo = &aura_gpu_i2c_algo; + context->i2c_adapter.class = I2C_CLASS_DEPRECATED; /* I2C_CLASS_DDC was removed in kernel version 6.8 + * it only appeared in the radeon_i2c kernel driver + * no in-tree module used it + * and class based device detection is discouraged */ + snprintf(context->i2c_adapter.name, sizeof(context->i2c_adapter.name), "AURA GPU adapter"); i2c_set_adapdata(&context->i2c_adapter, context); diff --git a/dkms.conf b/dkms.conf index 428cebc..f19bb39 100644 --- a/dkms.conf +++ b/dkms.conf @@ -1,7 +1,7 @@ MAKE="make TARGET=${kernelver}" CLEAN="make TARGET=${kernelver} clean" PACKAGE_NAME="aura-gpu" -PACKAGE_VERSION="14.12445ef" +PACKAGE_VERSION="20.7ce9965" BUILT_MODULE_NAME[0]="aura-gpu" DEST_MODULE_LOCATION[0]="/kernel/drivers/hwmon" AUTOINSTALL="yes" diff --git a/include/types.h b/include/types.h index 299b77c..32d6da8 100644 --- a/include/types.h +++ b/include/types.h @@ -1,9 +1,19 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _UAPI_INCLUDE_TYPES_H #define _UAPI_INCLUDE_TYPES_H +#include +#include + +#include "../asic/asic-types.h" #ifndef ERROR_TYPE typedef int error_t; + +struct aura_adapter { + struct i2c_adapter* adapter; + enum aura_asic_type asic_type; +}; + #define ERROR_TYPE error_t #endif diff --git a/main.c b/main.c index 0ecad47..8fda498 100644 --- a/main.c +++ b/main.c @@ -2,17 +2,27 @@ #include #include +#include "main.h" #include "debug.h" #include "aura-gpu-hw.h" +#include "include/types.h" -static struct i2c_adapter *adapter = NULL; +// Stores i2c_adapters and asic type +static struct aura_adapter adapters[] = { + [0 ... MAX_AURA_DEVICES] = {NULL, CHIP_LAST} +}; static int __init aura_module_init ( void ){ - adapter = aura_i2c_bios_create(); - if (IS_ERR_OR_NULL(adapter)) - CLEAR_ERR(adapter); + // find at most MAX_AURA_DEVICES devices + aura_i2c_bios_create(adapters); + + // clears error on all devices + for (int i = 0; i < MAX_AURA_DEVICES; ++i) { + if (IS_ERR(adapters[i].adapter)) + CLEAR_ERR(adapters[i].adapter); + } return 0; } @@ -20,14 +30,32 @@ static int __init aura_module_init ( static void __exit aura_module_exit ( void ){ - if (adapter) - aura_i2c_bios_destroy(adapter); + for (int i = 0; i < MAX_AURA_DEVICES; ++i) { + if (adapters[i].adapter) + aura_i2c_bios_destroy(adapters[i].adapter); + } +} + +/* + * Returns the AURA asic type associated to a certain adapter + */ +enum aura_asic_type aura_i2c_adapter_asic_type(struct i2c_adapter* adapter) { + for (int i = 0; i < MAX_AURA_DEVICES; ++i){ + // If adapter is not null, matches on adapter number + if ( + adapters[i].adapter && + i2c_adapter_id(adapters[i].adapter) == i2c_adapter_id(adapter) + ) { + return adapters[i].asic_type; + } + } + AURA_ERR("Asic_type not registered"); + return CHIP_LAST; } module_init(aura_module_init); module_exit(aura_module_exit); - MODULE_AUTHOR("Owen Parry "); MODULE_DESCRIPTION("ASUS AURA SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/main.h b/main.h new file mode 100644 index 0000000..dfb7f47 --- /dev/null +++ b/main.h @@ -0,0 +1,13 @@ +#ifndef _UAPI_AURA_GPU_MAIN_H +#define _UAPI_AURA_GPU_MAIN_H + +#define MAX_AURA_DEVICES 4 + +#include "include/types.h" + +/* + * Returns the AURA asic type associated to a certain adapter + */ +enum aura_asic_type aura_i2c_adapter_asic_type(struct i2c_adapter *adapter); + +#endif \ No newline at end of file diff --git a/pci_ids.h b/pci_ids.h index 2fbd9e9..105ad83 100644 --- a/pci_ids.h +++ b/pci_ids.h @@ -12,6 +12,7 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x67df, 0x1da2, 0xe366, 0, 0, CHIP_POLARIS10}, // RX580 (Sapphire Nitro+) {0x1002, 0x67df, 0x1043, 0x04fd, 0, 0, CHIP_POLARIS10}, // RX480 (Strix) + {0x1002, 0x67df, 0x1043, 0x04fb, 0, 0, CHIP_POLARIS10}, // RX480 (Strix) alternative id {0x1002, 0x67df, 0x1043, 0x0588, 0, 0, CHIP_POLARIS10}, // RX570 8G (Strix) {0x1002, 0x67df, 0x1043, 0x0517, 0, 0, CHIP_POLARIS10}, // RX580 (Strix) {0x1002, 0x67FF, 0x1043, 0x04BC, 0, 0, CHIP_POLARIS11}, // RX560