scsi: scsi_proto: Add structures and constants related to I/O groups and streams

Prepare for adding code that will query the I/O advice hints group
descriptors and for adding code that will retrieve the stream status.

Cc: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240130214911.1863909-11-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Bart Van Assche 2024-01-30 13:48:36 -08:00 committed by Martin K. Petersen
parent 96b171d6db
commit 4977c0f452
4 changed files with 141 additions and 0 deletions

View file

@ -232,6 +232,11 @@ config SCSI_SCAN_ASYNC
Note that this setting also affects whether resuming from Note that this setting also affects whether resuming from
system suspend will be performed asynchronously. system suspend will be performed asynchronously.
config SCSI_PROTO_TEST
tristate "scsi_proto.h unit tests" if !KUNIT_ALL_TESTS
depends on SCSI && KUNIT
default KUNIT_ALL_TESTS
menu "SCSI Transports" menu "SCSI Transports"
depends on SCSI depends on SCSI

View file

@ -24,6 +24,8 @@ obj-$(CONFIG_SCSI_COMMON) += scsi_common.o
obj-$(CONFIG_RAID_ATTRS) += raid_class.o obj-$(CONFIG_RAID_ATTRS) += raid_class.o
obj-$(CONFIG_SCSI_PROTO_TEST) += scsi_proto_test.o
# --- NOTE ORDERING HERE --- # --- NOTE ORDERING HERE ---
# For kernel non-modular link, transport attributes need to # For kernel non-modular link, transport attributes need to
# be initialised before drivers # be initialised before drivers

View file

@ -0,0 +1,56 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2023 Google LLC
*/
#include <kunit/test.h>
#include <asm-generic/unaligned.h>
#include <scsi/scsi_proto.h>
static void test_scsi_proto(struct kunit *test)
{
static const union {
struct scsi_io_group_descriptor desc;
u8 arr[sizeof(struct scsi_io_group_descriptor)];
} d = { .arr = { 0x45, 0, 0, 0, 0xb0, 0xe4, 0xe3 } };
KUNIT_EXPECT_EQ(test, d.desc.io_advice_hints_mode + 0, 1);
KUNIT_EXPECT_EQ(test, d.desc.st_enble + 0, 1);
KUNIT_EXPECT_EQ(test, d.desc.cs_enble + 0, 0);
KUNIT_EXPECT_EQ(test, d.desc.ic_enable + 0, 1);
KUNIT_EXPECT_EQ(test, d.desc.acdlu + 0, 1);
KUNIT_EXPECT_EQ(test, d.desc.rlbsr + 0, 3);
KUNIT_EXPECT_EQ(test, d.desc.lbm_descriptor_type + 0, 0);
KUNIT_EXPECT_EQ(test, d.desc.params[0] + 0, 0xe4);
KUNIT_EXPECT_EQ(test, d.desc.params[1] + 0, 0xe3);
static const union {
struct scsi_stream_status s;
u8 arr[sizeof(struct scsi_stream_status)];
} ss = { .arr = { 0x80, 0, 0x12, 0x34, 0x3f } };
KUNIT_EXPECT_EQ(test, ss.s.perm + 0, 1);
KUNIT_EXPECT_EQ(test, get_unaligned_be16(&ss.s.stream_identifier),
0x1234);
KUNIT_EXPECT_EQ(test, ss.s.rel_lifetime + 0, 0x3f);
static const union {
struct scsi_stream_status_header h;
u8 arr[sizeof(struct scsi_stream_status_header)];
} sh = { .arr = { 1, 2, 3, 4, 0, 0, 5, 6 } };
KUNIT_EXPECT_EQ(test, get_unaligned_be32(&sh.h.len), 0x1020304);
KUNIT_EXPECT_EQ(test, get_unaligned_be16(&sh.h.number_of_open_streams),
0x506);
}
static struct kunit_case scsi_proto_test_cases[] = {
KUNIT_CASE(test_scsi_proto),
{}
};
static struct kunit_suite scsi_proto_test_suite = {
.name = "scsi_proto",
.test_cases = scsi_proto_test_cases,
};
kunit_test_suite(scsi_proto_test_suite);
MODULE_DESCRIPTION("<scsi/scsi_proto.h> unit tests");
MODULE_AUTHOR("Bart Van Assche");
MODULE_LICENSE("GPL");

