1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
|
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/
/*
* Copyright 2013 STEC, Inc. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SKD_H
#define _SKD_H
#include <sys/types.h>
#include <sys/stropts.h>
#include <sys/stream.h>
#include <sys/cmn_err.h>
#include <sys/kmem.h>
#include <sys/modctl.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/strsun.h>
#include <sys/kstat.h>
#include <sys/conf.h>
#include <sys/debug.h>
#include <sys/modctl.h>
#include <sys/errno.h>
#include <sys/pci.h>
#include <sys/memlist.h>
#include <sys/param.h>
#include <sys/queue.h>
#define DRV_NAME "skd"
#define DRV_VERSION "2.2.1"
#define DRV_BUILD_ID "0264"
#define PFX DRV_NAME ": "
#define DRV_BIN_VERSION 0x100
#define DRV_VER_COMPL DRV_VERSION "." DRV_BUILD_ID
#define VERSIONSTR DRV_VERSION
#define SG_BOUNDARY 0x20000
#ifdef _BIG_ENDIAN
#define be64_to_cpu(x) (x)
#define be32_to_cpu(x) (x)
#define cpu_to_be64(x) (x)
#define cpu_to_be32(x) (x)
#else
#define be64_to_cpu(x) BSWAP_64(x)
#define be32_to_cpu(x) BSWAP_32(x)
#define cpu_to_be64(x) BSWAP_64(x)
#define cpu_to_be32(x) BSWAP_32(x)
#endif
#define ATYPE_64BIT 0
#define ATYPE_32BIT 1
#define BIT_0 0x00001
#define BIT_1 0x00002
#define BIT_2 0x00004
#define BIT_3 0x00008
#define BIT_4 0x00010
#define BIT_5 0x00020
#define BIT_6 0x00040
#define BIT_7 0x00080
#define BIT_8 0x00100
#define BIT_9 0x00200
#define BIT_10 0x00400
#define BIT_11 0x00800
#define BIT_12 0x01000
#define BIT_13 0x02000
#define BIT_14 0x04000
#define BIT_15 0x08000
#define BIT_16 0x10000
#define BIT_17 0x20000
#define BIT_18 0x40000
#define BIT_19 0x80000
/* Attach progress flags */
#define SKD_ATTACHED BIT_0
#define SKD_SOFT_STATE_ALLOCED BIT_1
#define SKD_CONFIG_SPACE_SETUP BIT_3
#define SKD_IOBASE_MAPPED BIT_4
#define SKD_IOMAP_IOBASE_MAPPED BIT_5
#define SKD_REGS_MAPPED BIT_6
#define SKD_DEV_IOBASE_MAPPED BIT_7
#define SKD_CONSTRUCTED BIT_8
#define SKD_PROBED BIT_9
#define SKD_INTR_ADDED BIT_10
#define SKD_PATHNAME_ALLOCED BIT_11
#define SKD_SUSPENDED BIT_12
#define SKD_CMD_ABORT_TMO BIT_13
#define SKD_MUTEX_INITED BIT_14
#define SKD_MUTEX_DESTROYED BIT_15
#define SKD_IODONE_WIOC 1 /* I/O done */
#define SKD_IODONE_WNIOC 2 /* I/O NOT done */
#define SKD_IODONE_WDEBUG 3 /* I/O - debug stuff */
#ifdef SKD_PM
#define MAX_POWER_LEVEL 0
#define LOW_POWER_LEVEL (BIT_1 | BIT_0)
#endif
#define SKD_MSIX_AIF 0x0
#define SKD_MSIX_RSPQ 0x1
#define SKD_MSIX_MAXAIF SKD_MSIX_RSPQ + 1
/*
* Stuff from Linux
*/
#define SAM_STAT_GOOD 0x00
#define SAM_STAT_CHECK_CONDITION 0x02
#define TEST_UNIT_READY 0x00
#define INQUIRY 0x12
#define INQUIRY2 (0x12 + 0xe0)
#define READ_CAPACITY 0x25
#define READ_CAPACITY_EXT 0x9e
#define SYNCHRONIZE_CACHE 0x35
/*
* SENSE KEYS
*/
#define NO_SENSE 0x00
#define RECOVERED_ERROR 0x01
#define UNIT_ATTENTION 0x06
#define ABORTED_COMMAND 0x0b
typedef struct dma_mem_t {
void *bp;
ddi_acc_handle_t acc_handle;
ddi_dma_handle_t dma_handle;
ddi_dma_cookie_t cookie;
ddi_dma_cookie_t *cookies;
uint32_t size;
} dma_mem_t;
#define SKD_WRITEL(DEV, VAL, OFF) skd_reg_write32(DEV, VAL, OFF)
#define SKD_READL(DEV, OFF) skd_reg_read32(DEV, OFF)
#define SKD_WRITEQ(DEV, VAL, OFF) skd_reg_write64(DEV, VAL, OFF)
/* Capability lists */
#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
/*
* End Stuff from Linux
*/
#define SKD_DMA_MAXXFER (2048 * DEV_BSIZE)
#define SKD_DMA_LOW_ADDRESS (uint64_t)0
#define SKD_DMA_HIGH_64BIT_ADDRESS (uint64_t)0xffffffffffffffff
#define SKD_DMA_HIGH_32BIT_ADDRESS (uint64_t)0xffffffff
#define SKD_DMA_XFER_COUNTER (uint64_t)0xffffffff
#define SKD_DMA_ADDRESS_ALIGNMENT (uint64_t)SG_BOUNDARY
#define SKD_DMA_BURSTSIZES 0xff
#define SKD_DMA_MIN_XFER_SIZE 1
#define SKD_DMA_MAX_XFER_SIZE (uint64_t)0xfffffe00
#define SKD_DMA_SEGMENT_BOUNDARY (uint64_t)0xffffffff
#define SKD_DMA_SG_LIST_LENGTH 256
#define SKD_DMA_XFER_FLAGS 0
#define SKD_DMA_GRANULARITY 512 /* 1 */
#define PCI_VENDOR_ID_STEC 0x1B39
#define PCI_DEVICE_ID_SUMO 0x0001
#define SKD_N_FITMSG_BYTES (512u)
#define SKD_N_SPECIAL_CONTEXT 64u
#define SKD_N_SPECIAL_FITMSG_BYTES (128u)
#define SKD_N_SPECIAL_DATA_BYTES (8u*1024u)
/*
* SG elements are 32 bytes, so we can make this 4096 and still be under the
* 128KB limit. That allows 4096*4K = 16M xfer size
*/
#define SKD_N_SG_PER_REQ_DEFAULT 256u
#define SKD_N_SG_PER_SPECIAL 256u
#define SKD_N_COMPLETION_ENTRY 256u
#define SKD_N_READ_CAP_BYTES (8u)
#define SKD_N_READ_CAP_EXT_BYTES (16)
#define SKD_N_INTERNAL_BYTES (512u)
/* 5 bits of uniqifier, 0xF800 */
#define SKD_ID_INCR (0x400)
#define SKD_ID_TABLE_MASK (3u << 8u)
#define SKD_ID_RW_REQUEST (0u << 8u)
#define SKD_ID_INTERNAL (1u << 8u)
#define SKD_ID_FIT_MSG (3u << 8u)
#define SKD_ID_SLOT_MASK 0x00FFu
#define SKD_ID_SLOT_AND_TABLE_MASK 0x03FFu
#define SKD_N_TIMEOUT_SLOT 8u
#define SKD_TIMEOUT_SLOT_MASK 7u
#define SKD_TIMER_SECONDS(seconds) (seconds)
#define SKD_TIMER_MINUTES(minutes) ((minutes)*(60))
/*
* NOTE: INTR_LOCK() should be held prior to grabbing WAITQ_LOCK() if both
* are needed.
*/
#define INTR_LOCK(skdev) mutex_enter(&skdev->skd_intr_mutex)
#define INTR_UNLOCK(skdev) mutex_exit(&skdev->skd_intr_mutex)
#define INTR_LOCK_HELD(skdev) MUTEX_HELD(&skdev->skd_intr_mutex)
#define WAITQ_LOCK(skdev) \
mutex_enter(&skdev->waitqueue_mutex)
#define WAITQ_UNLOCK(skdev) \
mutex_exit(&skdev->waitqueue_mutex)
#define WAITQ_LOCK_HELD(skdev) \
MUTEX_HELD(&skdev->waitqueue_mutex)
#define ADAPTER_STATE_LOCK(skdev) mutex_enter(&skdev->skd_lock_mutex)
#define ADAPTER_STATE_UNLOCK(skdev) mutex_exit(&skdev->skd_lock_mutex)
enum skd_drvr_state {
SKD_DRVR_STATE_LOAD, /* 0 when driver first loaded */
SKD_DRVR_STATE_IDLE, /* 1 when device goes offline */
SKD_DRVR_STATE_BUSY, /* 2 */
SKD_DRVR_STATE_STARTING, /* 3 */
SKD_DRVR_STATE_ONLINE, /* 4 */
SKD_DRVR_STATE_PAUSING, /* 5 */
SKD_DRVR_STATE_PAUSED, /* 6 */
SKD_DRVR_STATE_DRAINING_TIMEOUT, /* 7 */
SKD_DRVR_STATE_RESTARTING, /* 8 */
SKD_DRVR_STATE_RESUMING, /* 9 */
SKD_DRVR_STATE_STOPPING, /* 10 when driver is unloading */
SKD_DRVR_STATE_FAULT, /* 11 */
SKD_DRVR_STATE_DISAPPEARED, /* 12 */
SKD_DRVR_STATE_PROTOCOL_MISMATCH, /* 13 */
SKD_DRVR_STATE_BUSY_ERASE, /* 14 */
SKD_DRVR_STATE_BUSY_SANITIZE, /* 15 */
SKD_DRVR_STATE_BUSY_IMMINENT, /* 16 */
SKD_DRVR_STATE_WAIT_BOOT, /* 17 */
SKD_DRVR_STATE_SYNCING /* 18 */
};
#define SKD_WAIT_BOOT_TO 90u
#define SKD_STARTING_TO 248u
enum skd_req_state {
SKD_REQ_STATE_IDLE,
SKD_REQ_STATE_SETUP,
SKD_REQ_STATE_BUSY,
SKD_REQ_STATE_COMPLETED,
SKD_REQ_STATE_TIMEOUT,
SKD_REQ_STATE_ABORTED,
};
enum skd_fit_msg_state {
SKD_MSG_STATE_IDLE,
SKD_MSG_STATE_BUSY,
};
enum skd_check_status_action {
SKD_CHECK_STATUS_REPORT_GOOD,
SKD_CHECK_STATUS_REPORT_SMART_ALERT,
SKD_CHECK_STATUS_REQUEUE_REQUEST,
SKD_CHECK_STATUS_REPORT_ERROR,
SKD_CHECK_STATUS_BUSY_IMMINENT,
};
/* NOTE: mbu_t users should name this field "mbu". */
typedef union {
uint8_t *mb8;
uint64_t *mb64;
} mbu_t;
#define msg_buf mbu.mb8
#define msg_buf64 mbu.mb64
struct skd_fitmsg_context {
enum skd_fit_msg_state state;
struct skd_fitmsg_context *next;
uint32_t id;
uint16_t outstanding;
uint32_t length;
uint32_t offset;
mbu_t mbu; /* msg_buf & msg_buf64 */
dma_mem_t mb_dma_address;
};
struct skd_request_context {
enum skd_req_state state;
struct skd_request_context *next;
uint16_t did_complete;
uint16_t id;
uint32_t fitmsg_id;
struct skd_buf_private *pbuf;
uint32_t timeout_stamp;
uint8_t sg_data_dir;
uint32_t n_sg;
ddi_dma_handle_t io_dma_handle;
struct fit_sg_descriptor *sksg_list;
dma_mem_t sksg_dma_address;
struct fit_completion_entry_v1 completion;
struct fit_comp_error_info err_info;
int total_sg_bcount;
};
#define SKD_DATA_DIR_HOST_TO_CARD 1
#define SKD_DATA_DIR_CARD_TO_HOST 2
struct skd_special_context {
struct skd_request_context req;
uint8_t orphaned;
uint32_t sg_byte_count;
void *data_buf;
dma_mem_t db_dma_address;
mbu_t mbu; /* msg_buf & msg_buf64 */
dma_mem_t mb_dma_address;
int io_pending;
};
typedef struct skd_buf_private {
SIMPLEQ_ENTRY(skd_buf_private) sq;
struct skd_request_context *skreq;
bd_xfer_t *x_xfer;
int dir;
} skd_buf_private_t;
SIMPLEQ_HEAD(waitqueue, skd_buf_private);
typedef struct skd_device skd_device_t;
struct skd_device {
int irq_type;
int gendisk_on;
int sync_done;
char name[32];
enum skd_drvr_state state;
uint32_t drive_state;
uint32_t queue_depth_busy;
uint32_t queue_depth_limit;
uint32_t queue_depth_lowat;
uint32_t soft_queue_depth_limit;
uint32_t hard_queue_depth_limit;
uint32_t num_fitmsg_context;
uint32_t num_req_context;
uint32_t timeout_slot[SKD_N_TIMEOUT_SLOT];
uint32_t timeout_stamp;
struct skd_fitmsg_context *skmsg_free_list;
struct skd_fitmsg_context *skmsg_table;
struct skd_request_context *skreq_free_list;
struct skd_request_context *skreq_table;
struct skd_special_context internal_skspcl;
uint64_t read_cap_last_lba;
uint32_t read_cap_blocksize;
int read_cap_is_valid;
int inquiry_is_valid;
char inq_serial_num[13]; /* 12 chars plus null term */
char inq_vendor_id[9];
char inq_product_id[17];
char inq_product_rev[5];
char id_str[128]; /* holds a composite name (pci + sernum) */
uint8_t skcomp_cycle;
uint32_t skcomp_ix;
struct fit_completion_entry_v1 *skcomp_table;
struct fit_comp_error_info *skerr_table;
dma_mem_t cq_dma_address;
uint32_t timer_active;
uint32_t timer_countdown;
uint32_t timer_substate;
int sgs_per_request;
uint32_t last_mtd;
uint32_t proto_ver;
int dbg_level;
uint32_t timo_slot;
ddi_acc_handle_t pci_handle;
ddi_acc_handle_t iobase_handle;
ddi_acc_handle_t iomap_handle;
caddr_t iobase;
caddr_t iomap_iobase;
ddi_acc_handle_t dev_handle;
caddr_t dev_iobase;
int dev_memsize;
char *pathname;
dev_info_t *dip;
int instance;
uint16_t vendor_id;
uint16_t device_id;
kmutex_t skd_lock_mutex;
kmutex_t skd_intr_mutex;
kmutex_t skd_fit_mutex;
uint32_t flags;
#ifdef SKD_PM
uint8_t power_level;
#endif
/* AIF (Advanced Interrupt Framework) support */
ddi_intr_handle_t *htable;
uint32_t hsize;
int32_t intr_cnt;
uint32_t intr_pri;
int32_t intr_cap;
uint64_t Nblocks;
ddi_iblock_cookie_t iblock_cookie;
int n_req;
uint32_t progress;
uint64_t intr_cntr;
uint64_t fitmsg_sent1;
uint64_t fitmsg_sent2;
uint64_t active_cmds;
kmutex_t skd_internalio_mutex;
kcondvar_t cv_waitq;
kmutex_t waitqueue_mutex;
struct waitqueue waitqueue;
int disks_initialized;
ddi_devid_t s1120_devid;
char devid_str[80];
uint32_t d_blkshift;
int attached;
int ios_queued;
int ios_started;
int ios_completed;
int ios_errors;
int iodone_wioc;
int iodone_wnioc;
int iodone_wdebug;
int iodone_unknown;
bd_handle_t s_bdh;
int bd_attached;
#ifdef USE_SKE_EMULATOR
ske_device_t *ske_handle;
#endif
timeout_id_t skd_timer_timeout_id;
};
static void skd_disable_interrupts(struct skd_device *skdev);
static void skd_isr_completion_posted(struct skd_device *skdev);
static void skd_recover_requests(struct skd_device *skdev);
static void skd_log_skdev(struct skd_device *skdev, const char *event);
static void skd_restart_device(struct skd_device *skdev);
static void skd_destruct(struct skd_device *skdev);
static int skd_unquiesce_dev(struct skd_device *skdev);
static void skd_send_special_fitmsg(struct skd_device *skdev,
struct skd_special_context *skspcl);
static void skd_end_request(struct skd_device *skdev,
struct skd_request_context *skreq, int error);
static void skd_log_skmsg(struct skd_device *skdev,
struct skd_fitmsg_context *skmsg, const char *event);
static void skd_log_skreq(struct skd_device *skdev,
struct skd_request_context *skreq, const char *event);
static void skd_send_fitmsg(struct skd_device *skdev,
struct skd_fitmsg_context *skmsg);
static const char *skd_drive_state_to_str(int state);
static const char *skd_skdev_state_to_str(enum skd_drvr_state state);
#endif /* _SKD_H */
|