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
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _FCSM_H
#define _FCSM_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _KERNEL
/*
* Message printing flags
*/
#define SM_LOG 1
#define SM_CONSOLE 2
#define SM_LOG_AND_CONSOLE 3
/*
* Debug levels
*/
#define SMDL_TRACE 0x0001
#define SMDL_IO 0x0002
#define SMDL_ERR 0x0004
#define SMDL_INFO 0x0008
#ifdef DEBUG
#define FCSM_DEBUG(level, args) \
if (fcsm_debug & (level)) fcsm_display args
extern uint32_t fcsm_debug;
#else /* DEBUG */
#define FCSM_DEBUG(level, args)
#endif /* DEBUG */
#define FCSM_INIT_INSTANCES 8 /* # of instances for soft_state_init */
/*
* Open flags
*/
#define FCSM_IDLE 0x00
#define FCSM_OPEN 0x01
#define FCSM_EXCL 0x02
#define FCSM_ELS_TIMEOUT (20) /* secs */
#define FCSM_MS_TIMEOUT (20) /* secs */
#define FCSM_OFFLINE_TICKER (120) /* secs */
/* Definitions for command retries */
#define FCSM_MAX_CMD_RETRIES 5 /* Max retries in case of failure */
#define FCSM_RETRY_INTERVAL 3 /* Retry interval in seconds */
#define FCSM_RETRY_TICKER 1 /* Retry thread execution interval */
#define FCSM_MAX_JOB_RETRIES 3 /* Max retries in case of job failure */
/*
* fcsm_job - Job structure to issue commands using command thread
*/
typedef struct fcsm_job {
uint32_t job_code; /* Command code */
uint32_t job_flags; /* Command Flags */
int job_port_instance; /* port driver instance */
int job_result; /* job completion result */
opaque_t job_arg; /* Command Arguments */
opaque_t job_caller_priv; /* Caller private */
void (*job_comp)(opaque_t, struct fcsm_job *, int);
/* completion func */
opaque_t job_comp_arg; /* Arg for completion func */
kmutex_t job_mutex; /* per command mutex */
ksema_t job_sema; /* To wait for completion */
struct fcsm_job *job_next; /* for linked list */
int job_retry_count; /* Retry count */
void *job_priv; /* for fcsm private use */
uint32_t job_priv_flags; /* fcsm private flags */
} fcsm_job_t;
/*
* fcsm_t - FCSM Structure for per port information
*/
typedef struct fcsm {
kmutex_t sm_mutex; /* mutex for protection */
struct fcsm *sm_next; /* for global linked list */
int sm_sid; /* FCA Port ID */
int sm_instance; /* fc port instance number */
uint32_t sm_port_state; /* FCA port state */
uint32_t sm_port_top; /* Port topology */
uint32_t sm_state; /* San Mgmt State information */
uint32_t sm_flags; /* San Mgmt Flags (see below) */
int sm_ncmds; /* # of pending commands */
int sm_cb_count; /* # callbacks in progress */
fc_ulp_port_info_t sm_port_info; /* FCA Port Information */
fcsm_job_t *sm_job_head; /* port's job queue head */
fcsm_job_t *sm_job_tail; /* port's job queue tail */
struct fcsm_cmd *sm_retry_head; /* cmd retry queue head */
struct fcsm_cmd *sm_retry_tail; /* cmd retry queue tail */
timeout_id_t sm_retry_tid; /* retry timer */
timeout_id_t sm_offline_tid; /* offline timer */
kcondvar_t sm_job_cv; /* cv for job processing */
uint32_t sm_dev_count; /* # of devices discovered */
fc_portmap_t *sm_portmap; /* device map */
kthread_t *sm_thread; /* per port job thread */
kmem_cache_t *sm_cmd_cache; /* per port fc packet cache */
la_els_logi_t sm_ms_service_params;
/* Mgmt Server Login Params */
callb_cpr_t sm_cpr_info; /* CPR info */
} fcsm_t;
typedef struct fcsm_cmd {
fc_packet_t *cmd_fp_pkt;
fcsm_job_t *cmd_job;
fcsm_t *cmd_fcsm;
int cmd_retry_count;
int cmd_retry_interval;
int cmd_max_retries;
struct fcsm_cmd *cmd_next;
void (*cmd_comp)(struct fcsm_cmd *);
int (*cmd_transport)(opaque_t, fc_packet_t *);
uint32_t cmd_dma_flags;
fc_packet_t cmd_fc_packet;
} fcsm_cmd_t;
/*
* sm_flags in the per port FCSM Structure
*/
#define FCSM_ATTACHING 0x0001
#define FCSM_ATTACHED 0x0002
#define FCSM_DETACHING 0x0004
#define FCSM_DETACHED 0x0008
#define FCSM_SUSPENDED 0x0010
#define FCSM_POWER_DOWN 0x0020
#define FCSM_RESTORE_RETRY_TIMEOUT 0x0040
#define FCSM_RESTORE_OFFLINE_TIMEOUT 0x0080
#define FCSM_RETRY_TIMER_ACTIVE 0x0100
#define FCSM_SERIALIZE_JOBTHREAD 0x0200
#define FCSM_CMD_RETRY_Q_SUSPENDED 0x0400
#define FCSM_PORT_OFFLINE 0x0800
#define FCSM_LINK_DOWN 0x1000
#define FCSM_MGMT_SERVER_LOGGED_IN 0x2000
#define FCSM_MGMT_SERVER_LOGIN_IN_PROG 0x4000
#define FCSM_USING_NODMA_FCA 0x8000
/* Command flags for Job structure */
#define FCSM_JOBFLAG_SYNC 0x01
#define FCSM_JOBFLAG_ASYNC 0x02
#define FCSM_JOBFLAG_SERIALIZE 0x04
#define FCSM_JOBFLAG_CTHEADER_BE 0X08
/* Command codes */
#define FCSM_JOB_NONE 0x00
#define FCSM_JOB_THREAD_SHUTDOWN 0x01
#define FCSM_JOB_LOGIN_NAME_SERVER 0x02
#define FCSM_JOB_LOGIN_MGMT_SERVER 0x03
#define FCSM_JOB_CT_PASSTHRU 0x04
/* Private flags for command */
#define FCSM_JOB_PRIV_WAIT_FOR_LOGIN 0x01
#define FCSM_JOB_PRIV_LOGIN_IN_PROG 0x02
/* Command DMA Flags */
#define FCSM_CF_CMD_VALID_DMA_MEM 0x01
#define FCSM_CF_CMD_VALID_DMA_BIND 0x02
#define FCSM_CF_RESP_VALID_DMA_MEM 0x04
#define FCSM_CF_RESP_VALID_DMA_BIND 0x08
#define FCSM_INIT_CMD(cmd, job, tran_flags, tran_type, max_retries, func) { \
(cmd)->cmd_job = (job); \
(cmd)->cmd_fc_packet.pkt_tran_flags = (tran_flags); \
(cmd)->cmd_fc_packet.pkt_tran_type = (tran_type); \
(cmd)->cmd_max_retries = max_retries; \
(cmd)->cmd_comp = func; \
}
/*
* Macros to address endian issues
* local variable "fcsm" must exist before using these
*/
#define FCSM_REP_RD(handle, hostaddr, devaddr, cnt) \
{ \
if (!((fcsm)->sm_flags & FCSM_USING_NODMA_FCA)) { \
ddi_rep_get8((handle), (uint8_t *)(hostaddr), \
(uint8_t *)(devaddr), (cnt), \
DDI_DEV_AUTOINCR); \
} else { \
bcopy((devaddr), (hostaddr), (cnt)); \
} \
}
#define FCSM_REP_WR(handle, hostaddr, devaddr, cnt) \
{ \
if (!((fcsm)->sm_flags & FCSM_USING_NODMA_FCA)) { \
ddi_rep_put8((handle), (uint8_t *)(hostaddr), \
(uint8_t *)(devaddr), (cnt), \
DDI_DEV_AUTOINCR); \
} else { \
bcopy((hostaddr), (devaddr), (cnt)); \
} \
}
#endif /* _KERNEL */
/*
* IOCTL Definitions
*/
typedef struct fc_ct_aiu {
fc_ct_header_t aiu_header;
char aiu_payload[1];
/* aiu_payload can be up to 'm' bytes (arbitrary length) */
} fc_ct_aiu_t;
#define FCSMIO ('S' << 8)
#define FCSMIO_CMD (FCSMIO | 2000)
#define FCSMIO_SUB_CMD ('Y' << 8)
#define FCSMIO_CT_CMD (FCSMIO_SUB_CMD + 0x01)
#define FCSMIO_ADAPTER_LIST (FCSMIO_SUB_CMD + 0x02)
#define FCSMIO_FIND_ADAPTER (FCSMIO_SUB_CMD + 0x03)
#define FCSM_MAX_CT_SIZE (65536) /* 64K */
/* Management Server - Fabric Configuration Server Commands */
#define MS_CS_GTIN 0x0100 /* Get Topology Information */
#define MS_CS_GIEL 0x0101 /* Get Interconnect Element List */
#define MS_CS_GIET 0x0111 /* Get Interconnect Element Type */
#define MS_CS_GDID 0x0112 /* Get Domain Identifier */
#define MS_CS_GMID 0x0113 /* Get Management Identifier */
#define MS_CS_GFN 0x0114 /* Get Fabric Name */
#define MS_CS_GIELN 0x0115 /* Get Interconnect Element Logical Name */
#define MS_CS_GMAL 0x0116 /* Get Management Address List */
#define MS_CS_GIEIL 0x0117 /* Get Interconnect Element Information List */
#define MS_CS_GPL 0x0118 /* Get Port List */
#define MS_CS_GPT 0x0121 /* Get Port Type */
#define MS_CS_GPPN 0x0122 /* Get Physical Port Number */
#define MS_CS_GAPNL 0x0124 /* Get Attached Port Name List */
#define MS_CS_GPS 0x0126 /* Get Port State */
#define MS_CS_GATIN 0x0128 /* Get Attached Topology Information */
#define MS_CS_GPLNL 0x0191 /* Get Platform Node Name List */
#define MS_CS_GPLT 0x0192 /* Get Platform Type */
#define MS_CS_GPLML 0x0193 /* Get Platform Management Address List */
#define MS_CS_GNPL 0x01a1 /* Get Platform Name - Node Name */
#define MS_CS_GPNL 0x01a2 /* Get Platform Name List */
#define MS_CS_GNID 0x01b1 /* Get Node Identification Data - Node Name */
#define MS_CS_RIELN 0x0215 /* Register Interconnect Element Logical Name */
#define MS_CS_RPL 0x0280 /* Register Platform */
#define MS_CS_RPLN 0x0291 /* Register Platform Name */
#define MS_CS_RPLT 0x0292 /* Register Platform Type */
#define MS_CS_RPLM 0x0293 /* Register Platform Management Address */
#define MS_CS_DPL 0x0380 /* Deregister Platform */
#define MS_CS_DPLN 0x0391 /* Deregister Platform Node Name */
#define MS_CS_DPLML 0x0393 /* Deregister Platform Management Addr List */
#ifdef _KERNEL
/*
* Driver entry point functions
*/
static int fcsm_attach(dev_info_t *, ddi_attach_cmd_t);
static int fcsm_detach(dev_info_t *, ddi_detach_cmd_t);
static int fcsm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
static int fcsm_open(dev_t *, int, int, cred_t *);
static int fcsm_close(dev_t, int, int, cred_t *);
static int fcsm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
/*
* FC Transport functions
*/
static int fcsm_port_attach(opaque_t, fc_ulp_port_info_t *,
fc_attach_cmd_t, uint32_t);
static int fcsm_port_detach(opaque_t, fc_ulp_port_info_t *,
fc_detach_cmd_t);
static int fcsm_port_ioctl(opaque_t, opaque_t, dev_t, int, intptr_t,
int, cred_t *, int *, uint32_t);
static void fcsm_statec_cb(opaque_t, opaque_t, uint32_t, uint32_t,
fc_portmap_t *, uint32_t, uint32_t);
static int fcsm_els_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t);
static int fcsm_data_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t);
/*
* Internal functions
*/
static int fcsm_handle_port_attach(fc_ulp_port_info_t *, uint32_t, int);
static int fcsm_handle_port_resume(opaque_t, fc_ulp_port_info_t *,
fc_attach_cmd_t, uint32_t, fcsm_t *);
static int fcsm_handle_port_detach(fc_ulp_port_info_t *, fcsm_t *,
fc_detach_cmd_t);
static void fcsm_suspend_port(fcsm_t *);
static void fcsm_resume_port(fcsm_t *);
static void fcsm_cleanup_port(fcsm_t *);
static void fcsm_offline_timeout(void *);
static int fcsm_fciocmd(intptr_t, int, cred_t *, fcio_t *);
static int fcsm_fcio_copyout(fcio_t *, intptr_t, int);
static int fcsm_job_cache_constructor(void *, void *, int);
static void fcsm_job_cache_destructor(void *, void *);
static fcsm_job_t *fcsm_alloc_job(int);
static void fcsm_dealloc_job(fcsm_job_t *);
static void fcsm_init_job(fcsm_job_t *, int, uint32_t, uint32_t, opaque_t,
opaque_t, void (*comp)(opaque_t, fcsm_job_t *, int),
opaque_t);
static int fcsm_process_job(fcsm_job_t *, int);
static void fcsm_enque_job(fcsm_t *, fcsm_job_t *, int);
static fcsm_job_t *fcsm_deque_job(fcsm_t *);
static int fcsm_cmd_cache_constructor(void *, void *, int);
static void fcsm_cmd_cache_destructor(void *, void *);
static fcsm_cmd_t *fcsm_alloc_cmd(fcsm_t *, uint32_t, uint32_t, int);
static void fcsm_free_cmd_dma(fcsm_cmd_t *);
static void fcsm_job_thread(fcsm_t *);
static int fcsm_retry_job(fcsm_t *fcsm, fcsm_job_t *job);
static void fcsm_jobdone(fcsm_job_t *);
static void fcsm_ct_init(fcsm_t *, fcsm_cmd_t *, fc_ct_aiu_t *, size_t,
void (*comp_func)());
static void fcsm_ct_intr(fcsm_cmd_t *);
static void fcsm_job_ct_passthru(fcsm_job_t *);
static int fcsm_login_and_process_job(fcsm_t *, fcsm_job_t *);
static void fcsm_login_ms_comp(opaque_t, fcsm_job_t *, int);
static void fcsm_els_init(fcsm_cmd_t *, uint32_t);
static int fcsm_xlogi_init(fcsm_t *, fcsm_cmd_t *, uint32_t,
void (*comp_func)(), uchar_t);
static void fcsm_xlogi_intr(fcsm_cmd_t *);
static void fcsm_job_login_mgmt_server(fcsm_job_t *);
int fcsm_ct_passthru(int, fcio_t *, int, int,
void (*func)(fcio_t *));
static void fcsm_ct_passthru_comp(opaque_t, fcsm_job_t *, int);
static void fcsm_pkt_common_intr(fc_packet_t *);
static int fcsm_issue_cmd(fcsm_cmd_t *);
static int fcsm_retry_cmd(fcsm_cmd_t *);
static void fcsm_enque_cmd(fcsm_t *, fcsm_cmd_t *);
static fcsm_cmd_t *fcsm_deque_cmd(fcsm_t *);
static void fcsm_retry_timeout(void *);
static void fcsm_force_port_detach_all(void);
/*
* Utility functions
*/
static void fcsm_disp_devlist(fcsm_t *, fc_portmap_t *, uint32_t);
static void fcsm_display(int, int, fcsm_t *,
fc_packet_t *, const char *, ...);
int fcsm_pkt_state_to_rval(uchar_t, uint32_t);
caddr_t fcsm_port_state_to_str(uint32_t);
caddr_t fcsm_topology_to_str(uint32_t);
static caddr_t fcsm_dev_type_to_str(uint32_t);
#endif /* _KERNEL */
#ifdef __cplusplus
}
#endif
#endif /* _FCSM_H */
|