mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-28 13:34:38 +08:00
5b5c4e40a3
This patch adds the topology module to the driver. The topology is exposed to userspace through the sysfs. The calls to add and remove a device to/from topology are done by the radeon driver. v3: The CPU information, that is provided in the topology section of the amdkfd driver, is extracted from the CRAT table. Unlike the CPU information located in /sys/devices/system/cpu/cpu*, which is extracted from the SRAT table. While the CPU information provided by the CRAT and the SRAT tables might be identical, the node topology might be different. The SRAT table contains the topology of CPU nodes only. The CRAT table contains the topology of CPU and GPU nodes together (and can be interleaved). For example CPU node 1 in SRAT can be CPU node 3 in CRAT. Furthermore it's worth to mention that the CRAT table contains only HSA compatible nodes (nodes which are compliant with the HSA spec). To recap, amdkfd exposes a different kind of topology than the one exposed by /sys/devices/system/cpu/cpu even though it may contain similar information. v4: The topology module doesn't support uevent handling and doesn't notify the userspace about runtime modifications. It is up to the userspace to acquire snapshots of the topology information created by the amdkfd and exposed in sysfs. The following is an example of how the topology looks on a Kaveri A10-7850K system with amdkfd installed: /sys/devices/virtual/kfd/kfd/ | --- topology/ | |--- generation_id |--- system_properties |--- nodes/ | |--- 0/ | |--- gpu_id |--- name |--- properties |--- caches/ | |--- 0/ | |--- properties |--- 1/ | |--- properties |--- 2/ | |--- properties |--- io_links/ | |--- mem_banks/ | |--- 0/ | |--- properties |--- 1/ | |--- properties |--- 2/ | |--- properties |--- 3/ | |--- properties v5: Move amdkfd from drm/radeon/ to drm/amd/ Add a check if dev->gpu pointer is null before accessing it in the node_show function in kfd_topology.c This situation may occur when amdkfd is loaded and there is a GPU with a CRAT table, but that GPU isn't supported by amdkfd Signed-off-by: Evgeny Pinchuk <evgeny.pinchuk@amd.com> Signed-off-by: Oded Gabbay <oded.gabbay@amd.com>
138 lines
3.9 KiB
C
138 lines
3.9 KiB
C
/*
|
|
* Copyright 2014 Advanced Micro Devices, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include <linux/amd-iommu.h>
|
|
#include <linux/bsearch.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/slab.h>
|
|
#include "kfd_priv.h"
|
|
|
|
static const struct kfd_device_info kaveri_device_info = {
|
|
.max_pasid_bits = 16,
|
|
};
|
|
|
|
struct kfd_deviceid {
|
|
unsigned short did;
|
|
const struct kfd_device_info *device_info;
|
|
};
|
|
|
|
/* Please keep this sorted by increasing device id. */
|
|
static const struct kfd_deviceid supported_devices[] = {
|
|
{ 0x1304, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1305, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1306, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1307, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1309, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x130A, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x130B, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x130C, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x130D, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x130E, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x130F, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1310, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1311, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1312, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1313, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1315, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1316, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1317, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x1318, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x131B, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x131C, &kaveri_device_info }, /* Kaveri */
|
|
{ 0x131D, &kaveri_device_info }, /* Kaveri */
|
|
};
|
|
|
|
static const struct kfd_device_info *lookup_device_info(unsigned short did)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
|
|
if (supported_devices[i].did == did) {
|
|
BUG_ON(supported_devices[i].device_info == NULL);
|
|
return supported_devices[i].device_info;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev)
|
|
{
|
|
struct kfd_dev *kfd;
|
|
|
|
const struct kfd_device_info *device_info =
|
|
lookup_device_info(pdev->device);
|
|
|
|
if (!device_info)
|
|
return NULL;
|
|
|
|
kfd = kzalloc(sizeof(*kfd), GFP_KERNEL);
|
|
if (!kfd)
|
|
return NULL;
|
|
|
|
kfd->kgd = kgd;
|
|
kfd->device_info = device_info;
|
|
kfd->pdev = pdev;
|
|
|
|
return kfd;
|
|
}
|
|
|
|
bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
|
const struct kgd2kfd_shared_resources *gpu_resources)
|
|
{
|
|
kfd->shared_resources = *gpu_resources;
|
|
|
|
if (kfd_topology_add_device(kfd) != 0)
|
|
return false;
|
|
|
|
kfd->init_complete = true;
|
|
dev_info(kfd_device, "added device (%x:%x)\n", kfd->pdev->vendor,
|
|
kfd->pdev->device);
|
|
|
|
return true;
|
|
}
|
|
|
|
void kgd2kfd_device_exit(struct kfd_dev *kfd)
|
|
{
|
|
int err = kfd_topology_remove_device(kfd);
|
|
|
|
BUG_ON(err != 0);
|
|
|
|
kfree(kfd);
|
|
}
|
|
|
|
void kgd2kfd_suspend(struct kfd_dev *kfd)
|
|
{
|
|
BUG_ON(kfd == NULL);
|
|
}
|
|
|
|
int kgd2kfd_resume(struct kfd_dev *kfd)
|
|
{
|
|
BUG_ON(kfd == NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void kgd2kfd_interrupt(struct kfd_dev *dev, const void *ih_ring_entry)
|
|
{
|
|
}
|