@@ -401,6 +401,9 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
case GVE_ADMINQ_GET_PTYPE_MAP:
priv->adminq_get_ptype_map_cnt++;
break;
+ case GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY:
+ priv->adminq_verify_driver_compatibility_cnt++;
+ break;
default:
PMD_DRV_LOG(ERR, "unknown AQ command opcode %d", opcode);
}
@@ -859,6 +862,22 @@ int gve_adminq_report_stats(struct gve_priv *priv, u64 stats_report_len,
return gve_adminq_execute_cmd(priv, &cmd);
}
+int gve_adminq_verify_driver_compatibility(struct gve_priv *priv,
+ u64 driver_info_len,
+ dma_addr_t driver_info_addr)
+{
+ union gve_adminq_command cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = cpu_to_be32(GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY);
+ cmd.verify_driver_compatibility = (struct gve_adminq_verify_driver_compatibility) {
+ .driver_info_len = cpu_to_be64(driver_info_len),
+ .driver_info_addr = cpu_to_be64(driver_info_addr),
+ };
+
+ return gve_adminq_execute_cmd(priv, &cmd);
+}
+
int gve_adminq_report_link_speed(struct gve_priv *priv)
{
struct gve_dma_mem link_speed_region_dma_mem;
@@ -23,6 +23,7 @@ enum gve_adminq_opcodes {
GVE_ADMINQ_REPORT_STATS = 0xC,
GVE_ADMINQ_REPORT_LINK_SPEED = 0xD,
GVE_ADMINQ_GET_PTYPE_MAP = 0xE,
+ GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY = 0xF,
};
/* Admin queue status codes */
@@ -145,6 +146,48 @@ enum gve_sup_feature_mask {
};
#define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0
+#define GVE_VERSION_STR_LEN 128
+
+enum gve_driver_capbility {
+ gve_driver_capability_gqi_qpl = 0,
+ gve_driver_capability_gqi_rda = 1,
+ gve_driver_capability_dqo_qpl = 2, /* reserved for future use */
+ gve_driver_capability_dqo_rda = 3,
+};
+
+#define GVE_CAP1(a) BIT((int)a)
+#define GVE_CAP2(a) BIT(((int)a) - 64)
+#define GVE_CAP3(a) BIT(((int)a) - 128)
+#define GVE_CAP4(a) BIT(((int)a) - 192)
+
+#define GVE_DRIVER_CAPABILITY_FLAGS1 \
+ (GVE_CAP1(gve_driver_capability_gqi_qpl) | \
+ GVE_CAP1(gve_driver_capability_gqi_rda) | \
+ GVE_CAP1(gve_driver_capability_dqo_rda))
+
+#define GVE_DRIVER_CAPABILITY_FLAGS2 0x0
+#define GVE_DRIVER_CAPABILITY_FLAGS3 0x0
+#define GVE_DRIVER_CAPABILITY_FLAGS4 0x0
+
+struct gve_driver_info {
+ u8 os_type; /* 0x01 = Linux */
+ u8 driver_major;
+ u8 driver_minor;
+ u8 driver_sub;
+ __be32 os_version_major;
+ __be32 os_version_minor;
+ __be32 os_version_sub;
+ __be64 driver_capability_flags[4];
+ u8 os_version_str1[GVE_VERSION_STR_LEN];
+ u8 os_version_str2[GVE_VERSION_STR_LEN];
+};
+
+struct gve_adminq_verify_driver_compatibility {
+ __be64 driver_info_len;
+ __be64 driver_info_addr;
+};
+
+GVE_CHECK_STRUCT_LEN(16, gve_adminq_verify_driver_compatibility);
struct gve_adminq_configure_device_resources {
__be64 counter_array;
@@ -345,6 +388,8 @@ union gve_adminq_command {
struct gve_adminq_report_stats report_stats;
struct gve_adminq_report_link_speed report_link_speed;
struct gve_adminq_get_ptype_map get_ptype_map;
+ struct gve_adminq_verify_driver_compatibility
+ verify_driver_compatibility;
};
};
u8 reserved[64];
@@ -377,5 +422,8 @@ int gve_adminq_report_link_speed(struct gve_priv *priv);
struct gve_ptype_lut;
int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv,
struct gve_ptype_lut *ptype_lut);
+int gve_adminq_verify_driver_compatibility(struct gve_priv *priv,
+ u64 driver_info_len,
+ dma_addr_t driver_info_addr);
#endif /* _GVE_ADMINQ_H */
@@ -21,6 +21,9 @@
#include <rte_malloc.h>
#include <rte_memcpy.h>
#include <rte_memzone.h>
+#include <rte_version.h>
+#include <linux/version.h>
+#include <sys/utsname.h>
#include "../gve_logs.h"
@@ -82,6 +85,11 @@ typedef rte_iova_t dma_addr_t;
{ gve_static_assert_##X = (n) / ((sizeof(struct X) == (n)) ? 1 : 0) }
#define GVE_CHECK_UNION_LEN(n, X) enum gve_static_asset_enum_##X \
{ gve_static_assert_##X = (n) / ((sizeof(union X) == (n)) ? 1 : 0) }
+#ifndef LINUX_VERSION_MAJOR
+#define LINUX_VERSION_MAJOR (((LINUX_VERSION_CODE) >> 16) & 0xff)
+#define LINUX_VERSION_SUBLEVEL (((LINUX_VERSION_CODE) >> 8) & 0xff)
+#define LINUX_VERSION_PATCHLEVEL ((LINUX_VERSION_CODE) & 0xff)
+#endif
static __rte_always_inline u8
readb(volatile void *addr)
@@ -314,6 +314,60 @@ gve_dev_close(struct rte_eth_dev *dev)
return err;
}
+static int
+gve_verify_driver_compatibility(struct gve_priv *priv)
+{
+ const struct rte_memzone *driver_info_bus;
+ struct gve_driver_info *driver_info;
+ struct utsname uts;
+ char *release;
+ int err;
+
+ driver_info_bus = rte_memzone_reserve_aligned("verify_driver_compatibility",
+ sizeof(struct gve_driver_info),
+ rte_socket_id(),
+ RTE_MEMZONE_IOVA_CONTIG,
+ PAGE_SIZE);
+ if (driver_info_bus == NULL) {
+ PMD_DRV_LOG(ERR, "Could not alloc memzone for driver compatibility");
+ return -ENOMEM;
+ }
+ driver_info = (struct gve_driver_info *)driver_info_bus->addr;
+ *driver_info = (struct gve_driver_info) {
+ .os_type = 1, /* Linux */
+ .os_version_major = cpu_to_be32(LINUX_VERSION_MAJOR),
+ .os_version_minor = cpu_to_be32(LINUX_VERSION_SUBLEVEL),
+ .os_version_sub = cpu_to_be32(LINUX_VERSION_PATCHLEVEL),
+ .driver_capability_flags = {
+ cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS1),
+ cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS2),
+ cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS3),
+ cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS4),
+ },
+ };
+
+ if (uname(&uts) > 0)
+ release = uts.release;
+
+ /* OS version */
+ rte_strscpy((char *)driver_info->os_version_str1, release,
+ sizeof(driver_info->os_version_str1));
+ /* DPDK version */
+ rte_strscpy((char *)driver_info->os_version_str2, rte_version(),
+ sizeof(driver_info->os_version_str2));
+
+ err = gve_adminq_verify_driver_compatibility(priv,
+ sizeof(struct gve_driver_info),
+ (dma_addr_t)driver_info_bus);
+
+ /* It's ok if the device doesn't support this */
+ if (err == -EOPNOTSUPP)
+ err = 0;
+
+ rte_memzone_free(driver_info_bus);
+ return err;
+}
+
static int
gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
{
@@ -625,6 +679,12 @@ gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
return err;
}
+ err = gve_verify_driver_compatibility(priv);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Could not verify driver compatibility: err=%d", err);
+ goto free_adminq;
+ }
+
if (skip_describe_device)
goto setup_device;
@@ -250,6 +250,7 @@ struct gve_priv {
uint32_t adminq_report_stats_cnt;
uint32_t adminq_report_link_speed_cnt;
uint32_t adminq_get_ptype_map_cnt;
+ uint32_t adminq_verify_driver_compatibility_cnt;
volatile uint32_t state_flags;