Commit | Line | Data |
---|---|---|
88a678bb BL |
1 | /******************************************************************************* |
2 | * IBM Virtual SCSI Target Driver | |
3 | * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp. | |
4 | * Santiago Leon (santil@us.ibm.com) IBM Corp. | |
5 | * Linda Xie (lxie@us.ibm.com) IBM Corp. | |
6 | * | |
7 | * Copyright (C) 2005-2011 FUJITA Tomonori <tomof@acm.org> | |
8 | * Copyright (C) 2010 Nicholas A. Bellinger <nab@kernel.org> | |
9 | * Copyright (C) 2016 Bryant G. Ly <bryantly@linux.vnet.ibm.com> IBM Corp. | |
10 | * | |
11 | * Authors: Bryant G. Ly <bryantly@linux.vnet.ibm.com> | |
12 | * Authors: Michael Cyr <mikecyr@linux.vnet.ibm.com> | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or modify | |
15 | * it under the terms of the GNU General Public License as published by | |
16 | * the Free Software Foundation; either version 2 of the License, or | |
17 | * (at your option) any later version. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, | |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
22 | * GNU General Public License for more details. | |
23 | * | |
24 | ****************************************************************************/ | |
25 | ||
26 | #ifndef __H_IBMVSCSI_TGT | |
27 | #define __H_IBMVSCSI_TGT | |
28 | ||
29 | #include "libsrp.h" | |
30 | ||
31 | #define SYS_ID_NAME_LEN 64 | |
32 | #define PARTITION_NAMELEN 96 | |
33 | #define IBMVSCSIS_NAMELEN 32 | |
34 | ||
35 | #define MSG_HI 0 | |
36 | #define MSG_LOW 1 | |
37 | ||
38 | #define MAX_CMD_Q_PAGES 4 | |
39 | #define CRQ_PER_PAGE (PAGE_SIZE / sizeof(struct viosrp_crq)) | |
40 | /* in terms of number of elements */ | |
41 | #define DEFAULT_CMD_Q_SIZE CRQ_PER_PAGE | |
42 | #define MAX_CMD_Q_SIZE (DEFAULT_CMD_Q_SIZE * MAX_CMD_Q_PAGES) | |
43 | ||
44 | #define SRP_VIOLATION 0x102 /* general error code */ | |
45 | ||
46 | /* | |
47 | * SRP buffer formats defined as of 16.a supported by this driver. | |
48 | */ | |
49 | #define SUPPORTED_FORMATS ((SRP_DATA_DESC_DIRECT << 1) | \ | |
50 | (SRP_DATA_DESC_INDIRECT << 1)) | |
51 | ||
52 | #define SCSI_LUN_ADDR_METHOD_FLAT 1 | |
53 | ||
54 | struct dma_window { | |
55 | u32 liobn; /* Unique per vdevice */ | |
56 | u64 tce_base; /* Physical location of the TCE table */ | |
57 | u64 tce_size; /* Size of the TCE table in bytes */ | |
58 | }; | |
59 | ||
60 | struct target_dds { | |
61 | u64 unit_id; /* 64 bit will force alignment */ | |
62 | #define NUM_DMA_WINDOWS 2 | |
63 | #define LOCAL 0 | |
64 | #define REMOTE 1 | |
65 | struct dma_window window[NUM_DMA_WINDOWS]; | |
66 | ||
67 | /* root node property "ibm,partition-no" */ | |
68 | uint partition_num; | |
69 | char partition_name[PARTITION_NAMELEN]; | |
70 | }; | |
71 | ||
72 | #define MAX_NUM_PORTS 1 | |
73 | #define MAX_H_COPY_RDMA (128 * 1024) | |
74 | ||
75 | #define MAX_EYE 64 | |
76 | ||
77 | /* Return codes */ | |
78 | #define ADAPT_SUCCESS 0L | |
79 | /* choose error codes that do not conflict with PHYP */ | |
80 | #define ERROR -40L | |
81 | ||
82 | struct format_code { | |
83 | u8 reserved; | |
84 | u8 buffers; | |
85 | }; | |
86 | ||
87 | struct client_info { | |
88 | #define SRP_VERSION "16.a" | |
89 | char srp_version[8]; | |
90 | /* root node property ibm,partition-name */ | |
91 | char partition_name[PARTITION_NAMELEN]; | |
92 | /* root node property ibm,partition-no */ | |
93 | u32 partition_number; | |
94 | /* initially 1 */ | |
95 | u32 mad_version; | |
96 | u32 os_type; | |
97 | }; | |
98 | ||
99 | /* | |
100 | * Changing this constant changes the number of seconds to wait before | |
101 | * considering the client will never service its queue again. | |
102 | */ | |
103 | #define SECONDS_TO_CONSIDER_FAILED 30 | |
104 | /* | |
105 | * These constants set the polling period used to determine if the client | |
106 | * has freed at least one element in the response queue. | |
107 | */ | |
108 | #define WAIT_SECONDS 1 | |
109 | #define WAIT_NANO_SECONDS 5000 | |
110 | #define MAX_TIMER_POPS ((1000000 / WAIT_NANO_SECONDS) * \ | |
111 | SECONDS_TO_CONSIDER_FAILED) | |
112 | /* | |
113 | * general purpose timer control block | |
114 | * which can be used for multiple functions | |
115 | */ | |
116 | struct timer_cb { | |
117 | struct hrtimer timer; | |
118 | /* | |
119 | * how long has it been since the client | |
120 | * serviced the queue. The variable is incrmented | |
121 | * in the service_wait_q routine and cleared | |
122 | * in send messages | |
123 | */ | |
124 | int timer_pops; | |
125 | /* the timer is started */ | |
126 | bool started; | |
127 | }; | |
128 | ||
129 | struct cmd_queue { | |
130 | /* kva */ | |
131 | struct viosrp_crq *base_addr; | |
132 | dma_addr_t crq_token; | |
133 | /* used to maintain index */ | |
134 | uint mask; | |
135 | /* current element */ | |
136 | uint index; | |
137 | int size; | |
138 | }; | |
139 | ||
140 | #define SCSOLNT_RESP_SHIFT 1 | |
141 | #define UCSOLNT_RESP_SHIFT 2 | |
142 | ||
143 | #define SCSOLNT BIT(SCSOLNT_RESP_SHIFT) | |
144 | #define UCSOLNT BIT(UCSOLNT_RESP_SHIFT) | |
145 | ||
146 | enum cmd_type { | |
147 | SCSI_CDB = 0x01, | |
148 | TASK_MANAGEMENT = 0x02, | |
149 | /* MAD or addressed to port 0 */ | |
150 | ADAPTER_MAD = 0x04, | |
151 | UNSET_TYPE = 0x08, | |
152 | }; | |
153 | ||
154 | struct iu_rsp { | |
155 | u8 format; | |
156 | u8 sol_not; | |
157 | u16 len; | |
158 | /* tag is just to help client identify cmd, so don't translate be/le */ | |
159 | u64 tag; | |
160 | }; | |
161 | ||
162 | struct ibmvscsis_cmd { | |
163 | struct list_head list; | |
164 | /* Used for TCM Core operations */ | |
165 | struct se_cmd se_cmd; | |
166 | struct iu_entry *iue; | |
167 | struct iu_rsp rsp; | |
168 | struct work_struct work; | |
169 | struct scsi_info *adapter; | |
170 | /* Sense buffer that will be mapped into outgoing status */ | |
171 | unsigned char sense_buf[TRANSPORT_SENSE_BUFFER]; | |
172 | u64 init_time; | |
173 | #define CMD_FAST_FAIL BIT(0) | |
174 | u32 flags; | |
175 | char type; | |
176 | }; | |
177 | ||
178 | struct ibmvscsis_nexus { | |
179 | struct se_session *se_sess; | |
180 | }; | |
181 | ||
182 | struct ibmvscsis_tport { | |
183 | /* SCSI protocol the tport is providing */ | |
184 | u8 tport_proto_id; | |
185 | /* ASCII formatted WWPN for SRP Target port */ | |
186 | char tport_name[IBMVSCSIS_NAMELEN]; | |
187 | /* Returned by ibmvscsis_make_tport() */ | |
188 | struct se_wwn tport_wwn; | |
189 | /* Returned by ibmvscsis_make_tpg() */ | |
190 | struct se_portal_group se_tpg; | |
191 | /* ibmvscsis port target portal group tag for TCM */ | |
192 | u16 tport_tpgt; | |
193 | /* Pointer to TCM session for I_T Nexus */ | |
194 | struct ibmvscsis_nexus *ibmv_nexus; | |
195 | bool enabled; | |
196 | bool releasing; | |
197 | }; | |
198 | ||
199 | struct scsi_info { | |
200 | struct list_head list; | |
201 | char eye[MAX_EYE]; | |
202 | ||
203 | /* commands waiting for space on repsonse queue */ | |
204 | struct list_head waiting_rsp; | |
205 | #define NO_QUEUE 0x00 | |
206 | #define WAIT_ENABLED 0X01 | |
207 | /* driver has received an initialize command */ | |
208 | #define PART_UP_WAIT_ENAB 0x02 | |
209 | #define WAIT_CONNECTION 0x04 | |
210 | /* have established a connection */ | |
211 | #define CONNECTED 0x08 | |
212 | /* at least one port is processing SRP IU */ | |
213 | #define SRP_PROCESSING 0x10 | |
214 | /* remove request received */ | |
215 | #define UNCONFIGURING 0x20 | |
216 | /* disconnect by letting adapter go idle, no error */ | |
217 | #define WAIT_IDLE 0x40 | |
218 | /* disconnecting to clear an error */ | |
219 | #define ERR_DISCONNECT 0x80 | |
220 | /* disconnect to clear error state, then come back up */ | |
221 | #define ERR_DISCONNECT_RECONNECT 0x100 | |
222 | /* disconnected after clearing an error */ | |
223 | #define ERR_DISCONNECTED 0x200 | |
224 | /* A series of errors caused unexpected errors */ | |
225 | #define UNDEFINED 0x400 | |
226 | u16 state; | |
227 | int fast_fail; | |
228 | struct target_dds dds; | |
229 | char *cmd_pool; | |
230 | /* list of free commands */ | |
231 | struct list_head free_cmd; | |
232 | /* command elements ready for scheduler */ | |
233 | struct list_head schedule_q; | |
234 | /* commands sent to TCM */ | |
235 | struct list_head active_q; | |
236 | caddr_t *map_buf; | |
237 | /* ioba of map buffer */ | |
238 | dma_addr_t map_ioba; | |
239 | /* allowable number of outstanding SRP requests */ | |
240 | int request_limit; | |
241 | /* extra credit */ | |
242 | int credit; | |
243 | /* outstanding transactions against credit limit */ | |
244 | int debit; | |
245 | ||
246 | /* allow only one outstanding mad request */ | |
247 | #define PROCESSING_MAD 0x00002 | |
248 | /* Waiting to go idle */ | |
249 | #define WAIT_FOR_IDLE 0x00004 | |
250 | /* H_REG_CRQ called */ | |
251 | #define CRQ_CLOSED 0x00010 | |
252 | /* detected that client has failed */ | |
253 | #define CLIENT_FAILED 0x00040 | |
254 | /* detected that transport event occurred */ | |
255 | #define TRANS_EVENT 0x00080 | |
256 | /* don't attempt to send anything to the client */ | |
257 | #define RESPONSE_Q_DOWN 0x00100 | |
258 | /* request made to schedule disconnect handler */ | |
259 | #define SCHEDULE_DISCONNECT 0x00400 | |
260 | /* disconnect handler is scheduled */ | |
261 | #define DISCONNECT_SCHEDULED 0x00800 | |
262 | u32 flags; | |
263 | /* adapter lock */ | |
264 | spinlock_t intr_lock; | |
265 | /* information needed to manage command queue */ | |
266 | struct cmd_queue cmd_q; | |
267 | /* used in hcall to copy response back into srp buffer */ | |
268 | u64 empty_iu_id; | |
269 | /* used in crq, to tag what iu the response is for */ | |
270 | u64 empty_iu_tag; | |
271 | uint new_state; | |
272 | /* control block for the response queue timer */ | |
273 | struct timer_cb rsp_q_timer; | |
274 | /* keep last client to enable proper accounting */ | |
275 | struct client_info client_data; | |
276 | /* what can this client do */ | |
277 | u32 client_cap; | |
278 | /* | |
279 | * The following two fields capture state and flag changes that | |
280 | * can occur when the lock is given up. In the orginal design, | |
281 | * the lock was held during calls into phyp; | |
282 | * however, phyp did not meet PAPR architecture. This is | |
283 | * a work around. | |
284 | */ | |
285 | u16 phyp_acr_state; | |
286 | u32 phyp_acr_flags; | |
287 | ||
288 | struct workqueue_struct *work_q; | |
289 | struct completion wait_idle; | |
290 | struct device dev; | |
291 | struct vio_dev *dma_dev; | |
292 | struct srp_target target; | |
293 | struct ibmvscsis_tport tport; | |
294 | struct tasklet_struct work_task; | |
295 | struct work_struct proc_work; | |
296 | }; | |
297 | ||
298 | /* | |
299 | * Provide a constant that allows software to detect the adapter is | |
300 | * disconnecting from the client from one of several states. | |
301 | */ | |
302 | #define IS_DISCONNECTING (UNCONFIGURING | ERR_DISCONNECT_RECONNECT | \ | |
303 | ERR_DISCONNECT) | |
304 | ||
305 | /* | |
306 | * Provide a constant that can be used with interrupt handling that | |
307 | * essentially lets the interrupt handler know that all requests should | |
308 | * be thrown out, | |
309 | */ | |
310 | #define DONT_PROCESS_STATE (IS_DISCONNECTING | UNDEFINED | \ | |
311 | ERR_DISCONNECTED | WAIT_IDLE) | |
312 | ||
313 | /* | |
314 | * If any of these flag bits are set then do not allow the interrupt | |
315 | * handler to schedule the off level handler. | |
316 | */ | |
317 | #define BLOCK (DISCONNECT_SCHEDULED) | |
318 | ||
319 | /* State and transition events that stop the interrupt handler */ | |
320 | #define TARGET_STOP(VSCSI) (long)(((VSCSI)->state & DONT_PROCESS_STATE) | \ | |
321 | ((VSCSI)->flags & BLOCK)) | |
322 | ||
323 | /* flag bit that are not reset during disconnect */ | |
324 | #define PRESERVE_FLAG_FIELDS 0 | |
325 | ||
326 | #define vio_iu(IUE) ((union viosrp_iu *)((IUE)->sbuf->buf)) | |
327 | ||
328 | #define READ_CMD(cdb) (((cdb)[0] & 0x1F) == 8) | |
329 | #define WRITE_CMD(cdb) (((cdb)[0] & 0x1F) == 0xA) | |
330 | ||
331 | #ifndef H_GET_PARTNER_INFO | |
332 | #define H_GET_PARTNER_INFO 0x0000000000000008LL | |
333 | #endif | |
334 | ||
335 | #define h_copy_rdma(l, sa, sb, da, db) \ | |
336 | plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db) | |
337 | #define h_vioctl(u, o, a, u1, u2, u3, u4) \ | |
338 | plpar_hcall_norets(H_VIOCTL, u, o, a, u1, u2) | |
339 | #define h_reg_crq(ua, tok, sz) \ | |
340 | plpar_hcall_norets(H_REG_CRQ, ua, tok, sz) | |
341 | #define h_free_crq(ua) \ | |
342 | plpar_hcall_norets(H_FREE_CRQ, ua) | |
343 | #define h_send_crq(ua, d1, d2) \ | |
344 | plpar_hcall_norets(H_SEND_CRQ, ua, d1, d2) | |
345 | ||
346 | #endif |