Merge tag 'firewire-fixes-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / scsi / scsi_lib_test.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * KUnit tests for scsi_lib.c.
4  *
5  * Copyright (C) 2023, Oracle Corporation
6  */
7 #include <kunit/test.h>
8
9 #include <scsi/scsi_proto.h>
10 #include <scsi/scsi_cmnd.h>
11 #include <scsi/scsi_device.h>
12
13 #define SCSI_LIB_TEST_MAX_ALLOWED 3
14 #define SCSI_LIB_TEST_TOTAL_MAX_ALLOWED 5
15
16 static void scsi_lib_test_multiple_sense(struct kunit *test)
17 {
18         struct scsi_failure multiple_sense_failure_defs[] = {
19                 {
20                         .sense = DATA_PROTECT,
21                         .asc = 0x1,
22                         .ascq = 0x1,
23                         .result = SAM_STAT_CHECK_CONDITION,
24                 },
25                 {
26                         .sense = UNIT_ATTENTION,
27                         .asc = 0x11,
28                         .ascq = 0x0,
29                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
30                         .result = SAM_STAT_CHECK_CONDITION,
31                 },
32                 {
33                         .sense = NOT_READY,
34                         .asc = 0x11,
35                         .ascq = 0x22,
36                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
37                         .result = SAM_STAT_CHECK_CONDITION,
38                 },
39                 {
40                         .sense = ABORTED_COMMAND,
41                         .asc = 0x11,
42                         .ascq = SCMD_FAILURE_ASCQ_ANY,
43                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
44                         .result = SAM_STAT_CHECK_CONDITION,
45                 },
46                 {
47                         .sense = HARDWARE_ERROR,
48                         .asc = SCMD_FAILURE_ASC_ANY,
49                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
50                         .result = SAM_STAT_CHECK_CONDITION,
51                 },
52                 {
53                         .sense = ILLEGAL_REQUEST,
54                         .asc = 0x91,
55                         .ascq = 0x36,
56                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
57                         .result = SAM_STAT_CHECK_CONDITION,
58                 },
59                 {}
60         };
61         struct scsi_failures failures = {
62                 .failure_definitions = multiple_sense_failure_defs,
63         };
64         u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
65         struct scsi_cmnd sc = {
66                 .sense_buffer = sense,
67         };
68         int i;
69
70         /* Match end of array */
71         scsi_build_sense(&sc, 0, ILLEGAL_REQUEST, 0x91, 0x36);
72         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
73         /* Basic match in array */
74         scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x11, 0x0);
75         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
76         /* No matching sense entry */
77         scsi_build_sense(&sc, 0, MISCOMPARE, 0x11, 0x11);
78         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
79         /* Match using SCMD_FAILURE_ASCQ_ANY */
80         scsi_build_sense(&sc, 0, ABORTED_COMMAND, 0x11, 0x22);
81         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
82         /* Fail to match */
83         scsi_build_sense(&sc, 0, ABORTED_COMMAND, 0x22, 0x22);
84         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
85         /* Match using SCMD_FAILURE_ASC_ANY */
86         scsi_build_sense(&sc, 0, HARDWARE_ERROR, 0x11, 0x22);
87         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
88         /* No matching status entry */
89         sc.result = SAM_STAT_RESERVATION_CONFLICT;
90         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
91
92         /* Test hitting allowed limit */
93         scsi_build_sense(&sc, 0, NOT_READY, 0x11, 0x22);
94         for (i = 0; i < SCSI_LIB_TEST_MAX_ALLOWED; i++)
95                 KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,
96                                 &failures));
97         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
98
99         /* reset retries so we can retest */
100         failures.failure_definitions = multiple_sense_failure_defs;
101         scsi_failures_reset_retries(&failures);
102
103         /* Test no retries allowed */
104         scsi_build_sense(&sc, 0, DATA_PROTECT, 0x1, 0x1);
105         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
106 }
107
108 static void scsi_lib_test_any_sense(struct kunit *test)
109 {
110         struct scsi_failure any_sense_failure_defs[] = {
111                 {
112                         .result = SCMD_FAILURE_SENSE_ANY,
113                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
114                 },
115                 {}
116         };
117         struct scsi_failures failures = {
118                 .failure_definitions = any_sense_failure_defs,
119         };
120         u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
121         struct scsi_cmnd sc = {
122                 .sense_buffer = sense,
123         };
124
125         /* Match using SCMD_FAILURE_SENSE_ANY */
126         failures.failure_definitions = any_sense_failure_defs;
127         scsi_build_sense(&sc, 0, MEDIUM_ERROR, 0x11, 0x22);
128         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
129 }
130
131 static void scsi_lib_test_host(struct kunit *test)
132 {
133         struct scsi_failure retryable_host_failure_defs[] = {
134                 {
135                         .result = DID_TRANSPORT_DISRUPTED << 16,
136                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
137                 },
138                 {
139                         .result = DID_TIME_OUT << 16,
140                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
141                 },
142                 {}
143         };
144         struct scsi_failures failures = {
145                 .failure_definitions = retryable_host_failure_defs,
146         };
147         u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
148         struct scsi_cmnd sc = {
149                 .sense_buffer = sense,
150         };
151
152         /* No matching host byte entry */
153         failures.failure_definitions = retryable_host_failure_defs;
154         sc.result = DID_NO_CONNECT << 16;
155         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
156         /* Matching host byte entry */
157         sc.result = DID_TIME_OUT << 16;
158         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
159 }
160
161 static void scsi_lib_test_any_failure(struct kunit *test)
162 {
163         struct scsi_failure any_failure_defs[] = {
164                 {
165                         .result = SCMD_FAILURE_RESULT_ANY,
166                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
167                 },
168                 {}
169         };
170         struct scsi_failures failures = {
171                 .failure_definitions = any_failure_defs,
172         };
173         u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
174         struct scsi_cmnd sc = {
175                 .sense_buffer = sense,
176         };
177
178         /* Match SCMD_FAILURE_RESULT_ANY */
179         failures.failure_definitions = any_failure_defs;
180         sc.result = DID_TRANSPORT_FAILFAST << 16;
181         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
182 }
183
184 static void scsi_lib_test_any_status(struct kunit *test)
185 {
186         struct scsi_failure any_status_failure_defs[] = {
187                 {
188                         .result = SCMD_FAILURE_STAT_ANY,
189                         .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
190                 },
191                 {}
192         };
193         struct scsi_failures failures = {
194                 .failure_definitions = any_status_failure_defs,
195         };
196         u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
197         struct scsi_cmnd sc = {
198                 .sense_buffer = sense,
199         };
200
201         /* Test any status handling */
202         failures.failure_definitions = any_status_failure_defs;
203         sc.result = SAM_STAT_RESERVATION_CONFLICT;
204         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
205 }
206
207 static void scsi_lib_test_total_allowed(struct kunit *test)
208 {
209         struct scsi_failure total_allowed_defs[] = {
210                 {
211                         .sense = UNIT_ATTENTION,
212                         .asc = SCMD_FAILURE_ASC_ANY,
213                         .ascq = SCMD_FAILURE_ASCQ_ANY,
214                         .result = SAM_STAT_CHECK_CONDITION,
215                 },
216                 /* Fail all CCs except the UA above */
217                 {
218                         .sense = SCMD_FAILURE_SENSE_ANY,
219                         .result = SAM_STAT_CHECK_CONDITION,
220                 },
221                 /* Retry any other errors not listed above */
222                 {
223                         .result = SCMD_FAILURE_RESULT_ANY,
224                 },
225                 {}
226         };
227         struct scsi_failures failures = {
228                 .failure_definitions = total_allowed_defs,
229         };
230         u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
231         struct scsi_cmnd sc = {
232                 .sense_buffer = sense,
233         };
234         int i;
235
236         /* Test total_allowed */
237         failures.failure_definitions = total_allowed_defs;
238         scsi_failures_reset_retries(&failures);
239         failures.total_allowed = SCSI_LIB_TEST_TOTAL_MAX_ALLOWED;
240
241         scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);
242         for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)
243                 /* Retry since we under the total_allowed limit */
244                 KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,
245                                 &failures));
246         sc.result = DID_TIME_OUT << 16;
247         /* We have now hit the total_allowed limit so no more retries */
248         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
249 }
250
251 static void scsi_lib_test_mixed_total(struct kunit *test)
252 {
253         struct scsi_failure mixed_total_defs[] = {
254                 {
255                         .sense = UNIT_ATTENTION,
256                         .asc = 0x28,
257                         .result = SAM_STAT_CHECK_CONDITION,
258                 },
259                 {
260                         .sense = UNIT_ATTENTION,
261                         .asc = 0x29,
262                         .result = SAM_STAT_CHECK_CONDITION,
263                 },
264                 {
265                         .allowed = 1,
266                         .result = DID_TIME_OUT << 16,
267                 },
268                 {}
269         };
270         u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
271         struct scsi_failures failures = {
272                 .failure_definitions = mixed_total_defs,
273         };
274         struct scsi_cmnd sc = {
275                 .sense_buffer = sense,
276         };
277         int i;
278
279         /*
280          * Test total_allowed when there is a mix of per failure allowed
281          * and total_allowed limits.
282          */
283         failures.failure_definitions = mixed_total_defs;
284         scsi_failures_reset_retries(&failures);
285         failures.total_allowed = SCSI_LIB_TEST_TOTAL_MAX_ALLOWED;
286
287         scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);
288         for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)
289                 /* Retry since we under the total_allowed limit */
290                 KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,
291                                 &failures));
292         /* Do not retry since we are now over total_allowed limit */
293         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
294
295         scsi_failures_reset_retries(&failures);
296         scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);
297         for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)
298                 /* Retry since we under the total_allowed limit */
299                 KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,
300                                 &failures));
301         sc.result = DID_TIME_OUT << 16;
302         /* Retry because this failure has a per failure limit */
303         KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
304         scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x29, 0x0);
305         /* total_allowed is now hit so no more retries */
306         KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
307 }
308
309 static void scsi_lib_test_check_passthough(struct kunit *test)
310 {
311         scsi_lib_test_multiple_sense(test);
312         scsi_lib_test_any_sense(test);
313         scsi_lib_test_host(test);
314         scsi_lib_test_any_failure(test);
315         scsi_lib_test_any_status(test);
316         scsi_lib_test_total_allowed(test);
317         scsi_lib_test_mixed_total(test);
318 }
319
320 static struct kunit_case scsi_lib_test_cases[] = {
321         KUNIT_CASE(scsi_lib_test_check_passthough),
322         {}
323 };
324
325 static struct kunit_suite scsi_lib_test_suite = {
326         .name = "scsi_lib",
327         .test_cases = scsi_lib_test_cases,
328 };
329
330 kunit_test_suite(scsi_lib_test_suite);