The patch below fixes the following recently introduced checkpatch complaints:
[mirror/scst/.git] / scst / src / dev_handlers / scst_disk.c
1 /*
2  *  scst_disk.c
3  *
4  *  Copyright (C) 2004 - 2008 Vladislav Bolkhovitin <vst@vlnb.net>
5  *  Copyright (C) 2004 - 2005 Leonid Stoljar
6  *  Copyright (C) 2007 - 2008 CMS Distribution Limited
7  *
8  *  SCSI disk (type 0) dev handler
9  *  &
10  *  SCSI disk (type 0) "performance" device handler (skip all READ and WRITE
11  *   operations).
12  *
13  *  This program is free software; you can redistribute it and/or
14  *  modify it under the terms of the GNU General Public License
15  *  as published by the Free Software Foundation, version 2
16  *  of the License.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  *  GNU General Public License for more details.
22  */
23
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <scsi/scsi_host.h>
27
28 #define LOG_PREFIX           "dev_disk"
29
30 #include "scst.h"
31 #include "scst_dev_handler.h"
32
33 # define DISK_NAME           "dev_disk"
34 # define DISK_PERF_NAME      "dev_disk_perf"
35
36 #define DISK_TYPE {                                     \
37         .name =                 DISK_NAME,              \
38         .type =                 TYPE_DISK,              \
39         .parse_atomic =         1,                      \
40         .dev_done_atomic =      1,                      \
41         .exec_atomic =          1,                      \
42         .attach =               disk_attach,            \
43         .detach =               disk_detach,            \
44         .parse =                disk_parse,             \
45         .dev_done =             disk_done,              \
46 }
47
48 #define DISK_PERF_TYPE {                                \
49         .name =                 DISK_PERF_NAME,         \
50         .type =                 TYPE_DISK,              \
51         .parse_atomic =         1,                      \
52         .dev_done_atomic =      1,                      \
53         .exec_atomic =          1,                      \
54         .attach =               disk_attach,            \
55         .detach =               disk_detach,            \
56         .parse =                disk_parse,             \
57         .dev_done =             disk_done,              \
58         .exec =                 disk_exec,              \
59 }
60
61 #define DISK_DEF_BLOCK_SHIFT    9
62
63 struct disk_params {
64         int block_shift;
65 };
66
67 static int disk_attach(struct scst_device *dev);
68 static void disk_detach(struct scst_device *dev);
69 static int disk_parse(struct scst_cmd *cmd);
70 static int disk_done(struct scst_cmd *cmd);
71 static int disk_exec(struct scst_cmd *cmd);
72
73 static struct scst_dev_type disk_devtype = DISK_TYPE;
74 static struct scst_dev_type disk_devtype_perf = DISK_PERF_TYPE;
75
76 static int __init init_scst_disk_driver(void)
77 {
78         int res = 0;
79
80         TRACE_ENTRY();
81
82         disk_devtype.module = THIS_MODULE;
83
84         res = scst_register_dev_driver(&disk_devtype);
85         if (res < 0)
86                 goto out;
87
88         res = scst_dev_handler_build_std_proc(&disk_devtype);
89         if (res != 0)
90                 goto out_unreg1;
91
92         disk_devtype_perf.module = THIS_MODULE;
93
94         res = scst_register_dev_driver(&disk_devtype_perf);
95         if (res < 0)
96                 goto out_unreg1_err1;
97
98         res = scst_dev_handler_build_std_proc(&disk_devtype_perf);
99         if (res != 0)
100                 goto out_unreg2;
101
102 out:
103         TRACE_EXIT_RES(res);
104         return res;
105
106 out_unreg2:
107         scst_dev_handler_destroy_std_proc(&disk_devtype_perf);
108
109 out_unreg1_err1:
110         scst_dev_handler_destroy_std_proc(&disk_devtype);
111
112 out_unreg1:
113         scst_unregister_dev_driver(&disk_devtype);
114         goto out;
115 }
116
117 static void __exit exit_scst_disk_driver(void)
118 {
119         TRACE_ENTRY();
120         scst_dev_handler_destroy_std_proc(&disk_devtype_perf);
121         scst_unregister_dev_driver(&disk_devtype_perf);
122         scst_dev_handler_destroy_std_proc(&disk_devtype);
123         scst_unregister_dev_driver(&disk_devtype);
124         TRACE_EXIT();
125         return;
126 }
127
128 module_init(init_scst_disk_driver);
129 module_exit(exit_scst_disk_driver);
130
131 /**************************************************************
132  *  Function:  disk_attach
133  *
134  *  Argument:
135  *
136  *  Returns :  1 if attached, error code otherwise
137  *
138  *  Description:
139  *************************************************************/
140 static int disk_attach(struct scst_device *dev)
141 {
142         int res = 0;
143         uint8_t cmd[10];
144         const int buffer_size = 512;
145         uint8_t *buffer = NULL;
146         int retries;
147         unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
148         enum dma_data_direction data_dir;
149         struct disk_params *params;
150
151         TRACE_ENTRY();
152
153         if (dev->scsi_dev == NULL ||
154             dev->scsi_dev->type != dev->handler->type) {
155                 PRINT_ERROR("%s", "SCSI device not define or illegal type");
156                 res = -ENODEV;
157                 goto out;
158         }
159
160         params = kzalloc(sizeof(*params), GFP_KERNEL);
161         if (params == NULL) {
162                 TRACE(TRACE_OUT_OF_MEM, "%s",
163                       "Unable to allocate struct disk_params");
164                 res = -ENOMEM;
165                 goto out;
166         }
167
168         buffer = kmalloc(buffer_size, GFP_KERNEL);
169         if (!buffer) {
170                 TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
171                 res = -ENOMEM;
172                 goto out_free_params;
173         }
174
175         /* Clear any existing UA's and get disk capacity (disk block size) */
176         memset(cmd, 0, sizeof(cmd));
177         cmd[0] = READ_CAPACITY;
178         cmd[1] = (dev->scsi_dev->scsi_level <= SCSI_2) ?
179             ((dev->scsi_dev->lun << 5) & 0xe0) : 0;
180         retries = SCST_DEV_UA_RETRIES;
181         while (1) {
182                 memset(buffer, 0, buffer_size);
183                 data_dir = SCST_DATA_READ;
184
185                 TRACE_DBG("%s", "Doing READ_CAPACITY");
186                 res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
187                                    buffer_size, sense_buffer,
188                                    SCST_GENERIC_DISK_REG_TIMEOUT, 3, 0);
189
190                 TRACE_DBG("READ_CAPACITY done: %x", res);
191
192                 if ((res == 0) || !scst_analyze_sense(sense_buffer,
193                                 sizeof(sense_buffer), SCST_SENSE_ALL_VALID,
194                                 SCST_LOAD_SENSE(scst_sense_medium_changed_UA)) ||
195                     !scst_analyze_sense(sense_buffer, sizeof(sense_buffer),
196                                 SCST_SENSE_KEY_VALID | SCST_SENSE_ASC_VALID,
197                                 UNIT_ATTENTION, 0x29, 0))
198                         break;
199                 if (!--retries) {
200                         PRINT_ERROR("UA not clear after %d retries",
201                                 SCST_DEV_UA_RETRIES);
202                         res = -ENODEV;
203                         goto out_free_buf;
204                 }
205         }
206         if (res == 0) {
207                 int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
208                                      (buffer[6] << 8) | (buffer[7] << 0));
209                 if (sector_size == 0)
210                         params->block_shift = DISK_DEF_BLOCK_SHIFT;
211                 else
212                         params->block_shift =
213                                 scst_calc_block_shift(sector_size);
214         } else {
215                 TRACE_BUFFER("Sense set", sense_buffer, sizeof(sense_buffer));
216                 res = -ENODEV;
217                 goto out_free_buf;
218         }
219
220         res = scst_obtain_device_parameters(dev);
221         if (res != 0) {
222                 PRINT_ERROR("Failed to obtain control parameters for device "
223                         "%d:%d:%d:%d", dev->scsi_dev->host->host_no,
224                         dev->scsi_dev->channel, dev->scsi_dev->id,
225                         dev->scsi_dev->lun);
226                 goto out_free_buf;
227         }
228
229 out_free_buf:
230         kfree(buffer);
231
232 out_free_params:
233         if (res == 0)
234                 dev->dh_priv = params;
235         else
236                 kfree(params);
237
238 out:
239         TRACE_EXIT_RES(res);
240         return res;
241 }
242
243 /************************************************************
244  *  Function:  disk_detach
245  *
246  *  Argument:
247  *
248  *  Returns :  None
249  *
250  *  Description:  Called to detach this device type driver
251  ************************************************************/
252 static void disk_detach(struct scst_device *dev)
253 {
254         struct disk_params *params =
255                 (struct disk_params *)dev->dh_priv;
256
257         TRACE_ENTRY();
258
259         kfree(params);
260         dev->dh_priv = NULL;
261
262         TRACE_EXIT();
263         return;
264 }
265
266 static int disk_get_block_shift(struct scst_cmd *cmd)
267 {
268         struct disk_params *params = (struct disk_params *)cmd->dev->dh_priv;
269         /*
270          * No need for locks here, since *_detach() can not be
271          * called, when there are existing commands.
272          */
273         return params->block_shift;
274 }
275
276 /********************************************************************
277  *  Function:  disk_parse
278  *
279  *  Argument:
280  *
281  *  Returns :  The state of the command
282  *
283  *  Description:  This does the parsing of the command
284  *
285  *  Note:  Not all states are allowed on return
286  ********************************************************************/
287 static int disk_parse(struct scst_cmd *cmd)
288 {
289         int res = SCST_CMD_STATE_DEFAULT;
290
291         scst_sbc_generic_parse(cmd, disk_get_block_shift);
292
293         cmd->retries = SCST_PASSTHROUGH_RETRIES;
294
295         return res;
296 }
297
298 static void disk_set_block_shift(struct scst_cmd *cmd, int block_shift)
299 {
300         struct disk_params *params = (struct disk_params *)cmd->dev->dh_priv;
301         /*
302          * No need for locks here, since *_detach() can not be
303          * called, when there are existing commands.
304          */
305         if (block_shift != 0)
306                 params->block_shift = block_shift;
307         else
308                 params->block_shift = DISK_DEF_BLOCK_SHIFT;
309         return;
310 }
311
312 /********************************************************************
313  *  Function:  disk_done
314  *
315  *  Argument:
316  *
317  *  Returns :
318  *
319  *  Description:  This is the completion routine for the command,
320  *                it is used to extract any necessary information
321  *                about a command.
322  ********************************************************************/
323 static int disk_done(struct scst_cmd *cmd)
324 {
325         int res = SCST_CMD_STATE_DEFAULT;
326
327         TRACE_ENTRY();
328
329         res = scst_block_generic_dev_done(cmd, disk_set_block_shift);
330
331         TRACE_EXIT_RES(res);
332         return res;
333 }
334
335 /********************************************************************
336  *  Function:  disk_exec
337  *
338  *  Argument:
339  *
340  *  Returns :
341  *
342  *  Description:  Make SCST do nothing for data READs and WRITES.
343  *                Intended for raw line performance testing
344  ********************************************************************/
345 static int disk_exec(struct scst_cmd *cmd)
346 {
347         int res = SCST_EXEC_NOT_COMPLETED, rc;
348         int opcode = cmd->cdb[0];
349
350         TRACE_ENTRY();
351
352         rc = scst_check_local_events(cmd);
353         if (unlikely(rc != 0))
354                 goto out_done;
355
356         cmd->status = 0;
357         cmd->msg_status = 0;
358         cmd->host_status = DID_OK;
359         cmd->driver_status = 0;
360
361         switch (opcode) {
362         case WRITE_6:
363         case WRITE_10:
364         case WRITE_12:
365         case WRITE_16:
366         case READ_6:
367         case READ_10:
368         case READ_12:
369         case READ_16:
370                 cmd->completed = 1;
371                 goto out_done;
372         }
373
374 out:
375         TRACE_EXIT_RES(res);
376         return res;
377
378 out_done:
379         res = SCST_EXEC_COMPLETED;
380         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
381         goto out;
382 }
383
384 MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
385 MODULE_LICENSE("GPL");
386 MODULE_DESCRIPTION("SCSI disk (type 0) dev handler for SCST");
387 MODULE_VERSION(SCST_VERSION_STRING);