block:vblk: Resolve compile error tegra_vblk V6.11

Method to configure the struct queue_limits has changed
from kernel v6.11.
The following API's are removed from v6.11
[1] blk_queue_max_secure_erase_sectors
[2] blk_queue_max_discard_sectors
[3] blk_queue_write_cache
[4] blk_queue_logical_block_size
[5] blk_queue_physical_block_size
[6] blk_queue_max_hw_sectors
[7] The semantics of the flag QUEUE_FLAG_NONROT
is set as default value for queues, so this flag
is removed in v6.11.
[8] The flag BLK_MQ_F_SHOULD_MERGE is not valid in
v6.14

The above API's are replaced by direct
assignment to the queue_limits and use the new API
queue_limits_set. This API takes the incoming
values, validates, populates the other members
of the struct accordingly and assigns the
provided queue_limits to the corresponding queue.

The change contains:
 [1] Addition of new approach that is compatible
with v6.11
 [2] Addition of a macro (NV_BLOCK_USE_QUEUE_LIMITS_SET)
for backward compatibility
 [3] This is a special case where both the variable
and the function needs to be present for the macro to be
enabled. The changes were made accordingly.
 [4] The flag BLK_MQ_F_SHOULD_MERGE is protected by
macro

Bug 4311184

Signed-off-by: gokull <gokull@nvidia.com>
Change-Id: Ida2c12de0977f6405e7cc7dec946cf0f64413c97
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3303900
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
gokull
2025-02-16 22:32:59 +00:00
committed by Jon Hunter
parent b63a822a1b
commit d8a3d29fed
4 changed files with 139 additions and 48 deletions

View File

@@ -1,21 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Makefile for Virtual Storage Driver
#
LINUX_VERSION := $(shell expr $(VERSION) \* 256 + $(PATCHLEVEL))
LINUX_VERSION_6_11 := $(shell expr 6 \* 256 + 11)
# Use dummy driver for Kernel versions greater than or equal to Linux v6.11
ifeq ($(shell test $(LINUX_VERSION) -ge $(LINUX_VERSION_6_11); echo $$?),0)
tegra_vblk-y += tegra_hv_vblk_dummy.o
else
tegra_vblk-y += tegra_hv_vblk.o
tegra_vblk-y += tegra_hv_ioctl.o
tegra_vblk-y += tegra_hv_mmc.o
tegra_vblk-y += tegra_hv_scsi.o
tegra_vblk-y += tegra_hv_ufs.o
endif
obj-m += tegra_vblk.o

View File