View file

@ -10,6 +10,7 @@
#ifndef _SCSI_PROTO_H_ #ifndef _SCSI_PROTO_H_
#define _SCSI_PROTO_H_ #define _SCSI_PROTO_H_
#include <linux/build_bug.h>
#include <linux/types.h> #include <linux/types.h>
/* /*
@ -126,6 +127,7 @@
#define SAI_READ_CAPACITY_16 0x10 #define SAI_READ_CAPACITY_16 0x10
#define SAI_GET_LBA_STATUS 0x12 #define SAI_GET_LBA_STATUS 0x12
#define SAI_REPORT_REFERRALS 0x13 #define SAI_REPORT_REFERRALS 0x13
#define SAI_GET_STREAM_STATUS 0x16
/* values for maintenance in */ /* values for maintenance in */
#define MI_REPORT_IDENTIFYING_INFORMATION 0x05 #define MI_REPORT_IDENTIFYING_INFORMATION 0x05
#define MI_REPORT_TARGET_PGS 0x0a #define MI_REPORT_TARGET_PGS 0x0a
@ -275,6 +277,82 @@ struct scsi_lun {
__u8 scsi_lun[8]; __u8 scsi_lun[8];
}; };
/* SBC-5 IO advice hints group descriptor */
struct scsi_io_group_descriptor {
#if defined(__BIG_ENDIAN)
u8 io_advice_hints_mode: 2;
u8 reserved1: 3;
u8 st_enble: 1;
u8 cs_enble: 1;
u8 ic_enable: 1;
#elif defined(__LITTLE_ENDIAN)
u8 ic_enable: 1;
u8 cs_enble: 1;
u8 st_enble: 1;
u8 reserved1: 3;
u8 io_advice_hints_mode: 2;
#else
#error
#endif
u8 reserved2[3];
/* Logical block markup descriptor */
#if defined(__BIG_ENDIAN)
u8 acdlu: 1;
u8 reserved3: 1;
u8 rlbsr: 2;
u8 lbm_descriptor_type: 4;
#elif defined(__LITTLE_ENDIAN)
u8 lbm_descriptor_type: 4;
u8 rlbsr: 2;
u8 reserved3: 1;
u8 acdlu: 1;
#else
#error
#endif
u8 params[2];
u8 reserved4;
u8 reserved5[8];
};
static_assert(sizeof(struct scsi_io_group_descriptor) == 16);
/* SCSI stream status descriptor */
struct scsi_stream_status {
#if defined(__BIG_ENDIAN)
u8 perm: 1;
u8 reserved1: 7;
#elif defined(__LITTLE_ENDIAN)
u8 reserved1: 7;
u8 perm: 1;
#else
#error
#endif
u8 reserved2;
__be16 stream_identifier;
#if defined(__BIG_ENDIAN)
u8 reserved3: 2;
u8 rel_lifetime: 6;
#elif defined(__LITTLE_ENDIAN)
u8 rel_lifetime: 6;
u8 reserved3: 2;
#else
#error
#endif
u8 reserved4[3];
};
static_assert(sizeof(struct scsi_stream_status) == 8);
/* GET STREAM STATUS parameter data */
struct scsi_stream_status_header {
__be32 len; /* length in bytes of stream_status[] array. */
u16 reserved;
__be16 number_of_open_streams;
DECLARE_FLEX_ARRAY(struct scsi_stream_status, stream_status);
};
static_assert(sizeof(struct scsi_stream_status_header) == 8);
/* SPC asymmetric access states */ /* SPC asymmetric access states */
#define SCSI_ACCESS_STATE_OPTIMAL 0x00 #define SCSI_ACCESS_STATE_OPTIMAL 0x00
#define SCSI_ACCESS_STATE_ACTIVE 0x01 #define SCSI_ACCESS_STATE_ACTIVE 0x01