summaryrefslogtreecommitdiffstats
path: root/kernel/version/version.c
blob: 745be97ef7b296fc9778d2d9d1da37234caf208f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Driver Version Adaptation Layer
 * Handles interface differences between NVIDIA driver versions
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/version.h>

#include "version.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Open-IOV");
MODULE_DESCRIPTION("Driver Version Adaptation Layer");

/* Version 550 interface */
static struct driver_interface interface_550 = {
    .version = "550",
    .major = 550,
    .minor = 0,
    .has_vgpu_vfio = true,
    .has_migration = true,
    .has_scheduling = true,
    .has_notifications = true,
    .has_wpr = true,
    .vgpu_vfio_ops_size = sizeof(struct nvidia_vgpu_vfio_ops),
    .mdev_parent_ops_size = sizeof(struct nv_vgpu_mdev_parent_ops),
};

/* Version 560 interface */
static struct driver_interface interface_560 = {
    .version = "560",
    .major = 560,
    .minor = 0,
    .has_vgpu_vfio = true,
    .has_migration = true,
    .has_scheduling = true,
    .has_notifications = true,
    .has_wpr = true,
    .vgpu_vfio_ops_size = sizeof(struct nvidia_vgpu_vfio_ops),
    .mdev_parent_ops_size = sizeof(struct nv_vgpu_mdev_parent_ops),
};

/* Version 570 interface */
static struct driver_interface interface_570 = {
    .version = "570",
    .major = 570,
    .minor = 0,
    .has_vgpu_vfio = true,
    .has_migration = true,
    .has_scheduling = true,
    .has_notifications = true,
    .has_wpr = true,
    .vgpu_vfio_ops_size = sizeof(struct nvidia_vgpu_vfio_ops),
    .mdev_parent_ops_size = sizeof(struct nv_vgpu_mdev_parent_ops),
};

/* Version 580 interface */
static struct driver_interface interface_580 = {
    .version = "580",
    .major = 580,
    .minor = 0,
    .has_vgpu_vfio = true,
    .has_migration = true,
    .has_scheduling = true,
    .has_notifications = true,
    .has_wpr = true,
    .vgpu_vfio_ops_size = sizeof(struct nvidia_vgpu_vfio_ops),
    .mdev_parent_ops_size = sizeof(struct nv_vgpu_mdev_parent_ops),
};

static struct driver_interface *interfaces[] = {
    &interface_550,
    &interface_560,
    &interface_570,
    &interface_580,
    NULL
};

struct driver_interface *version_get_interface(const char *version_str)
{
    int major = 0, minor = 0;
    
    if (version_str) {
        sscanf(version_str, "%d.%d", &major, &minor);
    }
    
    for (int i = 0; interfaces[i]; i++) {
        if (interfaces[i]->major == major)
            return interfaces[i];
    }
    
    /* Default to latest known */
    return &interface_570;
}

struct driver_interface *version_get_by_kernel_version(void)
{
    /* Try to detect from kernel version or module version */
    return &interface_570;
}

bool version_has_feature(struct driver_interface *iface, enum driver_feature feature)
{
    if (!iface)
        return false;
    
    switch (feature) {
        case DRV_FEAT_VGPU_VFIO:
            return iface->has_vgpu_vfio;
        case DRV_FEAT_MIGRATION:
            return iface->has_migration;
        case DRV_FEAT_SCHEDULING:
            return iface->has_scheduling;
        case DRV_FEAT_NOTIFICATIONS:
            return iface->has_notifications;
        case DRV_FEAT_WPR:
            return iface->has_wpr;
        default:
            return false;
    }
}

const char *version_get_string(struct driver_interface *iface)
{
    return iface ? iface->version : "unknown";
}

EXPORT_SYMBOL_GPL(version_get_interface);
EXPORT_SYMBOL_GPL(version_get_by_kernel_version);
EXPORT_SYMBOL_GPL(version_has_feature);
EXPORT_SYMBOL_GPL(version_get_string);

MODULE_DESCRIPTION("Driver Version Adaptation Layer");
MODULE_LICENSE("GPL");