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