@@ -17,7 +17,6 @@
#include <linux/kdev_t.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/version.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <uapi/linux/sched/types.h>
@@ -35,11 +34,17 @@
#include <linux/dma-mapping.h>
#include <asm/cacheflush.h>
#include <linux/version.h>
#include <linux/blkdev.h>
#if (IS_ENABLED(CONFIG_TEGRA_HSIERRRPTINJ))
#include <linux/tegra-hsierrrptinj.h>
#endif
#include "tegra_vblk.h"
#if defined(NV_QUEUE_LIMITS_STRUCT_HAS_FEATURES) \
&& (NV_IS_EXPORT_SYMBOL_PRESENT_queue_limits_set == 1)
#define NV_BLOCK_USE_QUEUE_LIMITS_SET
#endif
#define DISCARD_ERASE_SECERASE_MASK (VS_BLK_DISCARD_OP_F | \
VS_BLK_SECURE_ERASE_OP_F | \
VS_BLK_ERASE_OP_F)
@@ -1103,14 +1108,18 @@ static void setup_ioctl_device(struct vblk_dev *vblkdev)
{
int ret;
#if defined(NV_BLOCK_USE_QUEUE_LIMITS_SET)
struct queue_limits limits;
#endif
memset(&vblkdev->ioctl_tag_set, 0, sizeof(vblkdev->tag_set));
vblkdev->ioctl_tag_set.ops = &vblk_mq_ops;
vblkdev->ioctl_tag_set.nr_hw_queues = 1;
vblkdev->ioctl_tag_set.nr_maps = 1;
vblkdev->ioctl_tag_set.queue_depth = 16;
vblkdev->ioctl_tag_set.numa_node = NUMA_NO_NODE;
#if defined(NV_BLK_MQ_F_SHOULD_MERGE) /* Linux 6.14 */
vblkdev->ioctl_tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
#endif
ret = blk_mq_alloc_tag_set(&vblkdev->ioctl_tag_set);
if (ret) {
dev_err(vblkdev->device, "failed to allocate tag set\n");
@@ -1130,12 +1139,24 @@ static void setup_ioctl_device(struct vblk_dev *vblkdev)
vblkdev->ioctl_queue->queuedata = vblkdev;
#if defined(NV_BLOCK_USE_QUEUE_LIMITS_SET)
limits.physical_block_size = vblkdev->config.blk_config.hardblk_size;
limits.logical_block_size = vblkdev->config.blk_config.hardblk_size;
limits.io_min = vblkdev->config.blk_config.hardblk_size;
limits.io_opt = vblkdev->config.blk_config.hardblk_size;
if (queue_limits_set(vblkdev->ioctl_queue, &limits) != 0) {
dev_err(vblkdev->device, "failed to set queue limits\n");
blk_mq_free_tag_set(&vblkdev->ioctl_tag_set);
return;
}
#else
blk_queue_logical_block_size(vblkdev->ioctl_queue,
vblkdev->config.blk_config.hardblk_size);
blk_queue_physical_block_size(vblkdev->ioctl_queue,
vblkdev->config.blk_config.hardblk_size);
blk_queue_flag_set(QUEUE_FLAG_NONROT, vblkdev->ioctl_queue);
#endif
/* And the gendisk structure. */
#if defined(NV_BLK_MQ_ALLOC_DISK_FOR_QUEUE_PRESENT) /* Linux v6.0 */
@@ -1179,6 +1200,10 @@ static void setup_ioctl_device(struct vblk_dev *vblkdev)
/* Set up virtual device. */
static void setup_device(struct vblk_dev *vblkdev)
{
#if defined(NV_BLOCK_USE_QUEUE_LIMITS_SET)
struct queue_limits limits;
#endif
uint32_t max_io_bytes;
uint32_t req_id;
uint32_t max_requests;
@@ -1200,8 +1225,9 @@ static void setup_device(struct vblk_dev *vblkdev)
vblkdev->tag_set.nr_maps = 1;
vblkdev->tag_set.queue_depth = 16;
vblkdev->tag_set.numa_node = NUMA_NO_NODE;
#if defined(NV_BLK_MQ_F_SHOULD_MERGE) /* Linux 6.14 */
vblkdev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
#endif
ret = blk_mq_alloc_tag_set(&vblkdev->tag_set);
if (ret)
return;
@@ -1219,13 +1245,26 @@ static void setup_device(struct vblk_dev *vblkdev)
vblkdev->queue->queuedata = vblkdev;
#if defined(NV_BLOCK_USE_QUEUE_LIMITS_SET)
limits.physical_block_size = vblkdev->config.blk_config.hardblk_size;
limits.logical_block_size = vblkdev->config.blk_config.hardblk_size;
limits.io_min = vblkdev->config.blk_config.hardblk_size;
limits.io_opt = vblkdev->config.blk_config.hardblk_size;
#else
blk_queue_logical_block_size(vblkdev->queue,
vblkdev->config.blk_config.hardblk_size);
blk_queue_physical_block_size(vblkdev->queue,
vblkdev->config.blk_config.hardblk_size);
#endif
if (vblkdev->config.blk_config.req_ops_supported & VS_BLK_FLUSH_OP_F) {
#if defined(NV_BLOCK_USE_QUEUE_LIMITS_SET)
limits.features |= (BLK_FEAT_WRITE_CACHE &
!(BLK_FLAG_WRITE_CACHE_DISABLED) &
!(BLK_FEAT_FUA));
#else
blk_queue_write_cache(vblkdev->queue, true, false);
#endif
}
if (vblkdev->config.blk_config.max_read_blks_per_io !=
@@ -1244,6 +1283,60 @@ static void setup_device(struct vblk_dev *vblkdev)
return;
}
#if defined(NV_BLOCK_USE_QUEUE_LIMITS_SET) && defined(NV_BLK_QUEUE_MAX_HW_SECTORS_PRESENT)
limits.max_hw_sectors = max_io_bytes / SECTOR_SIZE;
#elif defined(NV_BLK_QUEUE_MAX_HW_SECTORS_PRESENT) /* Removed in Linux v6.10 */
blk_queue_max_hw_sectors(vblkdev->queue, max_io_bytes / SECTOR_SIZE);
#endif
if ((vblkdev->config.blk_config.req_ops_supported & VS_BLK_SECURE_ERASE_OP_F)
|| (vblkdev->config.blk_config.req_ops_supported & VS_BLK_ERASE_OP_F)) {
#if defined(QUEUE_FLAG_SECERASE) /* Removed in Linux 5.19 */
/*
* FIXME: Support for Linux v5.19+ kernels
*/
blk_queue_flag_set(QUEUE_FLAG_SECERASE, vblkdev->queue);
#elif defined(NV_BLOCK_USE_QUEUE_LIMITS_SET)
limits.max_secure_erase_sectors = vblkdev->config.blk_config.max_erase_blks_per_io;
#else
blk_queue_max_secure_erase_sectors(vblkdev->queue,
vblkdev->config.blk_config.max_erase_blks_per_io);
#endif
}
if ((vblkdev->config.blk_config.req_ops_supported & VS_BLK_DISCARD_OP_F)
|| (((vblkdev->config.blk_config.req_ops_supported & VS_BLK_SECURE_ERASE_OP_F)
|| (vblkdev->config.blk_config.req_ops_supported & VS_BLK_ERASE_OP_F))
&& vblkdev->config.phys_dev == VSC_DEV_UFS)) {
#if defined(QUEUE_FLAG_DISCARD) /* Removed in Linux v5.19 */
/*
* FIXME: Support for Linux v5.19+ kernels
*/
blk_queue_flag_set(QUEUE_FLAG_DISCARD, vblkdev->queue);
#endif
#if defined(NV_BLOCK_USE_QUEUE_LIMITS_SET)
limits.max_discard_segments = vblkdev->config.blk_config.max_erase_blks_per_io;
limits.discard_granularity = vblkdev->config.blk_config.hardblk_size;
#else
blk_queue_max_discard_sectors(vblkdev->queue,
vblkdev->config.blk_config.max_erase_blks_per_io);
vblkdev->queue->limits.discard_granularity =
vblkdev->config.blk_config.hardblk_size;
#endif
print_erase_op_supported(vblkdev->device,
vblkdev->config.blk_config.req_ops_supported);
}
#if defined(NV_BLOCK_USE_QUEUE_LIMITS_SET)
if (queue_limits_set(vblkdev->queue, &limits) != 0) {
dev_err(vblkdev->device, "failed to set queue limits\n");
blk_mq_free_tag_set(&vblkdev->tag_set);
return;
}
#else
blk_queue_flag_set(QUEUE_FLAG_NONROT, vblkdev->queue);
#endif
/* reserve mempool for eMMC device and for ufs device
* with pass through support
*/
@@ -1394,40 +1487,6 @@ static void setup_device(struct vblk_dev *vblkdev)
vblkdev->max_requests = max_requests;
vblkdev->max_ioctl_requests = max_ioctl_requests;
#if defined(NV_BLK_QUEUE_MAX_HW_SECTORS_PRESENT) /* Removed in Linux v6.10 */
blk_queue_max_hw_sectors(vblkdev->queue, max_io_bytes / SECTOR_SIZE);
#endif
blk_queue_flag_set(QUEUE_FLAG_NONROT, vblkdev->queue);
if ((vblkdev->config.blk_config.req_ops_supported & VS_BLK_SECURE_ERASE_OP_F)
|| (vblkdev->config.blk_config.req_ops_supported & VS_BLK_ERASE_OP_F))
#if defined(QUEUE_FLAG_SECERASE) /* Removed in Linux 5.19 */
/*
* FIXME: Support for Linux v5.19+ kernels
*/
blk_queue_flag_set(QUEUE_FLAG_SECERASE, vblkdev->queue);
#else
blk_queue_max_secure_erase_sectors(vblkdev->queue,
vblkdev->config.blk_config.max_erase_blks_per_io);
#endif
if ((vblkdev->config.blk_config.req_ops_supported & VS_BLK_DISCARD_OP_F)
|| (((vblkdev->config.blk_config.req_ops_supported & VS_BLK_SECURE_ERASE_OP_F)
|| (vblkdev->config.blk_config.req_ops_supported & VS_BLK_ERASE_OP_F))
&& vblkdev->config.phys_dev == VSC_DEV_UFS)) {
#if defined(QUEUE_FLAG_DISCARD) /* Removed in Linux v5.19 */
/*
* FIXME: Support for Linux v5.19+ kernels
*/
blk_queue_flag_set(QUEUE_FLAG_DISCARD, vblkdev->queue);
#endif
blk_queue_max_discard_sectors(vblkdev->queue,
vblkdev->config.blk_config.max_erase_blks_per_io);
vblkdev->queue->limits.discard_granularity =
vblkdev->config.blk_config.hardblk_size;
print_erase_op_supported(vblkdev->device,
vblkdev->config.blk_config.req_ops_supported);
}
/* And the gendisk structure. */
#if defined(NV_BLK_MQ_ALLOC_DISK_FOR_QUEUE_PRESENT) /* Linux v6.0 */

View File

@@ -100,6 +100,8 @@ NV_CONFTEST_FUNCTION_COMPILE_TESTS += blk_mq_destroy_queue
NV_CONFTEST_FUNCTION_COMPILE_TESTS += blk_queue_max_hw_sectors
NV_CONFTEST_FUNCTION_COMPILE_TESTS += block_device_operations_open_has_gendisk_arg
NV_CONFTEST_FUNCTION_COMPILE_TESTS += block_device_operations_release_has_no_mode_arg
NV_CONFTEST_FUNCTION_COMPILE_TESTS += queue_limits_struct_has_features
NV_CONFTEST_FUNCTION_COMPILE_TESTS += blk_mq_f_should_merge
NV_CONFTEST_FUNCTION_COMPILE_TESTS += bus_type_struct_match_has_const_drv_arg
NV_CONFTEST_FUNCTION_COMPILE_TESTS += bus_type_struct_remove_has_int_return_type
NV_CONFTEST_FUNCTION_COMPILE_TESTS += bus_type_struct_uevent_has_const_dev_arg
@@ -224,6 +226,7 @@ NV_CONFTEST_FUNCTION_COMPILE_TESTS += vm_area_struct_has_const_vm_flags
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_property_read_reg
NV_CONFTEST_GENERIC_COMPILE_TESTS += is_export_symbol_present_drm_gem_prime_fd_to_handle
NV_CONFTEST_GENERIC_COMPILE_TESTS += is_export_symbol_present_drm_gem_prime_handle_to_fd
NV_CONFTEST_GENERIC_COMPILE_TESTS += is_export_symbol_present_queue_limits_set
NV_CONFTEST_FUNCTION_COMPILE_TESTS += crypto_engine_ctx_struct_removed_test
NV_CONFTEST_MACRO_COMPILE_TESTS ?=
NV_CONFTEST_SYMBOL_COMPILE_TESTS ?=

View File

@@ -6724,6 +6724,44 @@ compile_test() {
"NV_BLOCK_DEVICE_OPERATIONS_RELEASE_HAS_NO_MODE_ARG" "" "types"
;;
blk_mq_f_should_merge)
#
# Determine if the BLK_MQ_F_SHOULD_MERGE is present.
#
# In Linux v6.14, commit cc76ace465d6 ("block: remove BLK_MQ_F_SHOULD_MERGE")
# removed the definition BLK_MQ_F_SHOULD_MERGE.
#
CODE="
#include <linux/blk-mq.h>
int conftest_blk_mq_f_should_merge(void) {
return BLK_MQ_F_SHOULD_MERGE;
}"
compile_check_conftest "$CODE" \
"NV_BLK_MQ_F_SHOULD_MERGE" "" "types"
;;
queue_limits_struct_has_features)
#
# Determine if the 'queue_limits' needs to use
# the latest set of API's
# The queue_limit set has 2 situations:
# 1. The API queue_limits_set is present but
# queue_limits.features is not present.
# 2. Both the API and queue_limits.features
# are present.
#
# Another macro is derived from this macro
# in nv_hv_vblk.c
CODE="
#include <linux/blkdev.h>
int conftest_set_queue_limits(void) {
return offsetof(struct queue_limits, features);
}"
compile_check_conftest "$CODE" \
"NV_QUEUE_LIMITS_STRUCT_HAS_FEATURES" "" "types"
;;
bus_type_struct_match_has_const_drv_arg)
#
# Determine if the 'match' callback from the 'bus_type' structure