Merge branch 'tip/perf/core-2' of git://git.kernel.org/pub/scm/linux/kernel/git/roste...
[pandora-kernel.git] / drivers / staging / hv / hyperv_storage.h
1 /*
2  *
3  * Copyright (c) 2011, Microsoft Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16  * Place - Suite 330, Boston, MA 02111-1307 USA.
17  *
18  * Authors:
19  *   Haiyang Zhang <haiyangz@microsoft.com>
20  *   Hank Janssen  <hjanssen@microsoft.com>
21  *   K. Y. Srinivasan <kys@microsoft.com>
22  *
23  */
24
25 #ifndef _HYPERV_STORAGE_H
26 #define _HYPERV_STORAGE_H
27
28
29 /* vstorage.w revision number.  This is used in the case of a version match, */
30 /* to alert the user that structure sizes may be mismatched even though the */
31 /* protocol versions match. */
32
33
34 #define REVISION_STRING(REVISION_) #REVISION_
35 #define FILL_VMSTOR_REVISION(RESULT_LVALUE_)                            \
36         do {                                                            \
37                 char *revision_string                                   \
38                         = REVISION_STRING($Rev : 6 $) + 6;              \
39                 RESULT_LVALUE_ = 0;                                     \
40                 while (*revision_string >= '0'                          \
41                         && *revision_string <= '9') {                   \
42                         RESULT_LVALUE_ *= 10;                           \
43                         RESULT_LVALUE_ += *revision_string - '0';       \
44                         revision_string++;                              \
45                 }                                                       \
46         } while (0)
47
48 /* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
49 /* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
50 #define VMSTOR_PROTOCOL_MAJOR(VERSION_)         (((VERSION_) >> 8) & 0xff)
51 #define VMSTOR_PROTOCOL_MINOR(VERSION_)         (((VERSION_))      & 0xff)
52 #define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
53                                                  (((MINOR_) & 0xff)))
54 #define VMSTOR_INVALID_PROTOCOL_VERSION         (-1)
55
56 /* Version history: */
57 /* V1 Beta                    0.1 */
58 /* V1 RC < 2008/1/31          1.0 */
59 /* V1 RC > 2008/1/31          2.0 */
60 #define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
61
62
63
64
65 /*  This will get replaced with the max transfer length that is possible on */
66 /*  the host adapter. */
67 /*  The max transfer length will be published when we offer a vmbus channel. */
68 #define MAX_TRANSFER_LENGTH     0x40000
69 #define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) + \
70                         sizeof(struct vstor_packet) +           \
71                         sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
72
73
74 /*  Packet structure describing virtual storage requests. */
75 enum vstor_packet_operation {
76         VSTOR_OPERATION_COMPLETE_IO             = 1,
77         VSTOR_OPERATION_REMOVE_DEVICE           = 2,
78         VSTOR_OPERATION_EXECUTE_SRB             = 3,
79         VSTOR_OPERATION_RESET_LUN               = 4,
80         VSTOR_OPERATION_RESET_ADAPTER           = 5,
81         VSTOR_OPERATION_RESET_BUS               = 6,
82         VSTOR_OPERATION_BEGIN_INITIALIZATION    = 7,
83         VSTOR_OPERATION_END_INITIALIZATION      = 8,
84         VSTOR_OPERATION_QUERY_PROTOCOL_VERSION  = 9,
85         VSTOR_OPERATION_QUERY_PROPERTIES        = 10,
86         VSTOR_OPERATION_MAXIMUM                 = 10
87 };
88
89 /*
90  * Platform neutral description of a scsi request -
91  * this remains the same across the write regardless of 32/64 bit
92  * note: it's patterned off the SCSI_PASS_THROUGH structure
93  */
94 #define CDB16GENERIC_LENGTH                     0x10
95
96 #ifndef SENSE_BUFFER_SIZE
97 #define SENSE_BUFFER_SIZE                       0x12
98 #endif
99
100 #define MAX_DATA_BUF_LEN_WITH_PADDING           0x14
101
102 struct vmscsi_request {
103         unsigned short length;
104         unsigned char srb_status;
105         unsigned char scsi_status;
106
107         unsigned char port_number;
108         unsigned char path_id;
109         unsigned char target_id;
110         unsigned char lun;
111
112         unsigned char cdb_length;
113         unsigned char sense_info_length;
114         unsigned char data_in;
115         unsigned char reserved;
116
117         unsigned int data_transfer_length;
118
119         union {
120                 unsigned char cdb[CDB16GENERIC_LENGTH];
121                 unsigned char sense_data[SENSE_BUFFER_SIZE];
122                 unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
123         };
124 } __attribute((packed));
125
126
127 /*
128  * This structure is sent during the intialization phase to get the different
129  * properties of the channel.
130  */
131 struct vmstorage_channel_properties {
132         unsigned short protocol_version;
133         unsigned char path_id;
134         unsigned char target_id;
135
136         /* Note: port number is only really known on the client side */
137         unsigned int port_number;
138         unsigned int flags;
139         unsigned int max_transfer_bytes;
140
141         /*  This id is unique for each channel and will correspond with */
142         /*  vendor specific data in the inquirydata */
143         unsigned long long unique_id;
144 } __packed;
145
146 /*  This structure is sent during the storage protocol negotiations. */
147 struct vmstorage_protocol_version {
148         /* Major (MSW) and minor (LSW) version numbers. */
149         unsigned short major_minor;
150
151         /*
152          * Revision number is auto-incremented whenever this file is changed
153          * (See FILL_VMSTOR_REVISION macro above).  Mismatch does not
154          * definitely indicate incompatibility--but it does indicate mismatched
155          * builds.
156          */
157         unsigned short revision;
158 } __packed;
159
160 /* Channel Property Flags */
161 #define STORAGE_CHANNEL_REMOVABLE_FLAG          0x1
162 #define STORAGE_CHANNEL_EMULATED_IDE_FLAG       0x2
163
164 struct vstor_packet {
165         /* Requested operation type */
166         enum vstor_packet_operation operation;
167
168         /*  Flags - see below for values */
169         unsigned int flags;
170
171         /* Status of the request returned from the server side. */
172         unsigned int status;
173
174         /* Data payload area */
175         union {
176                 /*
177                  * Structure used to forward SCSI commands from the
178                  * client to the server.
179                  */
180                 struct vmscsi_request vm_srb;
181
182                 /* Structure used to query channel properties. */
183                 struct vmstorage_channel_properties storage_channel_properties;
184
185                 /* Used during version negotiations. */
186                 struct vmstorage_protocol_version version;
187         };
188 } __packed;
189
190 /* Packet flags */
191 /*
192  * This flag indicates that the server should send back a completion for this
193  * packet.
194  */
195 #define REQUEST_COMPLETION_FLAG 0x1
196
197 /*  This is the set of flags that the vsc can set in any packets it sends */
198 #define VSC_LEGAL_FLAGS         (REQUEST_COMPLETION_FLAG)
199
200
201 #include <linux/kernel.h>
202 #include <linux/wait.h>
203 #include "hyperv_storage.h"
204 #include "hyperv.h"
205
206 /* Defines */
207 #define STORVSC_RING_BUFFER_SIZE                        (20*PAGE_SIZE)
208 #define BLKVSC_RING_BUFFER_SIZE                         (20*PAGE_SIZE)
209
210 #define STORVSC_MAX_IO_REQUESTS                         128
211
212 /*
213  * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
214  * reality, the path/target is not used (ie always set to 0) so our
215  * scsi host adapter essentially has 1 bus with 1 target that contains
216  * up to 256 luns.
217  */
218 #define STORVSC_MAX_LUNS_PER_TARGET                     64
219 #define STORVSC_MAX_TARGETS                             1
220 #define STORVSC_MAX_CHANNELS                            1
221
222 struct hv_storvsc_request;
223
224 /* Matches Windows-end */
225 enum storvsc_request_type {
226         WRITE_TYPE,
227         READ_TYPE,
228         UNKNOWN_TYPE,
229 };
230
231
232 struct hv_storvsc_request {
233         struct hv_storvsc_request *request;
234         struct hv_device *device;
235
236         /* Synchronize the request/response if needed */
237         struct completion wait_event;
238
239         unsigned char *sense_buffer;
240         void *context;
241         void (*on_io_completion)(struct hv_storvsc_request *request);
242         struct hv_multipage_buffer data_buffer;
243
244         struct vstor_packet vstor_packet;
245 };
246
247
248 struct storvsc_device_info {
249         u32 ring_buffer_size;
250         unsigned int port_number;
251         unsigned char path_id;
252         unsigned char target_id;
253 };
254
255 struct storvsc_major_info {
256         int major;
257         int index;
258         bool do_register;
259         char *devname;
260         char *diskname;
261 };
262
263 /* A storvsc device is a device object that contains a vmbus channel */
264 struct storvsc_device {
265         struct hv_device *device;
266
267         /* 0 indicates the device is being destroyed */
268         atomic_t ref_count;
269
270         bool     drain_notify;
271         atomic_t num_outstanding_req;
272
273         wait_queue_head_t waiting_to_drain;
274
275         /*
276          * Each unique Port/Path/Target represents 1 channel ie scsi
277          * controller. In reality, the pathid, targetid is always 0
278          * and the port is set by us
279          */
280         unsigned int port_number;
281         unsigned char path_id;
282         unsigned char target_id;
283
284         /* Used for vsc/vsp channel reset process */
285         struct hv_storvsc_request init_request;
286         struct hv_storvsc_request reset_request;
287 };
288
289
290 /* Get the stordevice object iff exists and its refcount > 1 */
291 static inline struct storvsc_device *get_stor_device(struct hv_device *device)
292 {
293         struct storvsc_device *stor_device;
294
295         stor_device = (struct storvsc_device *)device->ext;
296         if (stor_device && atomic_read(&stor_device->ref_count) > 1)
297                 atomic_inc(&stor_device->ref_count);
298         else
299                 stor_device = NULL;
300
301         return stor_device;
302 }
303
304
305 static inline void put_stor_device(struct hv_device *device)
306 {
307         struct storvsc_device *stor_device;
308
309         stor_device = (struct storvsc_device *)device->ext;
310
311         atomic_dec(&stor_device->ref_count);
312 }
313
314 static inline void storvsc_wait_to_drain(struct storvsc_device *dev)
315 {
316         dev->drain_notify = true;
317         wait_event(dev->waiting_to_drain,
318                    atomic_read(&dev->num_outstanding_req) == 0);
319         dev->drain_notify = false;
320 }
321
322 /* Interface */
323
324 int storvsc_dev_add(struct hv_device *device,
325                                 void *additional_info);
326 int storvsc_dev_remove(struct hv_device *device);
327
328 int storvsc_do_io(struct hv_device *device,
329                                 struct hv_storvsc_request *request);
330
331 int storvsc_get_major_info(struct storvsc_device_info *device_info,
332                                 struct storvsc_major_info *major_info);
333
334 #endif /* _HYPERV_STORAGE_H */