Print this page
MFV: illumos-omnios@aea0472ecb9ee91fa70556d6f6a941c10c989f1d
Add support for Emulex Corporation Lancer Gen6: LPe32000 FC Host Adapter
Author: Andy Fiddaman <omnios@citrus-it.co.uk>
NEX-8705 Drivers for ATTO Celerity FC-162E Gen 5 and Celerity FC-162P Gen 6 16GB FC cards support
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-1878 update emlxs from source provided by Emulex
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c
+++ new/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at
9 9 * http://www.opensource.org/licenses/cddl1.txt.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2004-2012 Emulex. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #define DEF_ICFG 1
28 28
29 29 #include <emlxs.h>
30 30 #include <emlxs_version.h>
31 31
32 32
33 33 static char emlxs_copyright[] = EMLXS_COPYRIGHT;
34 34 char emlxs_revision[] = EMLXS_REVISION;
35 35 char emlxs_version[] = EMLXS_VERSION;
36 36 char emlxs_name[] = EMLXS_NAME;
37 37 char emlxs_label[] = EMLXS_LABEL;
38 38
39 39 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
40 40 EMLXS_MSG_DEF(EMLXS_SOLARIS_C);
41 41
42 42 #ifdef MENLO_SUPPORT
43 43 static int32_t emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp);
44 44 #endif /* MENLO_SUPPORT */
45 45
46 46 static void emlxs_fca_attach(emlxs_hba_t *hba);
47 47 static void emlxs_fca_detach(emlxs_hba_t *hba);
48 48 static void emlxs_drv_banner(emlxs_hba_t *hba);
49 49
50 50 static int32_t emlxs_get_props(emlxs_hba_t *hba);
51 51 static int32_t emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp,
52 52 uint32_t *pkt_flags);
53 53 static int32_t emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp);
54 54 static int32_t emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp);
55 55 static int32_t emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp);
56 56 static int32_t emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp);
57 57 static int32_t emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp);
58 58 static int32_t emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp);
59 59 static int32_t emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp);
60 60 static uint32_t emlxs_add_instance(int32_t ddiinst);
61 61 static void emlxs_iodone(emlxs_buf_t *sbp);
62 62 static int emlxs_pm_lower_power(dev_info_t *dip);
63 63 static int emlxs_pm_raise_power(dev_info_t *dip);
64 64 static void emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag,
65 65 uint32_t failed);
66 66 static void emlxs_iodone_server(void *arg1, void *arg2, void *arg3);
67 67 static uint32_t emlxs_integrity_check(emlxs_hba_t *hba);
68 68 static uint32_t emlxs_test(emlxs_hba_t *hba, uint32_t test_code,
69 69 uint32_t args, uint32_t *arg);
70 70
71 71 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4)
72 72 static void emlxs_read_vport_prop(emlxs_hba_t *hba);
73 73 #endif /* EMLXS_MODREV3 && EMLXS_MODREV4 */
74 74
75 75 static void emlxs_mode_init_masks(emlxs_hba_t *hba);
76 76
77 77
78 78 extern int
79 79 emlxs_msiid_to_chan(emlxs_hba_t *hba, int msi_id);
80 80 extern int
81 81 emlxs_select_msiid(emlxs_hba_t *hba);
82 82 extern void
83 83 emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba);
84 84
85 85 /*
86 86 * Driver Entry Routines.
87 87 */
88 88 static int32_t emlxs_detach(dev_info_t *, ddi_detach_cmd_t);
89 89 static int32_t emlxs_attach(dev_info_t *, ddi_attach_cmd_t);
90 90 static int32_t emlxs_open(dev_t *, int32_t, int32_t, cred_t *);
91 91 static int32_t emlxs_close(dev_t, int32_t, int32_t, cred_t *);
92 92 static int32_t emlxs_ioctl(dev_t, int32_t, intptr_t, int32_t,
93 93 cred_t *, int32_t *);
94 94 static int32_t emlxs_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
95 95
96 96
97 97 /*
98 98 * FC_AL Transport Functions.
99 99 */
100 100 static opaque_t emlxs_fca_bind_port(dev_info_t *, fc_fca_port_info_t *,
101 101 fc_fca_bind_info_t *);
102 102 static void emlxs_fca_unbind_port(opaque_t);
103 103 static void emlxs_initialize_pkt(emlxs_port_t *, emlxs_buf_t *);
104 104 static int32_t emlxs_fca_get_cap(opaque_t, char *, void *);
105 105 static int32_t emlxs_fca_set_cap(opaque_t, char *, void *);
106 106 static int32_t emlxs_fca_get_map(opaque_t, fc_lilpmap_t *);
107 107 static int32_t emlxs_fca_ub_alloc(opaque_t, uint64_t *, uint32_t,
108 108 uint32_t *, uint32_t);
109 109 static int32_t emlxs_fca_ub_free(opaque_t, uint32_t, uint64_t *);
110 110
111 111 static opaque_t emlxs_fca_get_device(opaque_t, fc_portid_t);
112 112 static int32_t emlxs_fca_notify(opaque_t, uint32_t);
113 113 static void emlxs_ub_els_reject(emlxs_port_t *, fc_unsol_buf_t *);
114 114
115 115 /*
116 116 * Driver Internal Functions.
117 117 */
118 118
119 119 static void emlxs_poll(emlxs_port_t *, emlxs_buf_t *);
120 120 static int32_t emlxs_power(dev_info_t *, int32_t, int32_t);
121 121 #ifdef EMLXS_I386
122 122 #ifdef S11
123 123 static int32_t emlxs_quiesce(dev_info_t *);
124 124 #endif /* S11 */
125 125 #endif /* EMLXS_I386 */
126 126 static int32_t emlxs_hba_resume(dev_info_t *);
127 127 static int32_t emlxs_hba_suspend(dev_info_t *);
128 128 static int32_t emlxs_hba_detach(dev_info_t *);
129 129 static int32_t emlxs_hba_attach(dev_info_t *);
130 130 static void emlxs_lock_destroy(emlxs_hba_t *);
131 131 static void emlxs_lock_init(emlxs_hba_t *);
132 132
133 133 char *emlxs_pm_components[] = {
134 134 "NAME=" DRIVER_NAME "000",
135 135 "0=Device D3 State",
136 136 "1=Device D0 State"
137 137 };
138 138
139 139
140 140 /*
141 141 * Default emlx dma limits
142 142 */
143 143 ddi_dma_lim_t emlxs_dma_lim = {
144 144 (uint32_t)0, /* dlim_addr_lo */
145 145 (uint32_t)0xffffffff, /* dlim_addr_hi */
146 146 (uint_t)0x00ffffff, /* dlim_cntr_max */
147 147 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dlim_burstsizes */
148 148 1, /* dlim_minxfer */
149 149 0x00ffffff /* dlim_dmaspeed */
150 150 };
151 151
152 152 /*
153 153 * Be careful when using these attributes; the defaults listed below are
154 154 * (almost) the most general case, permitting allocation in almost any
155 155 * way supported by the LightPulse family. The sole exception is the
156 156 * alignment specified as requiring memory allocation on a 4-byte boundary;
157 157 * the Lightpulse can DMA memory on any byte boundary.
158 158 *
159 159 * The LightPulse family currently is limited to 16M transfers;
160 160 * this restriction affects the dma_attr_count_max and dma_attr_maxxfer fields.
161 161 */
162 162 ddi_dma_attr_t emlxs_dma_attr = {
163 163 DMA_ATTR_V0, /* dma_attr_version */
164 164 (uint64_t)0, /* dma_attr_addr_lo */
165 165 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */
166 166 (uint64_t)0x00ffffff, /* dma_attr_count_max */
167 167 1, /* dma_attr_align */
168 168 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */
169 169 1, /* dma_attr_minxfer */
170 170 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */
171 171 (uint64_t)0xffffffff, /* dma_attr_seg */
172 172 1, /* dma_attr_sgllen */
173 173 1, /* dma_attr_granular */
174 174 0 /* dma_attr_flags */
175 175 };
176 176
177 177 ddi_dma_attr_t emlxs_dma_attr_ro = {
178 178 DMA_ATTR_V0, /* dma_attr_version */
179 179 (uint64_t)0, /* dma_attr_addr_lo */
180 180 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */
181 181 (uint64_t)0x00ffffff, /* dma_attr_count_max */
182 182 1, /* dma_attr_align */
183 183 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */
184 184 1, /* dma_attr_minxfer */
185 185 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */
186 186 (uint64_t)0xffffffff, /* dma_attr_seg */
187 187 1, /* dma_attr_sgllen */
188 188 1, /* dma_attr_granular */
189 189 DDI_DMA_RELAXED_ORDERING /* dma_attr_flags */
190 190 };
191 191
192 192 ddi_dma_attr_t emlxs_dma_attr_1sg = {
193 193 DMA_ATTR_V0, /* dma_attr_version */
194 194 (uint64_t)0, /* dma_attr_addr_lo */
195 195 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */
196 196 (uint64_t)0x00ffffff, /* dma_attr_count_max */
197 197 1, /* dma_attr_align */
198 198 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */
199 199 1, /* dma_attr_minxfer */
200 200 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */
201 201 (uint64_t)0xffffffff, /* dma_attr_seg */
202 202 1, /* dma_attr_sgllen */
203 203 1, /* dma_attr_granular */
204 204 0 /* dma_attr_flags */
205 205 };
206 206
207 207 #if (EMLXS_MODREV >= EMLXS_MODREV3)
208 208 ddi_dma_attr_t emlxs_dma_attr_fcip_rsp = {
209 209 DMA_ATTR_V0, /* dma_attr_version */
210 210 (uint64_t)0, /* dma_attr_addr_lo */
211 211 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */
212 212 (uint64_t)0x00ffffff, /* dma_attr_count_max */
213 213 1, /* dma_attr_align */
214 214 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */
215 215 1, /* dma_attr_minxfer */
216 216 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */
217 217 (uint64_t)0xffffffff, /* dma_attr_seg */
218 218 1, /* dma_attr_sgllen */
219 219 1, /* dma_attr_granular */
220 220 0 /* dma_attr_flags */
221 221 };
222 222 #endif /* >= EMLXS_MODREV3 */
223 223
224 224 /*
225 225 * DDI access attributes for device
226 226 */
227 227 ddi_device_acc_attr_t emlxs_dev_acc_attr = {
228 228 DDI_DEVICE_ATTR_V1, /* devacc_attr_version */
229 229 DDI_STRUCTURE_LE_ACC, /* PCI is Little Endian */
230 230 DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */
231 231 DDI_DEFAULT_ACC /* devacc_attr_access */
232 232 };
233 233
234 234 /*
235 235 * DDI access attributes for data
236 236 */
237 237 ddi_device_acc_attr_t emlxs_data_acc_attr = {
238 238 DDI_DEVICE_ATTR_V1, /* devacc_attr_version */
239 239 DDI_NEVERSWAP_ACC, /* don't swap for Data */
|
↓ open down ↓ |
239 lines elided |
↑ open up ↑ |
240 240 DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */
241 241 DDI_DEFAULT_ACC /* devacc_attr_access */
242 242 };
243 243
244 244 /*
245 245 * Fill in the FC Transport structure,
246 246 * as defined in the Fibre Channel Transport Programmming Guide.
247 247 */
248 248 #if (EMLXS_MODREV == EMLXS_MODREV5)
249 249 static fc_fca_tran_t emlxs_fca_tran = {
250 - FCTL_FCA_MODREV_5, /* fca_version, with SUN NPIV support */
250 + FCTL_FCA_MODREV_5, /* fca_version, with SUN NPIV support */
251 251 MAX_VPORTS, /* fca numerb of ports */
252 252 sizeof (emlxs_buf_t), /* fca pkt size */
253 253 2048, /* fca cmd max */
254 254 &emlxs_dma_lim, /* fca dma limits */
255 255 0, /* fca iblock, to be filled in later */
256 256 &emlxs_dma_attr, /* fca dma attributes */
257 257 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */
258 258 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */
259 259 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */
260 260 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */
261 261 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */
262 262 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */
263 263 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */
264 - &emlxs_data_acc_attr, /* fca access atributes */
264 + &emlxs_data_acc_attr, /* fca access atributes */
265 265 0, /* fca_num_npivports */
266 266 {0, 0, 0, 0, 0, 0, 0, 0}, /* Physical port WWPN */
267 267 emlxs_fca_bind_port,
268 268 emlxs_fca_unbind_port,
269 269 emlxs_fca_pkt_init,
270 270 emlxs_fca_pkt_uninit,
271 271 emlxs_fca_transport,
272 272 emlxs_fca_get_cap,
273 273 emlxs_fca_set_cap,
274 274 emlxs_fca_get_map,
275 275 emlxs_fca_transport,
276 276 emlxs_fca_ub_alloc,
277 277 emlxs_fca_ub_free,
278 278 emlxs_fca_ub_release,
279 279 emlxs_fca_pkt_abort,
280 280 emlxs_fca_reset,
281 281 emlxs_fca_port_manage,
282 282 emlxs_fca_get_device,
283 283 emlxs_fca_notify
284 284 };
285 285 #endif /* EMLXS_MODREV5 */
286 286
287 287
288 288 #if (EMLXS_MODREV == EMLXS_MODREV4)
289 289 static fc_fca_tran_t emlxs_fca_tran = {
290 290 FCTL_FCA_MODREV_4, /* fca_version */
291 291 MAX_VPORTS, /* fca numerb of ports */
292 292 sizeof (emlxs_buf_t), /* fca pkt size */
293 293 2048, /* fca cmd max */
294 294 &emlxs_dma_lim, /* fca dma limits */
295 295 0, /* fca iblock, to be filled in later */
296 296 &emlxs_dma_attr, /* fca dma attributes */
297 297 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */
298 298 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */
299 299 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */
300 300 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */
301 301 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */
302 302 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */
303 303 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */
304 304 &emlxs_data_acc_attr, /* fca access atributes */
305 305 emlxs_fca_bind_port,
306 306 emlxs_fca_unbind_port,
307 307 emlxs_fca_pkt_init,
308 308 emlxs_fca_pkt_uninit,
309 309 emlxs_fca_transport,
310 310 emlxs_fca_get_cap,
311 311 emlxs_fca_set_cap,
312 312 emlxs_fca_get_map,
313 313 emlxs_fca_transport,
314 314 emlxs_fca_ub_alloc,
315 315 emlxs_fca_ub_free,
316 316 emlxs_fca_ub_release,
317 317 emlxs_fca_pkt_abort,
318 318 emlxs_fca_reset,
319 319 emlxs_fca_port_manage,
320 320 emlxs_fca_get_device,
321 321 emlxs_fca_notify
322 322 };
323 323 #endif /* EMLXS_MODEREV4 */
324 324
325 325
326 326 #if (EMLXS_MODREV == EMLXS_MODREV3)
327 327 static fc_fca_tran_t emlxs_fca_tran = {
328 328 FCTL_FCA_MODREV_3, /* fca_version */
329 329 MAX_VPORTS, /* fca numerb of ports */
330 330 sizeof (emlxs_buf_t), /* fca pkt size */
331 331 2048, /* fca cmd max */
332 332 &emlxs_dma_lim, /* fca dma limits */
333 333 0, /* fca iblock, to be filled in later */
334 334 &emlxs_dma_attr, /* fca dma attributes */
335 335 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */
336 336 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */
337 337 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */
338 338 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */
339 339 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */
340 340 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */
341 341 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */
342 342 &emlxs_data_acc_attr, /* fca access atributes */
343 343 emlxs_fca_bind_port,
344 344 emlxs_fca_unbind_port,
345 345 emlxs_fca_pkt_init,
346 346 emlxs_fca_pkt_uninit,
347 347 emlxs_fca_transport,
348 348 emlxs_fca_get_cap,
349 349 emlxs_fca_set_cap,
350 350 emlxs_fca_get_map,
351 351 emlxs_fca_transport,
352 352 emlxs_fca_ub_alloc,
353 353 emlxs_fca_ub_free,
354 354 emlxs_fca_ub_release,
355 355 emlxs_fca_pkt_abort,
356 356 emlxs_fca_reset,
357 357 emlxs_fca_port_manage,
358 358 emlxs_fca_get_device,
359 359 emlxs_fca_notify
360 360 };
361 361 #endif /* EMLXS_MODREV3 */
362 362
363 363
364 364 #if (EMLXS_MODREV == EMLXS_MODREV2)
365 365 static fc_fca_tran_t emlxs_fca_tran = {
366 366 FCTL_FCA_MODREV_2, /* fca_version */
367 367 MAX_VPORTS, /* number of ports */
368 368 sizeof (emlxs_buf_t), /* pkt size */
369 369 2048, /* max cmds */
370 370 &emlxs_dma_lim, /* DMA limits */
371 371 0, /* iblock, to be filled in later */
372 372 &emlxs_dma_attr, /* dma attributes */
373 373 &emlxs_data_acc_attr, /* access atributes */
374 374 emlxs_fca_bind_port,
375 375 emlxs_fca_unbind_port,
376 376 emlxs_fca_pkt_init,
377 377 emlxs_fca_pkt_uninit,
378 378 emlxs_fca_transport,
379 379 emlxs_fca_get_cap,
380 380 emlxs_fca_set_cap,
381 381 emlxs_fca_get_map,
382 382 emlxs_fca_transport,
383 383 emlxs_fca_ub_alloc,
384 384 emlxs_fca_ub_free,
385 385 emlxs_fca_ub_release,
386 386 emlxs_fca_pkt_abort,
387 387 emlxs_fca_reset,
388 388 emlxs_fca_port_manage,
389 389 emlxs_fca_get_device,
390 390 emlxs_fca_notify
391 391 };
392 392 #endif /* EMLXS_MODREV2 */
393 393
394 394
395 395 /*
396 396 * state pointer which the implementation uses as a place to
397 397 * hang a set of per-driver structures;
398 398 *
399 399 */
400 400 void *emlxs_soft_state = NULL;
401 401
402 402 /*
403 403 * Driver Global variables.
404 404 */
405 405 int32_t emlxs_scsi_reset_delay = 3000; /* milliseconds */
406 406
407 407 emlxs_device_t emlxs_device;
408 408
409 409 uint32_t emlxs_instance[MAX_FC_BRDS]; /* uses emlxs_device.lock */
410 410 uint32_t emlxs_instance_count = 0; /* uses emlxs_device.lock */
411 411 uint32_t emlxs_instance_flag = 0; /* uses emlxs_device.lock */
412 412 #define EMLXS_FW_SHOW 0x00000001
413 413
414 414
415 415 /*
416 416 * CB ops vector. Used for administration only.
417 417 */
418 418 static struct cb_ops emlxs_cb_ops = {
419 419 emlxs_open, /* cb_open */
420 420 emlxs_close, /* cb_close */
421 421 nodev, /* cb_strategy */
422 422 nodev, /* cb_print */
423 423 nodev, /* cb_dump */
424 424 nodev, /* cb_read */
425 425 nodev, /* cb_write */
426 426 emlxs_ioctl, /* cb_ioctl */
427 427 nodev, /* cb_devmap */
428 428 nodev, /* cb_mmap */
429 429 nodev, /* cb_segmap */
430 430 nochpoll, /* cb_chpoll */
431 431 ddi_prop_op, /* cb_prop_op */
432 432 0, /* cb_stream */
433 433 #ifdef _LP64
434 434 D_64BIT | D_HOTPLUG | D_MP | D_NEW, /* cb_flag */
435 435 #else
436 436 D_HOTPLUG | D_MP | D_NEW, /* cb_flag */
437 437 #endif
438 438 CB_REV, /* rev */
439 439 nodev, /* cb_aread */
440 440 nodev /* cb_awrite */
441 441 };
442 442
443 443 static struct dev_ops emlxs_ops = {
444 444 DEVO_REV, /* rev */
445 445 0, /* refcnt */
446 446 emlxs_info, /* getinfo */
447 447 nulldev, /* identify */
448 448 nulldev, /* probe */
449 449 emlxs_attach, /* attach */
450 450 emlxs_detach, /* detach */
451 451 nodev, /* reset */
452 452 &emlxs_cb_ops, /* devo_cb_ops */
453 453 NULL, /* devo_bus_ops */
454 454 emlxs_power, /* power ops */
455 455 #ifdef EMLXS_I386
456 456 #ifdef S11
457 457 emlxs_quiesce, /* quiesce */
458 458 #endif /* S11 */
459 459 #endif /* EMLXS_I386 */
460 460 };
461 461
462 462 #include <sys/modctl.h>
463 463 extern struct mod_ops mod_driverops;
464 464
465 465 #ifdef SAN_DIAG_SUPPORT
466 466 extern kmutex_t emlxs_sd_bucket_mutex;
467 467 extern sd_bucket_info_t emlxs_sd_bucket;
468 468 #endif /* SAN_DIAG_SUPPORT */
469 469
470 470 /*
471 471 * Module linkage information for the kernel.
472 472 */
473 473 static struct modldrv emlxs_modldrv = {
474 474 &mod_driverops, /* module type - driver */
475 475 emlxs_name, /* module name */
476 476 &emlxs_ops, /* driver ops */
477 477 };
478 478
479 479
480 480 /*
481 481 * Driver module linkage structure
482 482 */
483 483 static struct modlinkage emlxs_modlinkage = {
484 484 MODREV_1, /* ml_rev - must be MODREV_1 */
485 485 &emlxs_modldrv, /* ml_linkage */
|
↓ open down ↓ |
211 lines elided |
↑ open up ↑ |
486 486 NULL /* end of driver linkage */
487 487 };
488 488
489 489
490 490 /* We only need to add entries for non-default return codes. */
491 491 /* Entries do not need to be in order. */
492 492 /* Default: FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, */
493 493 /* FC_EXPLN_NONE, FC_ACTION_RETRYABLE */
494 494
495 495 emlxs_xlat_err_t emlxs_iostat_tbl[] = {
496 -/* {f/w code, pkt_state, pkt_reason, */
497 -/* pkt_expln, pkt_action} */
496 +/* {f/w code, pkt_state, pkt_reason, */
497 +/* pkt_expln, pkt_action} */
498 498
499 499 /* 0x00 - Do not remove */
500 500 {IOSTAT_SUCCESS, FC_PKT_SUCCESS, FC_REASON_NONE,
501 501 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
502 502
503 503 /* 0x01 - Do not remove */
504 504 {IOSTAT_FCP_RSP_ERROR, FC_PKT_SUCCESS, FC_REASON_NONE,
505 505 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
506 506
507 507 /* 0x02 */
508 508 {IOSTAT_REMOTE_STOP, FC_PKT_REMOTE_STOP, FC_REASON_ABTS,
509 509 FC_EXPLN_NONE, FC_ACTION_NON_RETRYABLE},
510 510
511 511 /*
512 512 * This is a default entry.
513 513 * The real codes are written dynamically in emlxs_els.c
514 514 */
515 515 /* 0x09 */
516 516 {IOSTAT_LS_RJT, FC_PKT_LS_RJT, FC_REASON_CMD_UNABLE,
517 517 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
518 518
519 519 /* Special error code */
520 520 /* 0x10 */
521 521 {IOSTAT_DATA_OVERRUN, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN,
522 522 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
523 523
524 524 /* Special error code */
525 525 /* 0x11 */
526 526 {IOSTAT_DATA_UNDERRUN, FC_PKT_TRAN_ERROR, FC_REASON_ABORTED,
527 527 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
528 528
529 529 /* Special error code */
530 530 /* 0x12 */
531 531 {IOSTAT_RSP_INVALID, FC_PKT_TRAN_ERROR, FC_REASON_ABORTED,
532 532 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
533 533
534 534 /* CLASS 2 only */
535 535 /* 0x04 */
536 536 {IOSTAT_NPORT_RJT, FC_PKT_NPORT_RJT, FC_REASON_PROTOCOL_ERROR,
537 537 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
538 538
539 539 /* CLASS 2 only */
540 540 /* 0x05 */
541 541 {IOSTAT_FABRIC_RJT, FC_PKT_FABRIC_RJT, FC_REASON_PROTOCOL_ERROR,
542 542 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
543 543
544 544 /* CLASS 2 only */
545 545 /* 0x06 */
546 546 {IOSTAT_NPORT_BSY, FC_PKT_NPORT_BSY, FC_REASON_PHYSICAL_BUSY,
547 547 FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY},
548 548
549 549 /* CLASS 2 only */
550 550 /* 0x07 */
551 551 {IOSTAT_FABRIC_BSY, FC_PKT_FABRIC_BSY, FC_REASON_FABRIC_BSY,
552 552 FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY},
553 553 };
554 554
555 555 #define IOSTAT_MAX (sizeof (emlxs_iostat_tbl)/sizeof (emlxs_xlat_err_t))
556 556
557 557
558 558 /* We only need to add entries for non-default return codes. */
559 559 /* Entries do not need to be in order. */
560 560 /* Default: FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, */
561 561 /* FC_EXPLN_NONE, FC_ACTION_RETRYABLE} */
562 562
563 563 emlxs_xlat_err_t emlxs_ioerr_tbl[] = {
564 564 /* {f/w code, pkt_state, pkt_reason, */
565 565 /* pkt_expln, pkt_action} */
566 566
567 567 /* 0x01 */
568 568 {IOERR_MISSING_CONTINUE, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN,
569 569 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
570 570
571 571 /* 0x02 */
572 572 {IOERR_SEQUENCE_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT,
573 573 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
574 574
575 575 /* 0x04 */
576 576 {IOERR_INVALID_RPI, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
577 577 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
578 578
579 579 /* 0x05 */
580 580 {IOERR_NO_XRI, FC_PKT_LOCAL_RJT, FC_REASON_XCHG_DROPPED,
581 581 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
582 582
583 583 /* 0x06 */
584 584 {IOERR_ILLEGAL_COMMAND, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_REQ,
585 585 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
586 586
587 587 /* 0x07 */
588 588 {IOERR_XCHG_DROPPED, FC_PKT_LOCAL_RJT, FC_REASON_XCHG_DROPPED,
589 589 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
590 590
591 591 /* 0x08 */
592 592 {IOERR_ILLEGAL_FIELD, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_REQ,
593 593 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
594 594
595 595 /* 0x0B */
596 596 {IOERR_RCV_BUFFER_WAITING, FC_PKT_LOCAL_RJT, FC_REASON_NOMEM,
597 597 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
598 598
599 599 /* 0x0D */
600 600 {IOERR_TX_DMA_FAILED, FC_PKT_LOCAL_RJT, FC_REASON_DMA_ERROR,
601 601 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
602 602
603 603 /* 0x0E */
604 604 {IOERR_RX_DMA_FAILED, FC_PKT_LOCAL_RJT, FC_REASON_DMA_ERROR,
605 605 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
606 606
607 607 /* 0x0F */
608 608 {IOERR_ILLEGAL_FRAME, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_FRAME,
609 609 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
610 610
611 611 /* 0x11 */
612 612 {IOERR_NO_RESOURCES, FC_PKT_LOCAL_RJT, FC_REASON_NOMEM,
613 613 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
614 614
615 615 /* 0x13 */
616 616 {IOERR_ILLEGAL_LENGTH, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_LENGTH,
617 617 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
618 618
619 619 /* 0x14 */
620 620 {IOERR_UNSUPPORTED_FEATURE, FC_PKT_LOCAL_RJT, FC_REASON_UNSUPPORTED,
621 621 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
622 622
623 623 /* 0x15 */
624 624 {IOERR_ABORT_IN_PROGRESS, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED,
625 625 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
626 626
627 627 /* 0x16 */
628 628 {IOERR_ABORT_REQUESTED, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED,
629 629 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
630 630
631 631 /* 0x17 */
632 632 {IOERR_RCV_BUFFER_TIMEOUT, FC_PKT_LOCAL_RJT, FC_REASON_RX_BUF_TIMEOUT,
633 633 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
634 634
635 635 /* 0x18 */
636 636 {IOERR_LOOP_OPEN_FAILURE, FC_PKT_LOCAL_RJT, FC_REASON_FCAL_OPN_FAIL,
637 637 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
638 638
639 639 /* 0x1A */
640 640 {IOERR_LINK_DOWN, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
641 641 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
642 642
643 643 /* 0x21 */
644 644 {IOERR_BAD_HOST_ADDRESS, FC_PKT_LOCAL_RJT, FC_REASON_BAD_SID,
645 645 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
646 646
647 647 /* Occurs at link down */
648 648 /* 0x28 */
649 649 {IOERR_BUFFER_SHORTAGE, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE,
650 650 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
651 651
652 652 /* 0xF0 */
653 653 {IOERR_ABORT_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT,
654 654 FC_EXPLN_NONE, FC_ACTION_RETRYABLE},
655 655 };
656 656
657 657 #define IOERR_MAX (sizeof (emlxs_ioerr_tbl)/sizeof (emlxs_xlat_err_t))
658 658
659 659
660 660
661 661 emlxs_table_t emlxs_error_table[] = {
662 662 {IOERR_SUCCESS, "No error."},
663 663 {IOERR_MISSING_CONTINUE, "Missing continue."},
664 664 {IOERR_SEQUENCE_TIMEOUT, "Sequence timeout."},
665 665 {IOERR_INTERNAL_ERROR, "Internal error."},
666 666 {IOERR_INVALID_RPI, "Invalid RPI."},
667 667 {IOERR_NO_XRI, "No XRI."},
668 668 {IOERR_ILLEGAL_COMMAND, "Illegal command."},
669 669 {IOERR_XCHG_DROPPED, "Exchange dropped."},
670 670 {IOERR_ILLEGAL_FIELD, "Illegal field."},
671 671 {IOERR_RCV_BUFFER_WAITING, "RX buffer waiting."},
672 672 {IOERR_TX_DMA_FAILED, "TX DMA failed."},
673 673 {IOERR_RX_DMA_FAILED, "RX DMA failed."},
674 674 {IOERR_ILLEGAL_FRAME, "Illegal frame."},
675 675 {IOERR_NO_RESOURCES, "No resources."},
676 676 {IOERR_ILLEGAL_LENGTH, "Illegal length."},
677 677 {IOERR_UNSUPPORTED_FEATURE, "Unsupported feature."},
678 678 {IOERR_ABORT_IN_PROGRESS, "Abort in progess."},
679 679 {IOERR_ABORT_REQUESTED, "Abort requested."},
680 680 {IOERR_RCV_BUFFER_TIMEOUT, "RX buffer timeout."},
681 681 {IOERR_LOOP_OPEN_FAILURE, "Loop open failed."},
682 682 {IOERR_RING_RESET, "Ring reset."},
683 683 {IOERR_LINK_DOWN, "Link down."},
684 684 {IOERR_CORRUPTED_DATA, "Corrupted data."},
685 685 {IOERR_CORRUPTED_RPI, "Corrupted RPI."},
686 686 {IOERR_OUT_OF_ORDER_DATA, "Out-of-order data."},
687 687 {IOERR_OUT_OF_ORDER_ACK, "Out-of-order ack."},
688 688 {IOERR_DUP_FRAME, "Duplicate frame."},
689 689 {IOERR_LINK_CONTROL_FRAME, "Link control frame."},
690 690 {IOERR_BAD_HOST_ADDRESS, "Bad host address."},
691 691 {IOERR_RCV_HDRBUF_WAITING, "RX header buffer waiting."},
692 692 {IOERR_MISSING_HDR_BUFFER, "Missing header buffer."},
693 693 {IOERR_MSEQ_CHAIN_CORRUPTED, "MSEQ chain corrupted."},
694 694 {IOERR_ABORTMULT_REQUESTED, "Abort multiple requested."},
695 695 {IOERR_BUFFER_SHORTAGE, "Buffer shortage."},
696 696 {IOERR_XRIBUF_WAITING, "XRI buffer shortage"},
697 697 {IOERR_XRIBUF_MISSING, "XRI buffer missing"},
698 698 {IOERR_ROFFSET_INVAL, "Relative offset invalid."},
699 699 {IOERR_ROFFSET_MISSING, "Relative offset missing."},
700 700 {IOERR_INSUF_BUFFER, "Buffer too small."},
701 701 {IOERR_MISSING_SI, "ELS frame missing SI"},
702 702 {IOERR_MISSING_ES, "Exhausted burst without ES"},
703 703 {IOERR_INCOMP_XFER, "Transfer incomplete."},
704 704 {IOERR_ABORT_TIMEOUT, "Abort timeout."}
705 705
706 706 }; /* emlxs_error_table */
707 707
708 708
709 709 emlxs_table_t emlxs_state_table[] = {
710 710 {IOSTAT_SUCCESS, "Success."},
711 711 {IOSTAT_FCP_RSP_ERROR, "FCP response error."},
712 712 {IOSTAT_REMOTE_STOP, "Remote stop."},
713 713 {IOSTAT_LOCAL_REJECT, "Local reject."},
714 714 {IOSTAT_NPORT_RJT, "NPort reject."},
715 715 {IOSTAT_FABRIC_RJT, "Fabric reject."},
716 716 {IOSTAT_NPORT_BSY, "Nport busy."},
717 717 {IOSTAT_FABRIC_BSY, "Fabric busy."},
718 718 {IOSTAT_INTERMED_RSP, "Intermediate response."},
719 719 {IOSTAT_LS_RJT, "LS reject."},
720 720 {IOSTAT_CMD_REJECT, "Cmd reject."},
721 721 {IOSTAT_FCP_TGT_LENCHK, "TGT length check."},
722 722 {IOSTAT_NEED_BUFF_ENTRY, "Need buffer entry."},
723 723 {IOSTAT_DATA_UNDERRUN, "Data underrun."},
724 724 {IOSTAT_DATA_OVERRUN, "Data overrun."},
725 725 {IOSTAT_RSP_INVALID, "Response Invalid."},
726 726
727 727 }; /* emlxs_state_table */
728 728
729 729
730 730 #ifdef MENLO_SUPPORT
731 731 emlxs_table_t emlxs_menlo_cmd_table[] = {
732 732 {MENLO_CMD_INITIALIZE, "MENLO_INIT"},
733 733 {MENLO_CMD_FW_DOWNLOAD, "MENLO_FW_DOWNLOAD"},
734 734 {MENLO_CMD_READ_MEMORY, "MENLO_READ_MEM"},
735 735 {MENLO_CMD_WRITE_MEMORY, "MENLO_WRITE_MEM"},
736 736 {MENLO_CMD_FTE_INSERT, "MENLO_FTE_INSERT"},
737 737 {MENLO_CMD_FTE_DELETE, "MENLO_FTE_DELETE"},
738 738
739 739 {MENLO_CMD_GET_INIT, "MENLO_GET_INIT"},
740 740 {MENLO_CMD_GET_CONFIG, "MENLO_GET_CONFIG"},
741 741 {MENLO_CMD_GET_PORT_STATS, "MENLO_GET_PORT_STATS"},
742 742 {MENLO_CMD_GET_LIF_STATS, "MENLO_GET_LIF_STATS"},
743 743 {MENLO_CMD_GET_ASIC_STATS, "MENLO_GET_ASIC_STATS"},
744 744 {MENLO_CMD_GET_LOG_CONFIG, "MENLO_GET_LOG_CFG"},
745 745 {MENLO_CMD_GET_LOG_DATA, "MENLO_GET_LOG_DATA"},
746 746 {MENLO_CMD_GET_PANIC_LOG, "MENLO_GET_PANIC_LOG"},
747 747 {MENLO_CMD_GET_LB_MODE, "MENLO_GET_LB_MODE"},
748 748
749 749 {MENLO_CMD_SET_PAUSE, "MENLO_SET_PAUSE"},
750 750 {MENLO_CMD_SET_FCOE_COS, "MENLO_SET_FCOE_COS"},
751 751 {MENLO_CMD_SET_UIF_PORT_TYPE, "MENLO_SET_UIF_TYPE"},
752 752
753 753 {MENLO_CMD_DIAGNOSTICS, "MENLO_DIAGNOSTICS"},
754 754 {MENLO_CMD_LOOPBACK, "MENLO_LOOPBACK"},
755 755
756 756 {MENLO_CMD_RESET, "MENLO_RESET"},
757 757 {MENLO_CMD_SET_MODE, "MENLO_SET_MODE"}
758 758
759 759 }; /* emlxs_menlo_cmd_table */
760 760
761 761 emlxs_table_t emlxs_menlo_rsp_table[] = {
762 762 {MENLO_RSP_SUCCESS, "SUCCESS"},
763 763 {MENLO_ERR_FAILED, "FAILED"},
764 764 {MENLO_ERR_INVALID_CMD, "INVALID_CMD"},
765 765 {MENLO_ERR_INVALID_CREDIT, "INVALID_CREDIT"},
766 766 {MENLO_ERR_INVALID_SIZE, "INVALID_SIZE"},
767 767 {MENLO_ERR_INVALID_ADDRESS, "INVALID_ADDRESS"},
768 768 {MENLO_ERR_INVALID_CONTEXT, "INVALID_CONTEXT"},
769 769 {MENLO_ERR_INVALID_LENGTH, "INVALID_LENGTH"},
770 770 {MENLO_ERR_INVALID_TYPE, "INVALID_TYPE"},
771 771 {MENLO_ERR_INVALID_DATA, "INVALID_DATA"},
772 772 {MENLO_ERR_INVALID_VALUE1, "INVALID_VALUE1"},
773 773 {MENLO_ERR_INVALID_VALUE2, "INVALID_VALUE2"},
774 774 {MENLO_ERR_INVALID_MASK, "INVALID_MASK"},
775 775 {MENLO_ERR_CHECKSUM, "CHECKSUM_ERROR"},
776 776 {MENLO_ERR_UNKNOWN_FCID, "UNKNOWN_FCID"},
777 777 {MENLO_ERR_UNKNOWN_WWN, "UNKNOWN_WWN"},
778 778 {MENLO_ERR_BUSY, "BUSY"},
779 779
780 780 }; /* emlxs_menlo_rsp_table */
781 781
782 782 #endif /* MENLO_SUPPORT */
783 783
784 784
785 785 emlxs_table_t emlxs_mscmd_table[] = {
786 786 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
787 787 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
788 788 {MS_GTIN, "MS_GTIN"},
789 789 {MS_GIEL, "MS_GIEL"},
790 790 {MS_GIET, "MS_GIET"},
791 791 {MS_GDID, "MS_GDID"},
792 792 {MS_GMID, "MS_GMID"},
793 793 {MS_GFN, "MS_GFN"},
794 794 {MS_GIELN, "MS_GIELN"},
795 795 {MS_GMAL, "MS_GMAL"},
796 796 {MS_GIEIL, "MS_GIEIL"},
797 797 {MS_GPL, "MS_GPL"},
798 798 {MS_GPT, "MS_GPT"},
799 799 {MS_GPPN, "MS_GPPN"},
800 800 {MS_GAPNL, "MS_GAPNL"},
801 801 {MS_GPS, "MS_GPS"},
802 802 {MS_GPSC, "MS_GPSC"},
803 803 {MS_GATIN, "MS_GATIN"},
804 804 {MS_GSES, "MS_GSES"},
805 805 {MS_GPLNL, "MS_GPLNL"},
806 806 {MS_GPLT, "MS_GPLT"},
807 807 {MS_GPLML, "MS_GPLML"},
808 808 {MS_GPAB, "MS_GPAB"},
809 809 {MS_GNPL, "MS_GNPL"},
810 810 {MS_GPNL, "MS_GPNL"},
811 811 {MS_GPFCP, "MS_GPFCP"},
812 812 {MS_GPLI, "MS_GPLI"},
813 813 {MS_GNID, "MS_GNID"},
814 814 {MS_RIELN, "MS_RIELN"},
815 815 {MS_RPL, "MS_RPL"},
816 816 {MS_RPLN, "MS_RPLN"},
817 817 {MS_RPLT, "MS_RPLT"},
818 818 {MS_RPLM, "MS_RPLM"},
819 819 {MS_RPAB, "MS_RPAB"},
820 820 {MS_RPFCP, "MS_RPFCP"},
821 821 {MS_RPLI, "MS_RPLI"},
822 822 {MS_DPL, "MS_DPL"},
823 823 {MS_DPLN, "MS_DPLN"},
824 824 {MS_DPLM, "MS_DPLM"},
825 825 {MS_DPLML, "MS_DPLML"},
826 826 {MS_DPLI, "MS_DPLI"},
827 827 {MS_DPAB, "MS_DPAB"},
828 828 {MS_DPALL, "MS_DPALL"}
829 829
830 830 }; /* emlxs_mscmd_table */
831 831
832 832
833 833 emlxs_table_t emlxs_ctcmd_table[] = {
834 834 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
835 835 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
836 836 {SLI_CTNS_GA_NXT, "GA_NXT"},
837 837 {SLI_CTNS_GPN_ID, "GPN_ID"},
838 838 {SLI_CTNS_GNN_ID, "GNN_ID"},
839 839 {SLI_CTNS_GCS_ID, "GCS_ID"},
840 840 {SLI_CTNS_GFT_ID, "GFT_ID"},
841 841 {SLI_CTNS_GSPN_ID, "GSPN_ID"},
842 842 {SLI_CTNS_GPT_ID, "GPT_ID"},
843 843 {SLI_CTNS_GID_PN, "GID_PN"},
844 844 {SLI_CTNS_GID_NN, "GID_NN"},
845 845 {SLI_CTNS_GIP_NN, "GIP_NN"},
846 846 {SLI_CTNS_GIPA_NN, "GIPA_NN"},
847 847 {SLI_CTNS_GSNN_NN, "GSNN_NN"},
848 848 {SLI_CTNS_GNN_IP, "GNN_IP"},
849 849 {SLI_CTNS_GIPA_IP, "GIPA_IP"},
850 850 {SLI_CTNS_GID_FT, "GID_FT"},
851 851 {SLI_CTNS_GID_PT, "GID_PT"},
852 852 {SLI_CTNS_RPN_ID, "RPN_ID"},
853 853 {SLI_CTNS_RNN_ID, "RNN_ID"},
854 854 {SLI_CTNS_RCS_ID, "RCS_ID"},
855 855 {SLI_CTNS_RFT_ID, "RFT_ID"},
856 856 {SLI_CTNS_RSPN_ID, "RSPN_ID"},
857 857 {SLI_CTNS_RPT_ID, "RPT_ID"},
858 858 {SLI_CTNS_RIP_NN, "RIP_NN"},
859 859 {SLI_CTNS_RIPA_NN, "RIPA_NN"},
860 860 {SLI_CTNS_RSNN_NN, "RSNN_NN"},
861 861 {SLI_CTNS_DA_ID, "DA_ID"},
862 862 {SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */
863 863
864 864 }; /* emlxs_ctcmd_table */
865 865
866 866
867 867
868 868 emlxs_table_t emlxs_rmcmd_table[] = {
869 869 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
870 870 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
871 871 {CT_OP_GSAT, "RM_GSAT"},
872 872 {CT_OP_GHAT, "RM_GHAT"},
873 873 {CT_OP_GPAT, "RM_GPAT"},
874 874 {CT_OP_GDAT, "RM_GDAT"},
875 875 {CT_OP_GPST, "RM_GPST"},
876 876 {CT_OP_GDP, "RM_GDP"},
877 877 {CT_OP_GDPG, "RM_GDPG"},
878 878 {CT_OP_GEPS, "RM_GEPS"},
879 879 {CT_OP_GLAT, "RM_GLAT"},
880 880 {CT_OP_SSAT, "RM_SSAT"},
881 881 {CT_OP_SHAT, "RM_SHAT"},
882 882 {CT_OP_SPAT, "RM_SPAT"},
883 883 {CT_OP_SDAT, "RM_SDAT"},
884 884 {CT_OP_SDP, "RM_SDP"},
885 885 {CT_OP_SBBS, "RM_SBBS"},
886 886 {CT_OP_RPST, "RM_RPST"},
887 887 {CT_OP_VFW, "RM_VFW"},
888 888 {CT_OP_DFW, "RM_DFW"},
889 889 {CT_OP_RES, "RM_RES"},
890 890 {CT_OP_RHD, "RM_RHD"},
891 891 {CT_OP_UFW, "RM_UFW"},
892 892 {CT_OP_RDP, "RM_RDP"},
893 893 {CT_OP_GHDR, "RM_GHDR"},
894 894 {CT_OP_CHD, "RM_CHD"},
895 895 {CT_OP_SSR, "RM_SSR"},
896 896 {CT_OP_RSAT, "RM_RSAT"},
897 897 {CT_OP_WSAT, "RM_WSAT"},
898 898 {CT_OP_RSAH, "RM_RSAH"},
899 899 {CT_OP_WSAH, "RM_WSAH"},
900 900 {CT_OP_RACT, "RM_RACT"},
901 901 {CT_OP_WACT, "RM_WACT"},
902 902 {CT_OP_RKT, "RM_RKT"},
903 903 {CT_OP_WKT, "RM_WKT"},
904 904 {CT_OP_SSC, "RM_SSC"},
905 905 {CT_OP_QHBA, "RM_QHBA"},
906 906 {CT_OP_GST, "RM_GST"},
907 907 {CT_OP_GFTM, "RM_GFTM"},
908 908 {CT_OP_SRL, "RM_SRL"},
909 909 {CT_OP_SI, "RM_SI"},
910 910 {CT_OP_SRC, "RM_SRC"},
911 911 {CT_OP_GPB, "RM_GPB"},
912 912 {CT_OP_SPB, "RM_SPB"},
913 913 {CT_OP_RPB, "RM_RPB"},
914 914 {CT_OP_RAPB, "RM_RAPB"},
915 915 {CT_OP_GBC, "RM_GBC"},
916 916 {CT_OP_GBS, "RM_GBS"},
917 917 {CT_OP_SBS, "RM_SBS"},
918 918 {CT_OP_GANI, "RM_GANI"},
919 919 {CT_OP_GRV, "RM_GRV"},
920 920 {CT_OP_GAPBS, "RM_GAPBS"},
921 921 {CT_OP_APBC, "RM_APBC"},
922 922 {CT_OP_GDT, "RM_GDT"},
923 923 {CT_OP_GDLMI, "RM_GDLMI"},
924 924 {CT_OP_GANA, "RM_GANA"},
925 925 {CT_OP_GDLV, "RM_GDLV"},
926 926 {CT_OP_GWUP, "RM_GWUP"},
927 927 {CT_OP_GLM, "RM_GLM"},
928 928 {CT_OP_GABS, "RM_GABS"},
929 929 {CT_OP_SABS, "RM_SABS"},
930 930 {CT_OP_RPR, "RM_RPR"},
931 931 {SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */
932 932
933 933 }; /* emlxs_rmcmd_table */
934 934
935 935
936 936 emlxs_table_t emlxs_elscmd_table[] = {
937 937 {ELS_CMD_ACC, "ACC"},
938 938 {ELS_CMD_LS_RJT, "LS_RJT"},
939 939 {ELS_CMD_PLOGI, "PLOGI"},
940 940 {ELS_CMD_FLOGI, "FLOGI"},
941 941 {ELS_CMD_LOGO, "LOGO"},
942 942 {ELS_CMD_ABTX, "ABTX"},
943 943 {ELS_CMD_RCS, "RCS"},
944 944 {ELS_CMD_RES, "RES"},
945 945 {ELS_CMD_RSS, "RSS"},
946 946 {ELS_CMD_RSI, "RSI"},
947 947 {ELS_CMD_ESTS, "ESTS"},
948 948 {ELS_CMD_ESTC, "ESTC"},
949 949 {ELS_CMD_ADVC, "ADVC"},
950 950 {ELS_CMD_RTV, "RTV"},
951 951 {ELS_CMD_RLS, "RLS"},
952 952 {ELS_CMD_ECHO, "ECHO"},
953 953 {ELS_CMD_TEST, "TEST"},
954 954 {ELS_CMD_RRQ, "RRQ"},
955 955 {ELS_CMD_REC, "REC"},
956 956 {ELS_CMD_PRLI, "PRLI"},
957 957 {ELS_CMD_PRLO, "PRLO"},
958 958 {ELS_CMD_SCN, "SCN"},
959 959 {ELS_CMD_TPLS, "TPLS"},
960 960 {ELS_CMD_GPRLO, "GPRLO"},
961 961 {ELS_CMD_GAID, "GAID"},
962 962 {ELS_CMD_FACT, "FACT"},
963 963 {ELS_CMD_FDACT, "FDACT"},
964 964 {ELS_CMD_NACT, "NACT"},
965 965 {ELS_CMD_NDACT, "NDACT"},
966 966 {ELS_CMD_QoSR, "QoSR"},
967 967 {ELS_CMD_RVCS, "RVCS"},
968 968 {ELS_CMD_PDISC, "PDISC"},
969 969 {ELS_CMD_FDISC, "FDISC"},
970 970 {ELS_CMD_ADISC, "ADISC"},
971 971 {ELS_CMD_FARP, "FARP"},
972 972 {ELS_CMD_FARPR, "FARPR"},
973 973 {ELS_CMD_FAN, "FAN"},
974 974 {ELS_CMD_RSCN, "RSCN"},
975 975 {ELS_CMD_SCR, "SCR"},
976 976 {ELS_CMD_LINIT, "LINIT"},
977 977 {ELS_CMD_RNID, "RNID"},
978 978 {ELS_CMD_AUTH, "AUTH"}
979 979
980 980 }; /* emlxs_elscmd_table */
981 981
982 982
983 983 emlxs_table_t emlxs_mode_table[] = {
984 984 {MODE_NONE, "NONE"},
985 985 {MODE_INITIATOR, "INITIATOR"},
986 986 {MODE_TARGET, "TARGET"},
987 987 {MODE_ALL, "INITIATOR | TARGET"}
988 988 }; /* emlxs_mode_table */
989 989
990 990 /*
991 991 *
992 992 * Device Driver Entry Routines
993 993 *
994 994 */
995 995
996 996 #ifdef MODSYM_SUPPORT
997 997 static void emlxs_fca_modclose();
998 998 static int emlxs_fca_modopen();
999 999 emlxs_modsym_t emlxs_modsym; /* uses emlxs_device.lock */
1000 1000
1001 1001 static int
1002 1002 emlxs_fca_modopen()
1003 1003 {
1004 1004 int err;
1005 1005
1006 1006 if (emlxs_modsym.mod_fctl) {
1007 1007 return (0);
1008 1008 }
1009 1009
1010 1010 /* Leadville (fctl) */
1011 1011 err = 0;
1012 1012 emlxs_modsym.mod_fctl =
1013 1013 ddi_modopen("misc/fctl", KRTLD_MODE_FIRST, &err);
1014 1014 if (!emlxs_modsym.mod_fctl) {
1015 1015 cmn_err(CE_WARN,
1016 1016 "?%s: misc/fctl: ddi_modopen misc/fctl failed: error=%d",
1017 1017 DRIVER_NAME, err);
1018 1018
1019 1019 goto failed;
1020 1020 }
1021 1021
1022 1022 err = 0;
1023 1023 /* Check if the fctl fc_fca_attach is present */
1024 1024 emlxs_modsym.fc_fca_attach =
1025 1025 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_attach",
1026 1026 &err);
1027 1027 if ((void *)emlxs_modsym.fc_fca_attach == NULL) {
1028 1028 cmn_err(CE_WARN,
1029 1029 "?%s: misc/fctl: fc_fca_attach not present", DRIVER_NAME);
1030 1030 goto failed;
1031 1031 }
1032 1032
1033 1033 err = 0;
1034 1034 /* Check if the fctl fc_fca_detach is present */
1035 1035 emlxs_modsym.fc_fca_detach =
1036 1036 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_detach",
1037 1037 &err);
1038 1038 if ((void *)emlxs_modsym.fc_fca_detach == NULL) {
1039 1039 cmn_err(CE_WARN,
1040 1040 "?%s: misc/fctl: fc_fca_detach not present", DRIVER_NAME);
1041 1041 goto failed;
1042 1042 }
1043 1043
1044 1044 err = 0;
1045 1045 /* Check if the fctl fc_fca_init is present */
1046 1046 emlxs_modsym.fc_fca_init =
1047 1047 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_init", &err);
1048 1048 if ((void *)emlxs_modsym.fc_fca_init == NULL) {
1049 1049 cmn_err(CE_WARN,
1050 1050 "?%s: misc/fctl: fc_fca_init not present", DRIVER_NAME);
1051 1051 goto failed;
1052 1052 }
1053 1053
1054 1054 return (0);
1055 1055
1056 1056 failed:
1057 1057
1058 1058 emlxs_fca_modclose();
1059 1059
1060 1060 return (1);
1061 1061
1062 1062
1063 1063 } /* emlxs_fca_modopen() */
1064 1064
1065 1065
1066 1066 static void
1067 1067 emlxs_fca_modclose()
1068 1068 {
1069 1069 if (emlxs_modsym.mod_fctl) {
1070 1070 (void) ddi_modclose(emlxs_modsym.mod_fctl);
1071 1071 emlxs_modsym.mod_fctl = 0;
1072 1072 }
1073 1073
1074 1074 emlxs_modsym.fc_fca_attach = NULL;
1075 1075 emlxs_modsym.fc_fca_detach = NULL;
1076 1076 emlxs_modsym.fc_fca_init = NULL;
1077 1077
1078 1078 return;
1079 1079
1080 1080 } /* emlxs_fca_modclose() */
1081 1081
1082 1082 #endif /* MODSYM_SUPPORT */
1083 1083
1084 1084
1085 1085
1086 1086 /*
1087 1087 * Global driver initialization, called once when driver is loaded
1088 1088 */
1089 1089 int
1090 1090 _init(void)
1091 1091 {
1092 1092 int ret;
1093 1093
1094 1094 /*
1095 1095 * First init call for this driver,
1096 1096 * so initialize the emlxs_dev_ctl structure.
1097 1097 */
1098 1098 bzero(&emlxs_device, sizeof (emlxs_device));
1099 1099
1100 1100 #ifdef MODSYM_SUPPORT
1101 1101 bzero(&emlxs_modsym, sizeof (emlxs_modsym_t));
1102 1102 #endif /* MODSYM_SUPPORT */
1103 1103
1104 1104 mutex_init(&emlxs_device.lock, NULL, MUTEX_DRIVER, NULL);
1105 1105
1106 1106 (void) drv_getparm(LBOLT, &emlxs_device.log_timestamp);
1107 1107 emlxs_device.drv_timestamp = ddi_get_time();
1108 1108
1109 1109 for (ret = 0; ret < MAX_FC_BRDS; ret++) {
1110 1110 emlxs_instance[ret] = (uint32_t)-1;
1111 1111 }
1112 1112
1113 1113 /*
1114 1114 * Provide for one ddiinst of the emlxs_dev_ctl structure
1115 1115 * for each possible board in the system.
1116 1116 */
1117 1117 if ((ret = ddi_soft_state_init(&emlxs_soft_state,
1118 1118 sizeof (emlxs_hba_t), MAX_FC_BRDS)) != 0) {
1119 1119 cmn_err(CE_WARN,
1120 1120 "?%s: _init: ddi_soft_state_init failed. rval=%x",
1121 1121 DRIVER_NAME, ret);
1122 1122
1123 1123 return (ret);
1124 1124 }
1125 1125
1126 1126 #ifdef MODSYM_SUPPORT
1127 1127 /* Open SFS */
1128 1128 (void) emlxs_fca_modopen();
1129 1129 #endif /* MODSYM_SUPPORT */
1130 1130
1131 1131 /* Setup devops for SFS */
1132 1132 MODSYM(fc_fca_init)(&emlxs_ops);
1133 1133
1134 1134 if ((ret = mod_install(&emlxs_modlinkage)) != 0) {
1135 1135 (void) ddi_soft_state_fini(&emlxs_soft_state);
1136 1136 #ifdef MODSYM_SUPPORT
1137 1137 /* Close SFS */
1138 1138 emlxs_fca_modclose();
1139 1139 #endif /* MODSYM_SUPPORT */
1140 1140
1141 1141 return (ret);
1142 1142 }
1143 1143
1144 1144 #ifdef SAN_DIAG_SUPPORT
1145 1145 mutex_init(&emlxs_sd_bucket_mutex, NULL, MUTEX_DRIVER, NULL);
1146 1146 #endif /* SAN_DIAG_SUPPORT */
1147 1147
1148 1148 return (ret);
1149 1149
1150 1150 } /* _init() */
1151 1151
1152 1152
1153 1153 /*
1154 1154 * Called when driver is unloaded.
1155 1155 */
1156 1156 int
1157 1157 _fini(void)
1158 1158 {
1159 1159 int ret;
1160 1160
1161 1161 if ((ret = mod_remove(&emlxs_modlinkage)) != 0) {
1162 1162 return (ret);
1163 1163 }
1164 1164 #ifdef MODSYM_SUPPORT
1165 1165 /* Close SFS */
1166 1166 emlxs_fca_modclose();
1167 1167 #endif /* MODSYM_SUPPORT */
1168 1168
1169 1169 /*
1170 1170 * Destroy the soft state structure
1171 1171 */
1172 1172 (void) ddi_soft_state_fini(&emlxs_soft_state);
1173 1173
1174 1174 /* Destroy the global device lock */
1175 1175 mutex_destroy(&emlxs_device.lock);
1176 1176
1177 1177 #ifdef SAN_DIAG_SUPPORT
1178 1178 mutex_destroy(&emlxs_sd_bucket_mutex);
1179 1179 #endif /* SAN_DIAG_SUPPORT */
1180 1180
1181 1181 return (ret);
1182 1182
1183 1183 } /* _fini() */
1184 1184
1185 1185
1186 1186
1187 1187 int
1188 1188 _info(struct modinfo *modinfop)
1189 1189 {
1190 1190
1191 1191 return (mod_info(&emlxs_modlinkage, modinfop));
1192 1192
1193 1193 } /* _info() */
1194 1194
1195 1195
1196 1196 /*
1197 1197 * Attach an ddiinst of an emlx host adapter.
1198 1198 * Allocate data structures, initialize the adapter and we're ready to fly.
1199 1199 */
1200 1200 static int
1201 1201 emlxs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1202 1202 {
1203 1203 emlxs_hba_t *hba;
1204 1204 int ddiinst;
1205 1205 int emlxinst;
1206 1206 int rval;
1207 1207
1208 1208 switch (cmd) {
1209 1209 case DDI_ATTACH:
1210 1210 /* If successful this will set EMLXS_PM_IN_ATTACH */
1211 1211 rval = emlxs_hba_attach(dip);
1212 1212 break;
1213 1213
1214 1214 case DDI_RESUME:
1215 1215 /* This will resume the driver */
1216 1216 rval = emlxs_hba_resume(dip);
1217 1217 break;
1218 1218
1219 1219 default:
1220 1220 rval = DDI_FAILURE;
1221 1221 }
1222 1222
1223 1223 if (rval == DDI_SUCCESS) {
1224 1224 ddiinst = ddi_get_instance(dip);
1225 1225 emlxinst = emlxs_get_instance(ddiinst);
1226 1226 hba = emlxs_device.hba[emlxinst];
1227 1227
1228 1228 if ((hba != NULL) && (hba != (emlxs_hba_t *)-1)) {
1229 1229
1230 1230 /* Enable driver dump feature */
1231 1231 mutex_enter(&EMLXS_PORT_LOCK);
1232 1232 hba->flag |= FC_DUMP_SAFE;
1233 1233 mutex_exit(&EMLXS_PORT_LOCK);
1234 1234 }
1235 1235 }
1236 1236
1237 1237 return (rval);
1238 1238
1239 1239 } /* emlxs_attach() */
1240 1240
1241 1241
1242 1242 /*
1243 1243 * Detach/prepare driver to unload (see detach(9E)).
1244 1244 */
1245 1245 static int
1246 1246 emlxs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1247 1247 {
1248 1248 emlxs_hba_t *hba;
1249 1249 emlxs_port_t *port;
1250 1250 int ddiinst;
1251 1251 int emlxinst;
1252 1252 int rval;
1253 1253
1254 1254 ddiinst = ddi_get_instance(dip);
1255 1255 emlxinst = emlxs_get_instance(ddiinst);
1256 1256 hba = emlxs_device.hba[emlxinst];
1257 1257
1258 1258 if (hba == NULL) {
1259 1259 cmn_err(CE_WARN, "?%s: Detach: NULL device.", DRIVER_NAME);
1260 1260
1261 1261 return (DDI_FAILURE);
1262 1262 }
1263 1263
1264 1264 if (hba == (emlxs_hba_t *)-1) {
1265 1265 cmn_err(CE_WARN, "?%s: Detach: Device attach failed.",
1266 1266 DRIVER_NAME);
1267 1267
1268 1268 return (DDI_FAILURE);
1269 1269 }
1270 1270
1271 1271 port = &PPORT;
1272 1272 rval = DDI_SUCCESS;
1273 1273
1274 1274 /* Check driver dump */
1275 1275 mutex_enter(&EMLXS_PORT_LOCK);
1276 1276
1277 1277 if (hba->flag & FC_DUMP_ACTIVE) {
1278 1278 mutex_exit(&EMLXS_PORT_LOCK);
1279 1279
1280 1280 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1281 1281 "detach: Driver busy. Driver dump active.");
1282 1282
1283 1283 return (DDI_FAILURE);
1284 1284 }
1285 1285
1286 1286 #ifdef SFCT_SUPPORT
1287 1287 if ((port->flag & EMLXS_TGT_BOUND) &&
1288 1288 ((port->fct_flags & FCT_STATE_PORT_ONLINE) ||
1289 1289 (port->fct_flags & FCT_STATE_NOT_ACKED))) {
1290 1290 mutex_exit(&EMLXS_PORT_LOCK);
1291 1291
1292 1292 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1293 1293 "detach: Driver busy. Target mode active.");
1294 1294
1295 1295 return (DDI_FAILURE);
1296 1296 }
1297 1297 #endif /* SFCT_SUPPORT */
1298 1298
1299 1299 if (port->flag & EMLXS_INI_BOUND) {
1300 1300 mutex_exit(&EMLXS_PORT_LOCK);
1301 1301
1302 1302 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1303 1303 "detach: Driver busy. Initiator mode active.");
1304 1304
1305 1305 return (DDI_FAILURE);
1306 1306 }
1307 1307
1308 1308 hba->flag &= ~FC_DUMP_SAFE;
1309 1309
1310 1310 mutex_exit(&EMLXS_PORT_LOCK);
1311 1311
1312 1312 switch (cmd) {
1313 1313 case DDI_DETACH:
1314 1314
1315 1315 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg,
1316 1316 "DDI_DETACH");
1317 1317
1318 1318 rval = emlxs_hba_detach(dip);
1319 1319
1320 1320 if (rval != DDI_SUCCESS) {
1321 1321 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1322 1322 "Unable to detach.");
1323 1323 }
1324 1324 break;
1325 1325
1326 1326 case DDI_SUSPEND:
1327 1327
1328 1328 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg,
1329 1329 "DDI_SUSPEND");
1330 1330
1331 1331 /* Suspend the driver */
1332 1332 rval = emlxs_hba_suspend(dip);
1333 1333
1334 1334 if (rval != DDI_SUCCESS) {
1335 1335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
1336 1336 "Unable to suspend driver.");
1337 1337 }
1338 1338 break;
1339 1339
1340 1340 default:
1341 1341 cmn_err(CE_WARN, "?%s: Detach: Unknown cmd received. cmd=%x",
1342 1342 DRIVER_NAME, cmd);
1343 1343 rval = DDI_FAILURE;
1344 1344 }
1345 1345
1346 1346 if (rval == DDI_FAILURE) {
1347 1347 /* Re-Enable driver dump feature */
1348 1348 mutex_enter(&EMLXS_PORT_LOCK);
1349 1349 hba->flag |= FC_DUMP_SAFE;
1350 1350 mutex_exit(&EMLXS_PORT_LOCK);
1351 1351 }
1352 1352
1353 1353 return (rval);
1354 1354
1355 1355 } /* emlxs_detach() */
1356 1356
1357 1357
1358 1358 /* EMLXS_PORT_LOCK must be held when calling this */
1359 1359 extern void
1360 1360 emlxs_port_init(emlxs_port_t *port)
1361 1361 {
1362 1362 emlxs_hba_t *hba = HBA;
1363 1363
1364 1364 /* Initialize the base node */
1365 1365 bzero((caddr_t)&port->node_base, sizeof (NODELIST));
1366 1366 port->node_base.nlp_Rpi = 0;
1367 1367 port->node_base.nlp_DID = 0xffffff;
1368 1368 port->node_base.nlp_list_next = NULL;
1369 1369 port->node_base.nlp_list_prev = NULL;
1370 1370 port->node_base.nlp_active = 1;
1371 1371 port->node_base.nlp_base = 1;
1372 1372 port->node_count = 0;
1373 1373
1374 1374 if (!(port->flag & EMLXS_PORT_ENABLED)) {
1375 1375 uint8_t dummy_wwn[8] =
1376 1376 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
1377 1377
1378 1378 bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwnn,
1379 1379 sizeof (NAME_TYPE));
1380 1380 bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwpn,
1381 1381 sizeof (NAME_TYPE));
1382 1382 }
1383 1383
1384 1384 if (!(port->flag & EMLXS_PORT_CONFIG)) {
1385 1385 (void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn,
1386 1386 (sizeof (port->snn)-1));
1387 1387 (void) strncpy((caddr_t)port->spn, (caddr_t)hba->spn,
1388 1388 (sizeof (port->spn)-1));
1389 1389 }
1390 1390
1391 1391 bcopy((caddr_t)&hba->sparam, (caddr_t)&port->sparam,
1392 1392 sizeof (SERV_PARM));
1393 1393 bcopy((caddr_t)&port->wwnn, (caddr_t)&port->sparam.nodeName,
1394 1394 sizeof (NAME_TYPE));
1395 1395 bcopy((caddr_t)&port->wwpn, (caddr_t)&port->sparam.portName,
1396 1396 sizeof (NAME_TYPE));
1397 1397
1398 1398 return;
1399 1399
1400 1400 } /* emlxs_port_init() */
1401 1401
1402 1402
1403 1403 void
1404 1404 emlxs_disable_pcie_ce_err(emlxs_hba_t *hba)
1405 1405 {
1406 1406 uint16_t reg;
1407 1407
1408 1408 if (!hba->pci_cap_offset[PCI_CAP_ID_PCI_E]) {
1409 1409 return;
1410 1410 }
1411 1411
1412 1412 /* Turn off the Correctable Error Reporting */
1413 1413 /* (the Device Control Register, bit 0). */
1414 1414 reg = ddi_get16(hba->pci_acc_handle,
1415 1415 (uint16_t *)(hba->pci_addr +
1416 1416 hba->pci_cap_offset[PCI_CAP_ID_PCI_E] +
1417 1417 PCIE_DEVCTL));
1418 1418
1419 1419 reg &= ~1;
1420 1420
1421 1421 (void) ddi_put16(hba->pci_acc_handle,
1422 1422 (uint16_t *)(hba->pci_addr +
1423 1423 hba->pci_cap_offset[PCI_CAP_ID_PCI_E] +
1424 1424 PCIE_DEVCTL),
1425 1425 reg);
1426 1426
1427 1427 return;
1428 1428
1429 1429 } /* emlxs_disable_pcie_ce_err() */
1430 1430
1431 1431
1432 1432 /*
1433 1433 * emlxs_fca_bind_port
1434 1434 *
1435 1435 * Arguments:
1436 1436 *
1437 1437 * dip: the dev_info pointer for the ddiinst
1438 1438 * port_info: pointer to info handed back to the transport
1439 1439 * bind_info: pointer to info from the transport
1440 1440 *
1441 1441 * Return values: a port handle for this port, NULL for failure
1442 1442 *
1443 1443 */
1444 1444 static opaque_t
1445 1445 emlxs_fca_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info,
1446 1446 fc_fca_bind_info_t *bind_info)
1447 1447 {
1448 1448 emlxs_hba_t *hba;
1449 1449 emlxs_port_t *port;
1450 1450 emlxs_port_t *pport;
1451 1451 emlxs_port_t *vport;
1452 1452 int ddiinst;
1453 1453 emlxs_vpd_t *vpd;
1454 1454 emlxs_config_t *cfg;
1455 1455 char *dptr;
1456 1456 char buffer[16];
1457 1457 uint32_t length;
1458 1458 uint32_t len;
1459 1459 char topology[32];
1460 1460 char linkspeed[32];
1461 1461 uint32_t linkstate;
1462 1462
1463 1463 ddiinst = ddi_get_instance(dip);
1464 1464 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
1465 1465 port = &PPORT;
1466 1466 pport = &PPORT;
1467 1467
1468 1468 ddiinst = hba->ddiinst;
1469 1469 vpd = &VPD;
1470 1470 cfg = &CFG;
1471 1471
1472 1472 mutex_enter(&EMLXS_PORT_LOCK);
1473 1473
1474 1474 if (bind_info->port_num > 0) {
1475 1475 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1476 1476 if (!(hba->flag & FC_NPIV_ENABLED) ||
1477 1477 !(bind_info->port_npiv) ||
1478 1478 (bind_info->port_num > hba->vpi_max))
1479 1479 #elif (EMLXS_MODREV >= EMLXS_MODREV3)
1480 1480 if (!(hba->flag & FC_NPIV_ENABLED) ||
1481 1481 (bind_info->port_num > hba->vpi_high))
1482 1482 #endif
1483 1483 {
1484 1484 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1485 1485 "fca_bind_port: Port %d not supported.",
1486 1486 bind_info->port_num);
1487 1487
1488 1488 mutex_exit(&EMLXS_PORT_LOCK);
1489 1489
1490 1490 port_info->pi_error = FC_OUTOFBOUNDS;
1491 1491 return (NULL);
1492 1492 }
1493 1493 }
1494 1494
1495 1495 /* Get true port pointer */
1496 1496 port = &VPORT(bind_info->port_num);
1497 1497
1498 1498 /* Make sure the port is not already bound to the transport */
1499 1499 if (port->flag & EMLXS_INI_BOUND) {
1500 1500
1501 1501 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1502 1502 "fca_bind_port: Port %d already bound. flag=%x",
1503 1503 bind_info->port_num, port->flag);
1504 1504
1505 1505 mutex_exit(&EMLXS_PORT_LOCK);
1506 1506
1507 1507 port_info->pi_error = FC_ALREADY;
1508 1508 return (NULL);
1509 1509 }
1510 1510
1511 1511 if (!(pport->flag & EMLXS_INI_ENABLED)) {
1512 1512 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1513 1513 "fca_bind_port: Physical port does not support "
1514 1514 "initiator mode.");
1515 1515
1516 1516 mutex_exit(&EMLXS_PORT_LOCK);
1517 1517
1518 1518 port_info->pi_error = FC_OUTOFBOUNDS;
1519 1519 return (NULL);
1520 1520 }
1521 1521
1522 1522 /* Make sure port enable flag is set */
1523 1523 /* Just in case fca_port_unbind is called just prior to fca_port_bind */
1524 1524 /* without a driver attach or resume operation */
1525 1525 port->flag |= EMLXS_PORT_ENABLED;
1526 1526
1527 1527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1528 1528 "fca_bind_port: Port %d: port_info=%p bind_info=%p",
1529 1529 bind_info->port_num, port_info, bind_info);
1530 1530
1531 1531 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1532 1532 if (bind_info->port_npiv) {
1533 1533 /* Leadville is telling us about a new virtual port */
1534 1534 bcopy((caddr_t)&bind_info->port_nwwn, (caddr_t)&port->wwnn,
1535 1535 sizeof (NAME_TYPE));
1536 1536 bcopy((caddr_t)&bind_info->port_pwwn, (caddr_t)&port->wwpn,
1537 1537 sizeof (NAME_TYPE));
1538 1538 if (port->snn[0] == 0) {
1539 1539 (void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn,
1540 1540 (sizeof (port->snn)-1));
1541 1541
1542 1542 }
1543 1543
1544 1544 if (port->spn[0] == 0) {
1545 1545 (void) snprintf((caddr_t)port->spn,
1546 1546 (sizeof (port->spn)-1), "%s VPort-%d",
1547 1547 (caddr_t)hba->spn, port->vpi);
1548 1548 }
1549 1549 port->flag |= EMLXS_PORT_CONFIG;
1550 1550 }
1551 1551 #endif /* >= EMLXS_MODREV5 */
1552 1552
1553 1553 /*
1554 1554 * Restricted login should apply both physical and
1555 1555 * virtual ports.
1556 1556 */
1557 1557 if (cfg[CFG_VPORT_RESTRICTED].current) {
1558 1558 port->flag |= EMLXS_PORT_RESTRICTED;
1559 1559 }
1560 1560
1561 1561 /* Perform generic port initialization */
1562 1562 emlxs_port_init(port);
1563 1563
1564 1564 /* Perform SFS specific initialization */
1565 1565 port->ulp_handle = bind_info->port_handle;
1566 1566 port->ulp_statec_cb = bind_info->port_statec_cb;
1567 1567 port->ulp_unsol_cb = bind_info->port_unsol_cb;
1568 1568
1569 1569 /* Set the bound flag */
1570 1570 port->flag |= EMLXS_INI_BOUND;
1571 1571 hba->num_of_ports++;
1572 1572
1573 1573 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1574 1574 mutex_exit(&EMLXS_PORT_LOCK);
1575 1575 (void) emlxs_vpi_port_bind_notify(port);
1576 1576 mutex_enter(&EMLXS_PORT_LOCK);
1577 1577
1578 1578 linkstate = (port->vpip->state == VPI_STATE_PORT_ONLINE)?
1579 1579 FC_LINK_UP:FC_LINK_DOWN;
1580 1580 } else {
1581 1581 linkstate = hba->state;
1582 1582 }
1583 1583
1584 1584 /* Update the port info structure */
1585 1585
1586 1586 /* Set the topology and state */
1587 1587 if (port->mode == MODE_TARGET) {
1588 1588 port_info->pi_port_state = FC_STATE_OFFLINE;
1589 1589 port_info->pi_topology = FC_TOP_UNKNOWN;
1590 1590 } else if ((linkstate < FC_LINK_UP) ||
1591 1591 ((port->vpi > 0) && (!(port->flag & EMLXS_PORT_ENABLED) ||
1592 1592 !(hba->flag & FC_NPIV_SUPPORTED)))) {
1593 1593 port_info->pi_port_state = FC_STATE_OFFLINE;
1594 1594 port_info->pi_topology = FC_TOP_UNKNOWN;
1595 1595 }
1596 1596 #ifdef MENLO_SUPPORT
1597 1597 else if (hba->flag & FC_MENLO_MODE) {
1598 1598 port_info->pi_port_state = FC_STATE_OFFLINE;
1599 1599 port_info->pi_topology = FC_TOP_UNKNOWN;
1600 1600 }
1601 1601 #endif /* MENLO_SUPPORT */
1602 1602 else {
1603 1603 /* Check for loop topology */
1604 1604 if (hba->topology == TOPOLOGY_LOOP) {
1605 1605 port_info->pi_port_state = FC_STATE_LOOP;
1606 1606 (void) strlcpy(topology, ", loop", sizeof (topology));
1607 1607
1608 1608 if (hba->flag & FC_FABRIC_ATTACHED) {
1609 1609 port_info->pi_topology = FC_TOP_PUBLIC_LOOP;
1610 1610 } else {
1611 1611 port_info->pi_topology = FC_TOP_PRIVATE_LOOP;
1612 1612 }
1613 1613 } else {
1614 1614 port_info->pi_topology = FC_TOP_FABRIC;
1615 1615 port_info->pi_port_state = FC_STATE_ONLINE;
1616 1616 (void) strlcpy(topology, ", fabric", sizeof (topology));
1617 1617 }
1618 1618
1619 1619 /* Set the link speed */
1620 1620 switch (hba->linkspeed) {
1621 1621 case 0:
1622 1622 (void) strlcpy(linkspeed, "Gb", sizeof (linkspeed));
1623 1623 port_info->pi_port_state |= FC_STATE_1GBIT_SPEED;
1624 1624 break;
1625 1625
1626 1626 case LA_1GHZ_LINK:
1627 1627 (void) strlcpy(linkspeed, "1Gb", sizeof (linkspeed));
1628 1628 port_info->pi_port_state |= FC_STATE_1GBIT_SPEED;
1629 1629 break;
1630 1630 case LA_2GHZ_LINK:
1631 1631 (void) strlcpy(linkspeed, "2Gb", sizeof (linkspeed));
1632 1632 port_info->pi_port_state |= FC_STATE_2GBIT_SPEED;
1633 1633 break;
1634 1634 case LA_4GHZ_LINK:
1635 1635 (void) strlcpy(linkspeed, "4Gb", sizeof (linkspeed));
1636 1636 port_info->pi_port_state |= FC_STATE_4GBIT_SPEED;
1637 1637 break;
1638 1638 case LA_8GHZ_LINK:
1639 1639 (void) strlcpy(linkspeed, "8Gb", sizeof (linkspeed));
|
↓ open down ↓ |
1132 lines elided |
↑ open up ↑ |
1640 1640 port_info->pi_port_state |= FC_STATE_8GBIT_SPEED;
1641 1641 break;
1642 1642 case LA_10GHZ_LINK:
1643 1643 (void) strlcpy(linkspeed, "10Gb", sizeof (linkspeed));
1644 1644 port_info->pi_port_state |= FC_STATE_10GBIT_SPEED;
1645 1645 break;
1646 1646 case LA_16GHZ_LINK:
1647 1647 (void) strlcpy(linkspeed, "16Gb", sizeof (linkspeed));
1648 1648 port_info->pi_port_state |= FC_STATE_16GBIT_SPEED;
1649 1649 break;
1650 + case LA_32GHZ_LINK:
1651 + (void) strlcpy(linkspeed, "32Gb", sizeof (linkspeed));
1652 + port_info->pi_port_state |= FC_STATE_32GBIT_SPEED;
1653 + break;
1650 1654 default:
1651 1655 (void) snprintf(linkspeed, sizeof (linkspeed),
1652 1656 "unknown(0x%x)", hba->linkspeed);
1653 1657 break;
1654 1658 }
1655 1659
1656 1660 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
1657 1661 /* Adjusting port context for link up messages */
1658 1662 vport = port;
1659 1663 port = &PPORT;
1660 1664 if (vport->vpi == 0) {
1661 1665 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg,
1662 1666 "%s%s, initiator",
1663 1667 linkspeed, topology);
1664 1668 } else if (!(hba->flag & FC_NPIV_LINKUP)) {
1665 1669 hba->flag |= FC_NPIV_LINKUP;
1666 1670 EMLXS_MSGF(EMLXS_CONTEXT,
1667 1671 &emlxs_npiv_link_up_msg,
1668 1672 "%s%s, initiator", linkspeed, topology);
1669 1673 }
1670 1674 port = vport;
1671 1675 }
1672 1676 }
1673 1677
1674 1678 /* PCIE Correctable Error Reporting workaround */
1675 1679 if (((hba->model_info.chip == EMLXS_BE2_CHIP) ||
1676 1680 (hba->model_info.chip == EMLXS_BE3_CHIP)) &&
1677 1681 (bind_info->port_num == 0)) {
1678 1682 emlxs_disable_pcie_ce_err(hba);
1679 1683 }
1680 1684
1681 1685 /* Save initial state */
1682 1686 port->ulp_statec = port_info->pi_port_state;
1683 1687
1684 1688 /*
1685 1689 * The transport needs a copy of the common service parameters
1686 1690 * for this port. The transport can get any updates through
1687 1691 * the getcap entry point.
1688 1692 */
1689 1693 bcopy((void *) &port->sparam,
1690 1694 (void *) &port_info->pi_login_params.common_service,
1691 1695 sizeof (SERV_PARM));
1692 1696
1693 1697 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
1694 1698 /* Swap the service parameters for ULP */
1695 1699 emlxs_swap_service_params((SERV_PARM *)&port_info->pi_login_params.
1696 1700 common_service);
1697 1701 #endif /* EMLXS_MODREV2X */
1698 1702
1699 1703 port_info->pi_login_params.common_service.btob_credit = 0xffff;
1700 1704
1701 1705 bcopy((void *) &port->wwnn,
1702 1706 (void *) &port_info->pi_login_params.node_ww_name,
1703 1707 sizeof (NAME_TYPE));
1704 1708
1705 1709 bcopy((void *) &port->wwpn,
1706 1710 (void *) &port_info->pi_login_params.nport_ww_name,
1707 1711 sizeof (NAME_TYPE));
1708 1712
1709 1713 /*
1710 1714 * We need to turn off CLASS2 support.
1711 1715 * Otherwise, FC transport will use CLASS2 as default class
1712 1716 * and never try with CLASS3.
1713 1717 */
1714 1718 #if (EMLXS_MODREV >= EMLXS_MODREV3)
1715 1719 #if (EMLXS_MODREVX >= EMLXS_MODREV3X)
1716 1720 if ((port_info->pi_login_params.class_1.class_opt) & 0x0080) {
1717 1721 port_info->pi_login_params.class_1.class_opt &= ~0x0080;
1718 1722 }
1719 1723
1720 1724 if ((port_info->pi_login_params.class_2.class_opt) & 0x0080) {
1721 1725 port_info->pi_login_params.class_2.class_opt &= ~0x0080;
1722 1726 }
1723 1727 #else /* EMLXS_SPARC or EMLXS_MODREV2X */
1724 1728 if ((port_info->pi_login_params.class_1.class_opt) & 0x8000) {
1725 1729 port_info->pi_login_params.class_1.class_opt &= ~0x8000;
1726 1730 }
1727 1731
1728 1732 if ((port_info->pi_login_params.class_2.class_opt) & 0x8000) {
1729 1733 port_info->pi_login_params.class_2.class_opt &= ~0x8000;
1730 1734 }
1731 1735 #endif /* >= EMLXS_MODREV3X */
1732 1736 #endif /* >= EMLXS_MODREV3 */
1733 1737
1734 1738
1735 1739 #if (EMLXS_MODREV <= EMLXS_MODREV2)
1736 1740 if ((port_info->pi_login_params.class_1.data[0]) & 0x80) {
1737 1741 port_info->pi_login_params.class_1.data[0] &= ~0x80;
1738 1742 }
1739 1743
1740 1744 if ((port_info->pi_login_params.class_2.data[0]) & 0x80) {
1741 1745 port_info->pi_login_params.class_2.data[0] &= ~0x80;
1742 1746 }
1743 1747 #endif /* <= EMLXS_MODREV2 */
1744 1748
1745 1749 /* Additional parameters */
1746 1750 port_info->pi_s_id.port_id = port->did;
1747 1751 port_info->pi_s_id.priv_lilp_posit = 0;
1748 1752 port_info->pi_hard_addr.hard_addr = cfg[CFG_ASSIGN_ALPA].current;
1749 1753
1750 1754 /* Initialize the RNID parameters */
1751 1755 bzero(&port_info->pi_rnid_params, sizeof (port_info->pi_rnid_params));
1752 1756
1753 1757 (void) snprintf((char *)port_info->pi_rnid_params.params.global_id,
1754 1758 (sizeof (port_info->pi_rnid_params.params.global_id)-1),
1755 1759 "%01x%01x%02x%02x%02x%02x%02x%02x%02x", hba->wwpn.nameType,
1756 1760 hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0],
|
↓ open down ↓ |
97 lines elided |
↑ open up ↑ |
1757 1761 hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3],
1758 1762 hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
1759 1763
1760 1764 port_info->pi_rnid_params.params.unit_type = RNID_HBA;
1761 1765 port_info->pi_rnid_params.params.port_id = port->did;
1762 1766 port_info->pi_rnid_params.params.ip_version = RNID_IPV4;
1763 1767
1764 1768 /* Initialize the port attributes */
1765 1769 bzero(&port_info->pi_attrs, sizeof (port_info->pi_attrs));
1766 1770
1767 - (void) strncpy(port_info->pi_attrs.manufacturer, "Emulex",
1771 + (void) strncpy(port_info->pi_attrs.manufacturer,
1772 + hba->model_info.manufacturer,
1768 1773 (sizeof (port_info->pi_attrs.manufacturer)-1));
1769 1774
1770 1775 port_info->pi_rnid_params.status = FC_SUCCESS;
1771 1776
1772 1777 (void) strncpy(port_info->pi_attrs.serial_number, vpd->serial_num,
1773 1778 (sizeof (port_info->pi_attrs.serial_number)-1));
1774 1779
1775 1780 (void) snprintf(port_info->pi_attrs.firmware_version,
1776 1781 (sizeof (port_info->pi_attrs.firmware_version)-1), "%s (%s)",
1777 1782 vpd->fw_version, vpd->fw_label);
1778 1783
1779 1784 #ifdef EMLXS_I386
1780 1785 (void) snprintf(port_info->pi_attrs.option_rom_version,
1781 1786 (sizeof (port_info->pi_attrs.option_rom_version)-1),
1782 1787 "Boot:%s", vpd->boot_version);
1783 1788 #else /* EMLXS_SPARC */
1784 1789 (void) snprintf(port_info->pi_attrs.option_rom_version,
1785 1790 (sizeof (port_info->pi_attrs.option_rom_version)-1),
1786 1791 "Boot:%s Fcode:%s", vpd->boot_version, vpd->fcode_version);
1787 1792 #endif /* EMLXS_I386 */
1788 1793
1789 1794 (void) snprintf(port_info->pi_attrs.driver_version,
1790 1795 (sizeof (port_info->pi_attrs.driver_version)-1), "%s (%s)",
1791 1796 emlxs_version, emlxs_revision);
1792 1797
1793 1798 (void) strncpy(port_info->pi_attrs.driver_name, DRIVER_NAME,
1794 1799 (sizeof (port_info->pi_attrs.driver_name)-1));
1795 1800
1796 1801 port_info->pi_attrs.vendor_specific_id =
1797 1802 ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX);
1798 1803
1799 1804 port_info->pi_attrs.supported_cos = LE_SWAP32(FC_NS_CLASS3);
1800 1805
1801 1806 port_info->pi_attrs.max_frame_size = FF_FRAME_SIZE;
1802 1807
1803 1808 #if (EMLXS_MODREV >= EMLXS_MODREV3)
1804 1809 port_info->pi_rnid_params.params.num_attached = 0;
1805 1810
1806 1811 if (hba->model_info.chip == EMLXS_LANCER_CHIP) {
1807 1812 uint8_t byte;
1808 1813 uint8_t *wwpn;
1809 1814 uint32_t i;
1810 1815 uint32_t j;
1811 1816
1812 1817 /* Copy the WWPN as a string into the local buffer */
1813 1818 wwpn = (uint8_t *)&hba->wwpn;
1814 1819 for (i = 0; i < 16; i++) {
1815 1820 byte = *wwpn++;
1816 1821 j = ((byte & 0xf0) >> 4);
1817 1822 if (j <= 9) {
1818 1823 buffer[i] =
1819 1824 (char)((uint8_t)'0' + (uint8_t)j);
1820 1825 } else {
1821 1826 buffer[i] =
1822 1827 (char)((uint8_t)'A' + (uint8_t)(j -
1823 1828 10));
1824 1829 }
1825 1830
1826 1831 i++;
1827 1832 j = (byte & 0xf);
1828 1833 if (j <= 9) {
1829 1834 buffer[i] =
1830 1835 (char)((uint8_t)'0' + (uint8_t)j);
1831 1836 } else {
1832 1837 buffer[i] =
1833 1838 (char)((uint8_t)'A' + (uint8_t)(j -
1834 1839 10));
1835 1840 }
1836 1841 }
1837 1842
1838 1843 port_info->pi_attrs.hba_fru_details.port_index = 0;
1839 1844 #if ((EMLXS_MODREV == EMLXS_MODREV3) || (EMLXS_MODREV == EMLXS_MODREV4))
1840 1845
1841 1846 } else if (hba->flag & FC_NPIV_ENABLED) {
1842 1847 uint8_t byte;
1843 1848 uint8_t *wwpn;
1844 1849 uint32_t i;
1845 1850 uint32_t j;
1846 1851
1847 1852 /* Copy the WWPN as a string into the local buffer */
1848 1853 wwpn = (uint8_t *)&hba->wwpn;
1849 1854 for (i = 0; i < 16; i++) {
1850 1855 byte = *wwpn++;
1851 1856 j = ((byte & 0xf0) >> 4);
1852 1857 if (j <= 9) {
1853 1858 buffer[i] =
1854 1859 (char)((uint8_t)'0' + (uint8_t)j);
1855 1860 } else {
1856 1861 buffer[i] =
1857 1862 (char)((uint8_t)'A' + (uint8_t)(j -
1858 1863 10));
1859 1864 }
1860 1865
1861 1866 i++;
1862 1867 j = (byte & 0xf);
1863 1868 if (j <= 9) {
1864 1869 buffer[i] =
1865 1870 (char)((uint8_t)'0' + (uint8_t)j);
1866 1871 } else {
1867 1872 buffer[i] =
1868 1873 (char)((uint8_t)'A' + (uint8_t)(j -
1869 1874 10));
1870 1875 }
1871 1876 }
1872 1877
1873 1878 port_info->pi_attrs.hba_fru_details.port_index = port->vpi;
1874 1879 #endif /* == EMLXS_MODREV3 || EMLXS_MODREV4 */
1875 1880
1876 1881 } else {
1877 1882 /* Copy the serial number string (right most 16 chars) */
1878 1883 /* into the right justified local buffer */
1879 1884 bzero(buffer, sizeof (buffer));
1880 1885 length = strlen(vpd->serial_num);
1881 1886 len = (length > 16) ? 16 : length;
1882 1887 bcopy(&vpd->serial_num[(length - len)],
1883 1888 &buffer[(sizeof (buffer) - len)], len);
1884 1889
1885 1890 port_info->pi_attrs.hba_fru_details.port_index =
1886 1891 vpd->port_index;
1887 1892 }
1888 1893
1889 1894 dptr = (char *)&port_info->pi_attrs.hba_fru_details.high;
1890 1895 dptr[0] = buffer[0];
1891 1896 dptr[1] = buffer[1];
1892 1897 dptr[2] = buffer[2];
1893 1898 dptr[3] = buffer[3];
1894 1899 dptr[4] = buffer[4];
1895 1900 dptr[5] = buffer[5];
1896 1901 dptr[6] = buffer[6];
1897 1902 dptr[7] = buffer[7];
1898 1903 port_info->pi_attrs.hba_fru_details.high =
1899 1904 LE_SWAP64(port_info->pi_attrs.hba_fru_details.high);
1900 1905
1901 1906 dptr = (char *)&port_info->pi_attrs.hba_fru_details.low;
1902 1907 dptr[0] = buffer[8];
1903 1908 dptr[1] = buffer[9];
1904 1909 dptr[2] = buffer[10];
1905 1910 dptr[3] = buffer[11];
1906 1911 dptr[4] = buffer[12];
1907 1912 dptr[5] = buffer[13];
1908 1913 dptr[6] = buffer[14];
1909 1914 dptr[7] = buffer[15];
1910 1915 port_info->pi_attrs.hba_fru_details.low =
1911 1916 LE_SWAP64(port_info->pi_attrs.hba_fru_details.low);
1912 1917
1913 1918 #endif /* >= EMLXS_MODREV3 */
1914 1919
1915 1920 #if (EMLXS_MODREV >= EMLXS_MODREV4)
1916 1921 (void) strncpy((caddr_t)port_info->pi_attrs.sym_node_name,
1917 1922 (caddr_t)port->snn, FCHBA_SYMB_NAME_LEN);
1918 1923 (void) strncpy((caddr_t)port_info->pi_attrs.sym_port_name,
1919 1924 (caddr_t)port->spn, FCHBA_SYMB_NAME_LEN);
1920 1925 #endif /* >= EMLXS_MODREV4 */
1921 1926
1922 1927 (void) snprintf(port_info->pi_attrs.hardware_version,
1923 1928 (sizeof (port_info->pi_attrs.hardware_version)-1),
1924 1929 "%x", vpd->biuRev);
1925 1930
1926 1931 /* Set the hba speed limit */
1927 1932 if (vpd->link_speed & LMT_16GB_CAPABLE) {
1928 1933 port_info->pi_attrs.supported_speed |=
1929 1934 FC_HBA_PORTSPEED_16GBIT;
1930 1935 }
1931 1936 if (vpd->link_speed & LMT_10GB_CAPABLE) {
1932 1937 port_info->pi_attrs.supported_speed |=
1933 1938 FC_HBA_PORTSPEED_10GBIT;
1934 1939 }
1935 1940 if (vpd->link_speed & LMT_8GB_CAPABLE) {
1936 1941 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_8GBIT;
1937 1942 }
1938 1943 if (vpd->link_speed & LMT_4GB_CAPABLE) {
1939 1944 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_4GBIT;
1940 1945 }
1941 1946 if (vpd->link_speed & LMT_2GB_CAPABLE) {
1942 1947 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_2GBIT;
1943 1948 }
1944 1949 if (vpd->link_speed & LMT_1GB_CAPABLE) {
1945 1950 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_1GBIT;
1946 1951 }
1947 1952
1948 1953 /* Set the hba model info */
1949 1954 (void) strncpy(port_info->pi_attrs.model, hba->model_info.model,
1950 1955 (sizeof (port_info->pi_attrs.model)-1));
1951 1956 (void) strncpy(port_info->pi_attrs.model_description,
1952 1957 hba->model_info.model_desc,
1953 1958 (sizeof (port_info->pi_attrs.model_description)-1));
1954 1959
1955 1960
1956 1961 /* Log information */
1957 1962 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1958 1963 "Bind info: port_num = %d", bind_info->port_num);
1959 1964 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1960 1965 "Bind info: port_handle = %p", bind_info->port_handle);
1961 1966
1962 1967 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1963 1968 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1964 1969 "Bind info: port_npiv = %d", bind_info->port_npiv);
1965 1970 #endif /* >= EMLXS_MODREV5 */
1966 1971
1967 1972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1968 1973 "Port info: pi_topology = %x", port_info->pi_topology);
1969 1974 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1970 1975 "Port info: pi_error = %x", port_info->pi_error);
1971 1976 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1972 1977 "Port info: pi_port_state = %x", port_info->pi_port_state);
1973 1978
1974 1979 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1975 1980 "Port info: port_id = %x", port_info->pi_s_id.port_id);
1976 1981 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1977 1982 "Port info: priv_lilp_posit = %x",
1978 1983 port_info->pi_s_id.priv_lilp_posit);
1979 1984
1980 1985 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1981 1986 "Port info: hard_addr = %x",
1982 1987 port_info->pi_hard_addr.hard_addr);
1983 1988
1984 1989 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1985 1990 "Port info: rnid.status = %x",
1986 1991 port_info->pi_rnid_params.status);
1987 1992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1988 1993 "Port info: rnid.global_id = %16s",
1989 1994 port_info->pi_rnid_params.params.global_id);
1990 1995 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1991 1996 "Port info: rnid.unit_type = %x",
1992 1997 port_info->pi_rnid_params.params.unit_type);
1993 1998 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1994 1999 "Port info: rnid.port_id = %x",
1995 2000 port_info->pi_rnid_params.params.port_id);
1996 2001 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
1997 2002 "Port info: rnid.num_attached = %x",
1998 2003 port_info->pi_rnid_params.params.num_attached);
1999 2004 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2000 2005 "Port info: rnid.ip_version = %x",
2001 2006 port_info->pi_rnid_params.params.ip_version);
2002 2007 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2003 2008 "Port info: rnid.udp_port = %x",
2004 2009 port_info->pi_rnid_params.params.udp_port);
2005 2010 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2006 2011 "Port info: rnid.ip_addr = %16s",
2007 2012 port_info->pi_rnid_params.params.ip_addr);
2008 2013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2009 2014 "Port info: rnid.spec_id_resv = %x",
2010 2015 port_info->pi_rnid_params.params.specific_id_resv);
2011 2016 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2012 2017 "Port info: rnid.topo_flags = %x",
2013 2018 port_info->pi_rnid_params.params.topo_flags);
2014 2019
2015 2020 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2016 2021 "Port info: manufacturer = %s",
2017 2022 port_info->pi_attrs.manufacturer);
2018 2023 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2019 2024 "Port info: serial_num = %s",
2020 2025 port_info->pi_attrs.serial_number);
2021 2026 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2022 2027 "Port info: model = %s", port_info->pi_attrs.model);
2023 2028 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2024 2029 "Port info: model_description = %s",
2025 2030 port_info->pi_attrs.model_description);
2026 2031 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2027 2032 "Port info: hardware_version = %s",
2028 2033 port_info->pi_attrs.hardware_version);
2029 2034 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2030 2035 "Port info: driver_version = %s",
2031 2036 port_info->pi_attrs.driver_version);
2032 2037 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2033 2038 "Port info: option_rom_version = %s",
2034 2039 port_info->pi_attrs.option_rom_version);
2035 2040 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2036 2041 "Port info: firmware_version = %s",
2037 2042 port_info->pi_attrs.firmware_version);
2038 2043 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2039 2044 "Port info: driver_name = %s",
2040 2045 port_info->pi_attrs.driver_name);
2041 2046 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2042 2047 "Port info: vendor_specific_id = %x",
2043 2048 port_info->pi_attrs.vendor_specific_id);
2044 2049 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2045 2050 "Port info: supported_cos = %x",
2046 2051 port_info->pi_attrs.supported_cos);
2047 2052 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2048 2053 "Port info: supported_speed = %x",
2049 2054 port_info->pi_attrs.supported_speed);
2050 2055 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2051 2056 "Port info: max_frame_size = %x",
2052 2057 port_info->pi_attrs.max_frame_size);
2053 2058
2054 2059 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2055 2060 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2056 2061 "Port info: fru_port_index = %x",
2057 2062 port_info->pi_attrs.hba_fru_details.port_index);
2058 2063 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2059 2064 "Port info: fru_high = %llx",
2060 2065 port_info->pi_attrs.hba_fru_details.high);
2061 2066 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2062 2067 "Port info: fru_low = %llx",
2063 2068 port_info->pi_attrs.hba_fru_details.low);
2064 2069 #endif /* >= EMLXS_MODREV3 */
2065 2070
2066 2071 #if (EMLXS_MODREV >= EMLXS_MODREV4)
2067 2072 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2068 2073 "Port info: sym_node_name = %s",
2069 2074 port_info->pi_attrs.sym_node_name);
2070 2075 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
2071 2076 "Port info: sym_port_name = %s",
2072 2077 port_info->pi_attrs.sym_port_name);
2073 2078 #endif /* >= EMLXS_MODREV4 */
2074 2079
2075 2080 mutex_exit(&EMLXS_PORT_LOCK);
2076 2081
2077 2082 #ifdef SFCT_SUPPORT
2078 2083 if (port->flag & EMLXS_TGT_ENABLED) {
2079 2084 emlxs_fct_bind_port(port);
2080 2085 }
2081 2086 #endif /* SFCT_SUPPORT */
2082 2087
2083 2088 return ((opaque_t)port);
2084 2089
2085 2090 } /* emlxs_fca_bind_port() */
2086 2091
2087 2092
2088 2093 static void
2089 2094 emlxs_fca_unbind_port(opaque_t fca_port_handle)
2090 2095 {
2091 2096 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2092 2097 emlxs_hba_t *hba = HBA;
2093 2098
2094 2099 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2095 2100 "fca_unbind_port: port=%p", port);
2096 2101
2097 2102 if (!(port->flag & EMLXS_PORT_BOUND)) {
2098 2103 return;
2099 2104 }
2100 2105
2101 2106 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2102 2107 (void) emlxs_vpi_port_unbind_notify(port, 1);
2103 2108 }
2104 2109
2105 2110 /* Destroy & flush all port nodes, if they exist */
2106 2111 if (port->node_count) {
2107 2112 (void) EMLXS_SLI_UNREG_NODE(port, 0, 0, 0, 0);
2108 2113 }
2109 2114
2110 2115 #if (EMLXS_MODREV >= EMLXS_MODREV5)
2111 2116 if ((hba->sli_mode <= EMLXS_HBA_SLI3_MODE) &&
2112 2117 (hba->flag & FC_NPIV_ENABLED) &&
2113 2118 (port->flag & (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED))) {
2114 2119 (void) emlxs_mb_unreg_vpi(port);
2115 2120 }
2116 2121 #endif
2117 2122
2118 2123 mutex_enter(&EMLXS_PORT_LOCK);
2119 2124 if (port->flag & EMLXS_INI_BOUND) {
2120 2125 #if (EMLXS_MODREV >= EMLXS_MODREV5)
2121 2126 port->flag &= ~(EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED);
2122 2127 #endif
2123 2128 port->flag &= ~EMLXS_INI_BOUND;
2124 2129 hba->num_of_ports--;
2125 2130
2126 2131 /* Wait until ulp callback interface is idle */
2127 2132 while (port->ulp_busy) {
2128 2133 mutex_exit(&EMLXS_PORT_LOCK);
2129 2134 delay(drv_usectohz(500000));
2130 2135 mutex_enter(&EMLXS_PORT_LOCK);
2131 2136 }
2132 2137
2133 2138 port->ulp_handle = 0;
2134 2139 port->ulp_statec = FC_STATE_OFFLINE;
2135 2140 port->ulp_statec_cb = NULL;
2136 2141 port->ulp_unsol_cb = NULL;
2137 2142 }
2138 2143 mutex_exit(&EMLXS_PORT_LOCK);
2139 2144
2140 2145 #ifdef SFCT_SUPPORT
2141 2146 /* Check if port was target bound */
2142 2147 if (port->flag & EMLXS_TGT_BOUND) {
2143 2148 emlxs_fct_unbind_port(port);
2144 2149 }
2145 2150 #endif /* SFCT_SUPPORT */
2146 2151
2147 2152 return;
2148 2153
2149 2154 } /* emlxs_fca_unbind_port() */
2150 2155
2151 2156
2152 2157 /*ARGSUSED*/
2153 2158 extern int
2154 2159 emlxs_fca_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep)
2155 2160 {
2156 2161 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2157 2162 emlxs_hba_t *hba = HBA;
2158 2163 emlxs_buf_t *sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
2159 2164
2160 2165 if (!sbp) {
2161 2166 return (FC_FAILURE);
2162 2167 }
2163 2168 bzero((void *)sbp, sizeof (emlxs_buf_t));
2164 2169
2165 2170 mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, DDI_INTR_PRI(hba->intr_arg));
2166 2171 sbp->pkt_flags =
2167 2172 PACKET_VALID | PACKET_ULP_OWNED;
2168 2173 sbp->port = port;
2169 2174 sbp->pkt = pkt;
2170 2175 sbp->iocbq.sbp = sbp;
2171 2176
2172 2177 return (FC_SUCCESS);
2173 2178
2174 2179 } /* emlxs_fca_pkt_init() */
2175 2180
2176 2181
2177 2182
2178 2183 static void
2179 2184 emlxs_initialize_pkt(emlxs_port_t *port, emlxs_buf_t *sbp)
2180 2185 {
2181 2186 emlxs_hba_t *hba = HBA;
2182 2187 emlxs_config_t *cfg = &CFG;
2183 2188 fc_packet_t *pkt = PRIV2PKT(sbp);
2184 2189
2185 2190 mutex_enter(&sbp->mtx);
2186 2191
2187 2192 /* Reinitialize */
2188 2193 sbp->pkt = pkt;
2189 2194 sbp->port = port;
2190 2195 sbp->bmp = NULL;
2191 2196 sbp->pkt_flags &= (PACKET_VALID | PACKET_ALLOCATED);
2192 2197 sbp->iotag = 0;
2193 2198 sbp->ticks = 0;
2194 2199 sbp->abort_attempts = 0;
2195 2200 sbp->fpkt = NULL;
2196 2201 sbp->flush_count = 0;
2197 2202 sbp->next = NULL;
2198 2203
2199 2204 if (port->mode == MODE_INITIATOR) {
2200 2205 sbp->node = NULL;
2201 2206 sbp->did = 0;
2202 2207 sbp->lun = EMLXS_LUN_NONE;
2203 2208 sbp->class = 0;
2204 2209 sbp->channel = NULL;
2205 2210 }
2206 2211
2207 2212 bzero((void *)&sbp->iocbq, sizeof (IOCBQ));
2208 2213 sbp->iocbq.sbp = sbp;
2209 2214
2210 2215 if ((pkt->pkt_tran_flags & FC_TRAN_NO_INTR) || !pkt->pkt_comp ||
2211 2216 ddi_in_panic()) {
2212 2217 sbp->pkt_flags |= PACKET_POLLED;
2213 2218 }
2214 2219
2215 2220 /* Prepare the fc packet */
2216 2221 pkt->pkt_state = FC_PKT_SUCCESS;
2217 2222 pkt->pkt_reason = 0;
2218 2223 pkt->pkt_action = 0;
2219 2224 pkt->pkt_expln = 0;
2220 2225 pkt->pkt_data_resid = 0;
2221 2226 pkt->pkt_resp_resid = 0;
2222 2227
2223 2228 /* Make sure all pkt's have a proper timeout */
2224 2229 if (!cfg[CFG_TIMEOUT_ENABLE].current) {
2225 2230 /* This disables all IOCB on chip timeouts */
2226 2231 pkt->pkt_timeout = 0x80000000;
2227 2232 } else if (pkt->pkt_timeout == 0 || pkt->pkt_timeout == 0xffffffff) {
2228 2233 pkt->pkt_timeout = 60;
2229 2234 }
2230 2235
2231 2236 /* Clear the response buffer */
2232 2237 if (pkt->pkt_rsplen) {
2233 2238 bzero(pkt->pkt_resp, pkt->pkt_rsplen);
2234 2239 }
2235 2240
2236 2241 mutex_exit(&sbp->mtx);
2237 2242
2238 2243 return;
2239 2244
2240 2245 } /* emlxs_initialize_pkt() */
2241 2246
2242 2247
2243 2248
2244 2249 /*
2245 2250 * We may not need this routine
2246 2251 */
2247 2252 /*ARGSUSED*/
2248 2253 extern int
2249 2254 emlxs_fca_pkt_uninit(opaque_t fca_port_handle, fc_packet_t *pkt)
2250 2255 {
2251 2256 emlxs_buf_t *sbp = PKT2PRIV(pkt);
2252 2257
2253 2258 if (!sbp) {
2254 2259 return (FC_FAILURE);
2255 2260 }
2256 2261
2257 2262 if (!(sbp->pkt_flags & PACKET_VALID)) {
2258 2263 return (FC_FAILURE);
2259 2264 }
2260 2265 sbp->pkt_flags &= ~PACKET_VALID;
2261 2266 mutex_destroy(&sbp->mtx);
2262 2267
2263 2268 return (FC_SUCCESS);
2264 2269
2265 2270 } /* emlxs_fca_pkt_uninit() */
2266 2271
2267 2272
2268 2273 static int
2269 2274 emlxs_fca_get_cap(opaque_t fca_port_handle, char *cap, void *ptr)
2270 2275 {
2271 2276 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2272 2277 emlxs_hba_t *hba = HBA;
2273 2278 int32_t rval;
2274 2279 emlxs_config_t *cfg = &CFG;
2275 2280
2276 2281 if (!(port->flag & EMLXS_INI_BOUND)) {
2277 2282 return (FC_CAP_ERROR);
2278 2283 }
2279 2284
2280 2285 if (strcmp(cap, FC_NODE_WWN) == 0) {
2281 2286 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2282 2287 "fca_get_cap: FC_NODE_WWN");
2283 2288
2284 2289 bcopy((void *)&hba->wwnn, (void *)ptr, sizeof (NAME_TYPE));
2285 2290 rval = FC_CAP_FOUND;
2286 2291
2287 2292 } else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
2288 2293 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2289 2294 "fca_get_cap: FC_LOGIN_PARAMS");
2290 2295
2291 2296 /*
2292 2297 * We need to turn off CLASS2 support.
2293 2298 * Otherwise, FC transport will use CLASS2 as default class
2294 2299 * and never try with CLASS3.
2295 2300 */
2296 2301 hba->sparam.cls2.classValid = 0;
2297 2302
2298 2303 bcopy((void *)&hba->sparam, (void *)ptr, sizeof (SERV_PARM));
2299 2304
2300 2305 rval = FC_CAP_FOUND;
2301 2306
2302 2307 } else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) {
2303 2308 int32_t *num_bufs;
2304 2309
2305 2310 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2306 2311 "fca_get_cap: FC_CAP_UNSOL_BUF (%d)",
2307 2312 cfg[CFG_UB_BUFS].current);
2308 2313
2309 2314 num_bufs = (int32_t *)ptr;
2310 2315
2311 2316 /* We multiply by MAX_VPORTS because ULP uses a */
2312 2317 /* formula to calculate ub bufs from this */
2313 2318 *num_bufs = (cfg[CFG_UB_BUFS].current * MAX_VPORTS);
2314 2319
2315 2320 rval = FC_CAP_FOUND;
2316 2321
2317 2322 } else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
2318 2323 int32_t *size;
2319 2324
2320 2325 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2321 2326 "fca_get_cap: FC_CAP_PAYLOAD_SIZE");
2322 2327
2323 2328 size = (int32_t *)ptr;
2324 2329 *size = -1;
2325 2330 rval = FC_CAP_FOUND;
2326 2331
2327 2332 } else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
2328 2333 fc_reset_action_t *action;
2329 2334
2330 2335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2331 2336 "fca_get_cap: FC_CAP_POST_RESET_BEHAVIOR");
2332 2337
2333 2338 action = (fc_reset_action_t *)ptr;
2334 2339 *action = FC_RESET_RETURN_ALL;
2335 2340 rval = FC_CAP_FOUND;
2336 2341
2337 2342 } else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) {
2338 2343 fc_dma_behavior_t *behavior;
2339 2344
2340 2345 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2341 2346 "fca_get_cap: FC_CAP_NOSTREAM_ON_UNALIGN_BUF");
2342 2347
2343 2348 behavior = (fc_dma_behavior_t *)ptr;
2344 2349 *behavior = FC_ALLOW_STREAMING;
2345 2350 rval = FC_CAP_FOUND;
2346 2351
2347 2352 } else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) {
2348 2353 fc_fcp_dma_t *fcp_dma;
2349 2354
2350 2355 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2351 2356 "fca_get_cap: FC_CAP_FCP_DMA");
2352 2357
2353 2358 fcp_dma = (fc_fcp_dma_t *)ptr;
2354 2359 *fcp_dma = FC_DVMA_SPACE;
2355 2360 rval = FC_CAP_FOUND;
2356 2361
2357 2362 } else {
2358 2363 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2359 2364 "fca_get_cap: Unknown capability. [%s]", cap);
2360 2365
2361 2366 rval = FC_CAP_ERROR;
2362 2367
2363 2368 }
2364 2369
2365 2370 return (rval);
2366 2371
2367 2372 } /* emlxs_fca_get_cap() */
2368 2373
2369 2374
2370 2375
2371 2376 static int
2372 2377 emlxs_fca_set_cap(opaque_t fca_port_handle, char *cap, void *ptr)
2373 2378 {
2374 2379 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2375 2380
2376 2381 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2377 2382 "fca_set_cap: cap=[%s] arg=%p", cap, ptr);
2378 2383
2379 2384 return (FC_CAP_ERROR);
2380 2385
2381 2386 } /* emlxs_fca_set_cap() */
2382 2387
2383 2388
2384 2389 static opaque_t
2385 2390 emlxs_fca_get_device(opaque_t fca_port_handle, fc_portid_t d_id)
2386 2391 {
2387 2392 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2388 2393
2389 2394 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2390 2395 "fca_get_device: did=%x", d_id.port_id);
2391 2396
2392 2397 return (NULL);
2393 2398
2394 2399 } /* emlxs_fca_get_device() */
2395 2400
2396 2401
2397 2402 static int32_t
2398 2403 emlxs_fca_notify(opaque_t fca_port_handle, uint32_t cmd)
2399 2404 {
2400 2405 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2401 2406
2402 2407 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, "fca_notify: cmd=%x",
2403 2408 cmd);
2404 2409
2405 2410 return (FC_SUCCESS);
2406 2411
2407 2412 } /* emlxs_fca_notify */
2408 2413
2409 2414
2410 2415
2411 2416 static int
2412 2417 emlxs_fca_get_map(opaque_t fca_port_handle, fc_lilpmap_t *mapbuf)
2413 2418 {
2414 2419 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2415 2420 emlxs_hba_t *hba = HBA;
2416 2421 uint32_t lilp_length;
2417 2422
2418 2423 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2419 2424 "fca_get_map: mapbuf=%p length=%d (%X,%X,%X,%X)", mapbuf,
2420 2425 port->alpa_map[0], port->alpa_map[1], port->alpa_map[2],
2421 2426 port->alpa_map[3], port->alpa_map[4]);
2422 2427
2423 2428 if (!(port->flag & EMLXS_INI_BOUND)) {
2424 2429 return (FC_NOMAP);
2425 2430 }
2426 2431
2427 2432 if (hba->topology != TOPOLOGY_LOOP) {
2428 2433 return (FC_NOMAP);
2429 2434 }
2430 2435
2431 2436 /* Check if alpa map is available */
2432 2437 if (port->alpa_map[0] != 0) {
2433 2438 mapbuf->lilp_magic = MAGIC_LILP;
2434 2439 } else { /* No LILP map available */
2435 2440
2436 2441 /* Set lilp_magic to MAGIC_LISA and this will */
2437 2442 /* trigger an ALPA scan in ULP */
2438 2443 mapbuf->lilp_magic = MAGIC_LISA;
2439 2444 }
2440 2445
2441 2446 mapbuf->lilp_myalpa = port->did;
2442 2447
2443 2448 /* The first byte of the alpa_map is the lilp map length */
2444 2449 /* Add one to include the lilp length byte itself */
2445 2450 lilp_length = (uint32_t)port->alpa_map[0] + 1;
2446 2451
2447 2452 /* Make sure the max transfer is 128 bytes */
2448 2453 if (lilp_length > 128) {
2449 2454 lilp_length = 128;
2450 2455 }
2451 2456
2452 2457 /* We start copying from the lilp_length field */
2453 2458 /* in order to get a word aligned address */
2454 2459 bcopy((void *)&port->alpa_map, (void *)&mapbuf->lilp_length,
2455 2460 lilp_length);
2456 2461
2457 2462 return (FC_SUCCESS);
2458 2463
2459 2464 } /* emlxs_fca_get_map() */
2460 2465
2461 2466
2462 2467
2463 2468 extern int
2464 2469 emlxs_fca_transport(opaque_t fca_port_handle, fc_packet_t *pkt)
2465 2470 {
2466 2471 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2467 2472 emlxs_hba_t *hba = HBA;
2468 2473 emlxs_buf_t *sbp;
2469 2474 uint32_t rval;
2470 2475 uint32_t pkt_flags;
2471 2476
2472 2477 /* Validate packet */
2473 2478 sbp = PKT2PRIV(pkt);
2474 2479
2475 2480 /* Make sure adapter is online */
2476 2481 if (!(hba->flag & FC_ONLINE_MODE) &&
2477 2482 !(sbp->pkt_flags & PACKET_ALLOCATED)) {
2478 2483 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
2479 2484 "Adapter offline.");
2480 2485
2481 2486 rval = (hba->flag & FC_ONLINING_MODE) ?
2482 2487 FC_TRAN_BUSY : FC_OFFLINE;
2483 2488 return (rval);
2484 2489 }
2485 2490
2486 2491 /* Make sure ULP was told that the port was online */
2487 2492 if ((port->ulp_statec == FC_STATE_OFFLINE) &&
2488 2493 !(sbp->pkt_flags & PACKET_ALLOCATED)) {
2489 2494 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2490 2495 "Port offline.");
2491 2496
2492 2497 return (FC_OFFLINE);
2493 2498 }
2494 2499
2495 2500 if (sbp->port != port) {
2496 2501 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
2497 2502 "Invalid port handle. sbp=%p port=%p flags=%x", sbp,
2498 2503 sbp->port, sbp->pkt_flags);
2499 2504 return (FC_BADPACKET);
2500 2505 }
2501 2506
2502 2507 if (!(sbp->pkt_flags & (PACKET_VALID | PACKET_ULP_OWNED))) {
2503 2508 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
2504 2509 "Invalid packet flags. sbp=%p port=%p flags=%x", sbp,
2505 2510 sbp->port, sbp->pkt_flags);
2506 2511 return (FC_BADPACKET);
2507 2512 }
2508 2513
2509 2514 #ifdef SFCT_SUPPORT
2510 2515 if ((port->mode == MODE_TARGET) && !sbp->fct_cmd &&
2511 2516 !(sbp->pkt_flags & PACKET_ALLOCATED)) {
2512 2517 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
2513 2518 "Packet blocked. Target mode.");
2514 2519 return (FC_TRANSPORT_ERROR);
2515 2520 }
2516 2521 #endif /* SFCT_SUPPORT */
2517 2522
2518 2523 #ifdef IDLE_TIMER
2519 2524 emlxs_pm_busy_component(hba);
2520 2525 #endif /* IDLE_TIMER */
2521 2526
2522 2527 /* Prepare the packet for transport */
2523 2528 emlxs_initialize_pkt(port, sbp);
2524 2529
2525 2530 /* Save a copy of the pkt flags. */
2526 2531 /* We will check the polling flag later */
2527 2532 pkt_flags = sbp->pkt_flags;
2528 2533
2529 2534 /* Send the packet */
2530 2535 switch (pkt->pkt_tran_type) {
2531 2536 case FC_PKT_FCP_READ:
2532 2537 case FC_PKT_FCP_WRITE:
2533 2538 rval = emlxs_send_fcp_cmd(port, sbp, &pkt_flags);
2534 2539 break;
2535 2540
2536 2541 case FC_PKT_IP_WRITE:
2537 2542 case FC_PKT_BROADCAST:
2538 2543 rval = emlxs_send_ip(port, sbp);
2539 2544 break;
2540 2545
2541 2546 case FC_PKT_EXCHANGE:
2542 2547 switch (pkt->pkt_cmd_fhdr.type) {
2543 2548 case FC_TYPE_SCSI_FCP:
2544 2549 rval = emlxs_send_fcp_cmd(port, sbp, &pkt_flags);
2545 2550 break;
2546 2551
2547 2552 case FC_TYPE_FC_SERVICES:
2548 2553 rval = emlxs_send_ct(port, sbp);
2549 2554 break;
2550 2555
2551 2556 #ifdef MENLO_SUPPORT
2552 2557 case EMLXS_MENLO_TYPE:
2553 2558 rval = emlxs_send_menlo(port, sbp);
2554 2559 break;
2555 2560 #endif /* MENLO_SUPPORT */
2556 2561
2557 2562 default:
2558 2563 rval = emlxs_send_els(port, sbp);
2559 2564 }
2560 2565 break;
2561 2566
2562 2567 case FC_PKT_OUTBOUND:
2563 2568 switch (pkt->pkt_cmd_fhdr.type) {
2564 2569 #ifdef SFCT_SUPPORT
2565 2570 case FC_TYPE_SCSI_FCP:
2566 2571 rval = emlxs_send_fct_status(port, sbp);
2567 2572 break;
2568 2573
2569 2574 case FC_TYPE_BASIC_LS:
2570 2575 rval = emlxs_send_fct_abort(port, sbp);
2571 2576 break;
2572 2577 #endif /* SFCT_SUPPORT */
2573 2578
2574 2579 case FC_TYPE_FC_SERVICES:
2575 2580 rval = emlxs_send_ct_rsp(port, sbp);
2576 2581 break;
2577 2582 #ifdef MENLO_SUPPORT
2578 2583 case EMLXS_MENLO_TYPE:
2579 2584 rval = emlxs_send_menlo(port, sbp);
2580 2585 break;
2581 2586 #endif /* MENLO_SUPPORT */
2582 2587
2583 2588 default:
2584 2589 rval = emlxs_send_els_rsp(port, sbp);
2585 2590 }
2586 2591 break;
2587 2592
2588 2593 default:
2589 2594 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
2590 2595 "Unsupported pkt_tran_type. type=%x", pkt->pkt_tran_type);
2591 2596 rval = FC_TRANSPORT_ERROR;
2592 2597 break;
2593 2598 }
2594 2599
2595 2600 /* Check if send was not successful */
2596 2601 if (rval != FC_SUCCESS) {
2597 2602 /* Return packet to ULP */
2598 2603 mutex_enter(&sbp->mtx);
2599 2604 sbp->pkt_flags |= PACKET_ULP_OWNED;
2600 2605 mutex_exit(&sbp->mtx);
2601 2606
2602 2607 return (rval);
2603 2608 }
2604 2609
2605 2610 /* Check if this packet should be polled for completion before */
2606 2611 /* returning. This check must be done with a saved copy of the */
2607 2612 /* pkt_flags because the packet itself could already be freed from */
2608 2613 /* memory if it was not polled. */
2609 2614 if (pkt_flags & PACKET_POLLED) {
2610 2615 emlxs_poll(port, sbp);
2611 2616 }
2612 2617
2613 2618 return (FC_SUCCESS);
2614 2619
2615 2620 } /* emlxs_fca_transport() */
2616 2621
2617 2622
2618 2623
2619 2624 static void
2620 2625 emlxs_poll(emlxs_port_t *port, emlxs_buf_t *sbp)
2621 2626 {
2622 2627 emlxs_hba_t *hba = HBA;
2623 2628 fc_packet_t *pkt = PRIV2PKT(sbp);
2624 2629 clock_t timeout;
2625 2630 clock_t time;
2626 2631 CHANNEL *cp;
2627 2632 int in_panic = 0;
2628 2633
2629 2634 mutex_enter(&EMLXS_PORT_LOCK);
2630 2635 hba->io_poll_count++;
2631 2636 mutex_exit(&EMLXS_PORT_LOCK);
2632 2637
2633 2638 /* Check for panic situation */
2634 2639 cp = (CHANNEL *)sbp->channel;
2635 2640
2636 2641 if (ddi_in_panic()) {
2637 2642 in_panic = 1;
2638 2643 /*
2639 2644 * In panic situations there will be one thread with
2640 2645 * no interrrupts (hard or soft) and no timers
2641 2646 */
2642 2647
2643 2648 /*
2644 2649 * We must manually poll everything in this thread
2645 2650 * to keep the driver going.
2646 2651 */
2647 2652
2648 2653 /* Keep polling the chip until our IO is completed */
2649 2654 /* Driver's timer will not function during panics. */
2650 2655 /* Therefore, timer checks must be performed manually. */
2651 2656 (void) drv_getparm(LBOLT, &time);
2652 2657 timeout = time + drv_usectohz(1000000);
2653 2658 while (!(sbp->pkt_flags & PACKET_COMPLETED)) {
2654 2659 EMLXS_SLI_POLL_INTR(hba);
2655 2660 (void) drv_getparm(LBOLT, &time);
2656 2661
2657 2662 /* Trigger timer checks periodically */
2658 2663 if (time >= timeout) {
2659 2664 emlxs_timer_checks(hba);
2660 2665 timeout = time + drv_usectohz(1000000);
2661 2666 }
2662 2667 }
2663 2668 } else {
2664 2669 /* Wait for IO completion */
2665 2670 /* The driver's timer will detect */
2666 2671 /* any timeout and abort the I/O. */
2667 2672 mutex_enter(&EMLXS_PKT_LOCK);
2668 2673 while (!(sbp->pkt_flags & PACKET_COMPLETED)) {
2669 2674 cv_wait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK);
2670 2675 }
2671 2676 mutex_exit(&EMLXS_PKT_LOCK);
2672 2677 }
2673 2678
2674 2679 /* Check for fcp reset pkt */
2675 2680 if (sbp->pkt_flags & PACKET_FCP_RESET) {
2676 2681 if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) {
2677 2682 /* Flush the IO's on the chipq */
2678 2683 (void) emlxs_chipq_node_flush(port,
2679 2684 &hba->chan[hba->channel_fcp],
2680 2685 sbp->node, sbp);
2681 2686 } else {
2682 2687 /* Flush the IO's on the chipq for this lun */
2683 2688 (void) emlxs_chipq_lun_flush(port,
2684 2689 sbp->node, sbp->lun, sbp);
2685 2690 }
2686 2691
2687 2692 if (sbp->flush_count == 0) {
2688 2693 emlxs_node_open(port, sbp->node, hba->channel_fcp);
2689 2694 goto done;
2690 2695 }
2691 2696
2692 2697 /* Set the timeout so the flush has time to complete */
2693 2698 timeout = emlxs_timeout(hba, 60);
2694 2699 (void) drv_getparm(LBOLT, &time);
2695 2700 while ((time < timeout) && sbp->flush_count > 0) {
2696 2701 delay(drv_usectohz(500000));
2697 2702 (void) drv_getparm(LBOLT, &time);
2698 2703 }
2699 2704
2700 2705 if (sbp->flush_count == 0) {
2701 2706 emlxs_node_open(port, sbp->node, hba->channel_fcp);
2702 2707 goto done;
2703 2708 }
2704 2709
2705 2710 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
2706 2711 "sbp=%p flush_count=%d. Waiting...", sbp,
2707 2712 sbp->flush_count);
2708 2713
2709 2714 /* Let's try this one more time */
2710 2715
2711 2716 if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) {
2712 2717 /* Flush the IO's on the chipq */
2713 2718 (void) emlxs_chipq_node_flush(port,
2714 2719 &hba->chan[hba->channel_fcp],
2715 2720 sbp->node, sbp);
2716 2721 } else {
2717 2722 /* Flush the IO's on the chipq for this lun */
2718 2723 (void) emlxs_chipq_lun_flush(port,
2719 2724 sbp->node, sbp->lun, sbp);
2720 2725 }
2721 2726
2722 2727 /* Reset the timeout so the flush has time to complete */
2723 2728 timeout = emlxs_timeout(hba, 60);
2724 2729 (void) drv_getparm(LBOLT, &time);
2725 2730 while ((time < timeout) && sbp->flush_count > 0) {
2726 2731 delay(drv_usectohz(500000));
2727 2732 (void) drv_getparm(LBOLT, &time);
2728 2733 }
2729 2734
2730 2735 if (sbp->flush_count == 0) {
2731 2736 emlxs_node_open(port, sbp->node, hba->channel_fcp);
2732 2737 goto done;
2733 2738 }
2734 2739
2735 2740 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
2736 2741 "sbp=%p flush_count=%d. Resetting link.", sbp,
2737 2742 sbp->flush_count);
2738 2743
2739 2744 /* Let's first try to reset the link */
2740 2745 (void) emlxs_reset(port, FC_FCA_LINK_RESET);
2741 2746
2742 2747 if (sbp->flush_count == 0) {
2743 2748 goto done;
2744 2749 }
2745 2750
2746 2751 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
2747 2752 "sbp=%p flush_count=%d. Resetting HBA.", sbp,
2748 2753 sbp->flush_count);
2749 2754
2750 2755 /* If that doesn't work, reset the adapter */
2751 2756 (void) emlxs_reset(port, FC_FCA_RESET);
2752 2757
2753 2758 if (sbp->flush_count != 0) {
2754 2759 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg,
2755 2760 "sbp=%p flush_count=%d. Giving up.", sbp,
2756 2761 sbp->flush_count);
2757 2762 }
2758 2763
2759 2764 }
2760 2765 /* PACKET_FCP_RESET */
2761 2766 done:
2762 2767
2763 2768 /* Packet has been declared completed and is now ready to be returned */
2764 2769
2765 2770 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
2766 2771 emlxs_unswap_pkt(sbp);
2767 2772 #endif /* EMLXS_MODREV2X */
2768 2773
2769 2774 mutex_enter(&sbp->mtx);
2770 2775 sbp->pkt_flags |= PACKET_ULP_OWNED;
2771 2776 mutex_exit(&sbp->mtx);
2772 2777
2773 2778 mutex_enter(&EMLXS_PORT_LOCK);
2774 2779 hba->io_poll_count--;
2775 2780 mutex_exit(&EMLXS_PORT_LOCK);
2776 2781
2777 2782 #ifdef FMA_SUPPORT
2778 2783 if (!in_panic) {
2779 2784 emlxs_check_dma(hba, sbp);
2780 2785 }
2781 2786 #endif
2782 2787
2783 2788 /* Make ULP completion callback if required */
2784 2789 if (pkt->pkt_comp) {
2785 2790 cp->ulpCmplCmd++;
2786 2791 (*pkt->pkt_comp) (pkt);
2787 2792 }
2788 2793
2789 2794 #ifdef FMA_SUPPORT
2790 2795 if (hba->flag & FC_DMA_CHECK_ERROR) {
2791 2796 emlxs_thread_spawn(hba, emlxs_restart_thread,
2792 2797 NULL, NULL);
2793 2798 }
2794 2799 #endif
2795 2800
2796 2801 return;
2797 2802
2798 2803 } /* emlxs_poll() */
2799 2804
2800 2805
2801 2806 static int
2802 2807 emlxs_fca_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size,
2803 2808 uint32_t *count, uint32_t type)
2804 2809 {
2805 2810 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
2806 2811 emlxs_hba_t *hba = HBA;
2807 2812 char *err = NULL;
2808 2813 emlxs_unsol_buf_t *pool = NULL;
2809 2814 emlxs_unsol_buf_t *new_pool = NULL;
2810 2815 emlxs_config_t *cfg = &CFG;
2811 2816 int32_t i;
2812 2817 int result;
2813 2818 uint32_t free_resv;
2814 2819 uint32_t free;
2815 2820 fc_unsol_buf_t *ubp;
2816 2821 emlxs_ub_priv_t *ub_priv;
2817 2822 int rc;
2818 2823
2819 2824 if (!(port->flag & EMLXS_INI_ENABLED)) {
2820 2825 if (tokens && count) {
2821 2826 bzero(tokens, (sizeof (uint64_t) * (*count)));
2822 2827 }
2823 2828 return (FC_SUCCESS);
2824 2829 }
2825 2830
2826 2831 if (!(port->flag & EMLXS_INI_BOUND)) {
2827 2832 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2828 2833 "fca_ub_alloc failed: Port not bound! size=%x count=%d "
2829 2834 "type=%x", size, *count, type);
2830 2835
2831 2836 return (FC_FAILURE);
2832 2837 }
2833 2838
2834 2839 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2835 2840 "fca_ub_alloc: size=%x count=%d type=%x", size, *count, type);
2836 2841
2837 2842 if (count && (*count > EMLXS_MAX_UBUFS)) {
2838 2843 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
2839 2844 "fca_ub_alloc failed: Too many unsolicted buffers "
2840 2845 "requested. count=%x", *count);
2841 2846
2842 2847 return (FC_FAILURE);
2843 2848
2844 2849 }
2845 2850
2846 2851 if (tokens == NULL) {
2847 2852 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
2848 2853 "fca_ub_alloc failed: Token array is NULL.");
2849 2854
2850 2855 return (FC_FAILURE);
2851 2856 }
2852 2857
2853 2858 /* Clear the token array */
2854 2859 bzero(tokens, (sizeof (uint64_t) * (*count)));
2855 2860
2856 2861 free_resv = 0;
2857 2862 free = *count;
2858 2863 switch (type) {
2859 2864 case FC_TYPE_BASIC_LS:
2860 2865 err = "BASIC_LS";
2861 2866 break;
2862 2867 case FC_TYPE_EXTENDED_LS:
2863 2868 err = "EXTENDED_LS";
2864 2869 free = *count / 2; /* Hold 50% for normal use */
2865 2870 free_resv = *count - free; /* Reserve 50% for RSCN use */
2866 2871 break;
2867 2872 case FC_TYPE_IS8802:
2868 2873 err = "IS8802";
2869 2874 break;
2870 2875 case FC_TYPE_IS8802_SNAP:
2871 2876 err = "IS8802_SNAP";
2872 2877
2873 2878 if (cfg[CFG_NETWORK_ON].current == 0) {
2874 2879 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2875 2880 "fca_ub_alloc failed: IP support is disabled.");
2876 2881
2877 2882 return (FC_FAILURE);
2878 2883 }
2879 2884 break;
2880 2885 case FC_TYPE_SCSI_FCP:
2881 2886 err = "SCSI_FCP";
2882 2887 break;
2883 2888 case FC_TYPE_SCSI_GPP:
2884 2889 err = "SCSI_GPP";
2885 2890 break;
2886 2891 case FC_TYPE_HIPP_FP:
2887 2892 err = "HIPP_FP";
2888 2893 break;
2889 2894 case FC_TYPE_IPI3_MASTER:
2890 2895 err = "IPI3_MASTER";
2891 2896 break;
2892 2897 case FC_TYPE_IPI3_SLAVE:
2893 2898 err = "IPI3_SLAVE";
2894 2899 break;
2895 2900 case FC_TYPE_IPI3_PEER:
2896 2901 err = "IPI3_PEER";
2897 2902 break;
2898 2903 case FC_TYPE_FC_SERVICES:
2899 2904 err = "FC_SERVICES";
2900 2905 break;
2901 2906 }
2902 2907
2903 2908 mutex_enter(&EMLXS_UB_LOCK);
2904 2909
2905 2910 /*
2906 2911 * Walk through the list of the unsolicited buffers
2907 2912 * for this ddiinst of emlx.
2908 2913 */
2909 2914
2910 2915 pool = port->ub_pool;
2911 2916
2912 2917 /*
2913 2918 * The emlxs_fca_ub_alloc() can be called more than once with different
2914 2919 * size. We will reject the call if there are
2915 2920 * duplicate size with the same FC-4 type.
2916 2921 */
2917 2922 while (pool) {
2918 2923 if ((pool->pool_type == type) &&
2919 2924 (pool->pool_buf_size == size)) {
2920 2925 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
2921 2926 "fca_ub_alloc failed: Unsolicited buffer pool "
2922 2927 "for %s of size 0x%x bytes already exists.",
2923 2928 err, size);
2924 2929
2925 2930 result = FC_FAILURE;
2926 2931 goto fail;
2927 2932 }
2928 2933
2929 2934 pool = pool->pool_next;
2930 2935 }
2931 2936
2932 2937 mutex_exit(&EMLXS_UB_LOCK);
2933 2938
2934 2939 new_pool = (emlxs_unsol_buf_t *)kmem_zalloc(sizeof (emlxs_unsol_buf_t),
2935 2940 KM_SLEEP);
2936 2941
2937 2942 new_pool->pool_next = NULL;
2938 2943 new_pool->pool_type = type;
2939 2944 new_pool->pool_buf_size = size;
2940 2945 new_pool->pool_nentries = *count;
2941 2946 new_pool->pool_available = new_pool->pool_nentries;
2942 2947 new_pool->pool_free = free;
2943 2948 new_pool->pool_free_resv = free_resv;
2944 2949 new_pool->fc_ubufs =
2945 2950 kmem_zalloc((sizeof (fc_unsol_buf_t) * (*count)), KM_SLEEP);
2946 2951
2947 2952 new_pool->pool_first_token = port->ub_count;
2948 2953 new_pool->pool_last_token = port->ub_count + new_pool->pool_nentries;
2949 2954
2950 2955 for (i = 0; i < new_pool->pool_nentries; i++) {
2951 2956 ubp = (fc_unsol_buf_t *)&new_pool->fc_ubufs[i];
2952 2957 ubp->ub_port_handle = port->ulp_handle;
2953 2958 ubp->ub_token = (uint64_t)((unsigned long)ubp);
2954 2959 ubp->ub_bufsize = size;
2955 2960 ubp->ub_class = FC_TRAN_CLASS3;
2956 2961 ubp->ub_port_private = NULL;
2957 2962 ubp->ub_fca_private =
2958 2963 (emlxs_ub_priv_t *)kmem_zalloc(sizeof (emlxs_ub_priv_t),
2959 2964 KM_SLEEP);
2960 2965
2961 2966 /*
2962 2967 * Initialize emlxs_ub_priv_t
2963 2968 */
2964 2969 ub_priv = ubp->ub_fca_private;
2965 2970 ub_priv->ubp = ubp;
2966 2971 ub_priv->port = port;
2967 2972 ub_priv->flags = EMLXS_UB_FREE;
2968 2973 ub_priv->available = 1;
2969 2974 ub_priv->pool = new_pool;
2970 2975 ub_priv->time = 0;
2971 2976 ub_priv->timeout = 0;
2972 2977 ub_priv->token = port->ub_count;
2973 2978 ub_priv->cmd = 0;
2974 2979
2975 2980 /* Allocate the actual buffer */
2976 2981 ubp->ub_buffer = (caddr_t)kmem_zalloc(size, KM_SLEEP);
2977 2982
2978 2983
2979 2984 tokens[i] = (uint64_t)((unsigned long)ubp);
2980 2985 port->ub_count++;
2981 2986 }
2982 2987
2983 2988 mutex_enter(&EMLXS_UB_LOCK);
2984 2989
2985 2990 /* Add the pool to the top of the pool list */
2986 2991 new_pool->pool_prev = NULL;
2987 2992 new_pool->pool_next = port->ub_pool;
2988 2993
2989 2994 if (port->ub_pool) {
2990 2995 port->ub_pool->pool_prev = new_pool;
2991 2996 }
2992 2997 port->ub_pool = new_pool;
2993 2998
2994 2999 /* Set the post counts */
2995 3000 if (type == FC_TYPE_IS8802_SNAP) {
2996 3001 MAILBOXQ *mbox;
2997 3002
2998 3003 port->ub_post[hba->channel_ip] += new_pool->pool_nentries;
2999 3004
3000 3005 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
3001 3006 MEM_MBOX))) {
3002 3007 emlxs_mb_config_farp(hba, mbox);
3003 3008 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba,
3004 3009 mbox, MBX_NOWAIT, 0);
3005 3010 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
3006 3011 emlxs_mem_put(hba, MEM_MBOX, (void *)mbox);
3007 3012 }
3008 3013 }
3009 3014 port->flag |= EMLXS_PORT_IP_UP;
3010 3015 } else if (type == FC_TYPE_EXTENDED_LS) {
3011 3016 port->ub_post[hba->channel_els] += new_pool->pool_nentries;
3012 3017 } else if (type == FC_TYPE_FC_SERVICES) {
3013 3018 port->ub_post[hba->channel_ct] += new_pool->pool_nentries;
3014 3019 }
3015 3020
3016 3021 mutex_exit(&EMLXS_UB_LOCK);
3017 3022
3018 3023 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
3019 3024 "%d unsolicited buffers allocated for %s of size 0x%x bytes.",
3020 3025 *count, err, size);
3021 3026
3022 3027 return (FC_SUCCESS);
3023 3028
3024 3029 fail:
3025 3030
3026 3031 /* Clean the pool */
3027 3032 for (i = 0; tokens[i] != NULL; i++) {
3028 3033 /* Get the buffer object */
3029 3034 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
3030 3035 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
3031 3036
3032 3037 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
3033 3038 "fca_ub_alloc failed: Freed buffer=%p token=%x size=%x "
3034 3039 "type=%x ", ubp, ub_priv->token, ubp->ub_bufsize, type);
3035 3040
3036 3041 /* Free the actual buffer */
3037 3042 kmem_free(ubp->ub_buffer, ubp->ub_bufsize);
3038 3043
3039 3044 /* Free the private area of the buffer object */
3040 3045 kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t));
3041 3046
3042 3047 tokens[i] = 0;
3043 3048 port->ub_count--;
3044 3049 }
3045 3050
3046 3051 if (new_pool) {
3047 3052 /* Free the array of buffer objects in the pool */
3048 3053 kmem_free((caddr_t)new_pool->fc_ubufs,
3049 3054 (sizeof (fc_unsol_buf_t) * new_pool->pool_nentries));
3050 3055
3051 3056 /* Free the pool object */
3052 3057 kmem_free((caddr_t)new_pool, sizeof (emlxs_unsol_buf_t));
3053 3058 }
3054 3059
3055 3060 mutex_exit(&EMLXS_UB_LOCK);
3056 3061
3057 3062 return (result);
3058 3063
3059 3064 } /* emlxs_fca_ub_alloc() */
3060 3065
3061 3066
3062 3067 static void
3063 3068 emlxs_ub_els_reject(emlxs_port_t *port, fc_unsol_buf_t *ubp)
3064 3069 {
3065 3070 emlxs_hba_t *hba = HBA;
3066 3071 emlxs_ub_priv_t *ub_priv;
3067 3072 fc_packet_t *pkt;
3068 3073 ELS_PKT *els;
3069 3074 uint32_t sid;
3070 3075
3071 3076 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
3072 3077
3073 3078 if (hba->state <= FC_LINK_DOWN) {
3074 3079 emlxs_abort_els_exchange(hba, port, ubp->ub_frame.rx_id);
3075 3080 return;
3076 3081 }
3077 3082
3078 3083 if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) +
3079 3084 sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) {
3080 3085 emlxs_abort_els_exchange(hba, port, ubp->ub_frame.rx_id);
3081 3086 return;
3082 3087 }
3083 3088
3084 3089 sid = LE_SWAP24_LO(ubp->ub_frame.s_id);
3085 3090
3086 3091 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3087 3092 "%s dropped: sid=%x. Rejecting.",
3088 3093 emlxs_elscmd_xlate(ub_priv->cmd), sid);
3089 3094
3090 3095 pkt->pkt_tran_type = FC_PKT_OUTBOUND;
3091 3096 pkt->pkt_timeout = (2 * hba->fc_ratov);
3092 3097
3093 3098 if ((uint32_t)ubp->ub_class == FC_TRAN_CLASS2) {
3094 3099 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3;
3095 3100 pkt->pkt_tran_flags |= FC_TRAN_CLASS2;
3096 3101 }
3097 3102
3098 3103 /* Build the fc header */
3099 3104 pkt->pkt_cmd_fhdr.d_id = ubp->ub_frame.s_id;
3100 3105 pkt->pkt_cmd_fhdr.r_ctl =
3101 3106 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
3102 3107 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
3103 3108 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3104 3109 pkt->pkt_cmd_fhdr.f_ctl =
3105 3110 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
3106 3111 pkt->pkt_cmd_fhdr.seq_id = 0;
3107 3112 pkt->pkt_cmd_fhdr.df_ctl = 0;
3108 3113 pkt->pkt_cmd_fhdr.seq_cnt = 0;
3109 3114 pkt->pkt_cmd_fhdr.ox_id = (ub_priv->cmd >> ELS_CMD_SHIFT) & 0xff;
3110 3115 pkt->pkt_cmd_fhdr.rx_id = ubp->ub_frame.rx_id;
3111 3116 pkt->pkt_cmd_fhdr.ro = 0;
3112 3117
3113 3118 /* Build the command */
3114 3119 els = (ELS_PKT *) pkt->pkt_cmd;
3115 3120 els->elsCode = 0x01;
3116 3121 els->un.lsRjt.un.b.lsRjtRsvd0 = 0;
3117 3122 els->un.lsRjt.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3118 3123 els->un.lsRjt.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
3119 3124 els->un.lsRjt.un.b.vendorUnique = 0x02;
3120 3125
3121 3126 /* Send the pkt later in another thread */
3122 3127 (void) emlxs_pkt_send(pkt, 0);
3123 3128
3124 3129 return;
3125 3130
3126 3131 } /* emlxs_ub_els_reject() */
3127 3132
3128 3133 extern int
3129 3134 emlxs_fca_ub_release(opaque_t fca_port_handle, uint32_t count,
3130 3135 uint64_t tokens[])
3131 3136 {
3132 3137 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
3133 3138 emlxs_hba_t *hba = HBA;
3134 3139 fc_unsol_buf_t *ubp;
3135 3140 emlxs_ub_priv_t *ub_priv;
3136 3141 uint32_t i;
3137 3142 uint32_t time;
3138 3143 emlxs_unsol_buf_t *pool;
3139 3144
3140 3145 if (count == 0) {
3141 3146 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3142 3147 "fca_ub_release: Nothing to do. count=%d", count);
3143 3148
3144 3149 return (FC_SUCCESS);
3145 3150 }
3146 3151
3147 3152 if (!(port->flag & EMLXS_INI_BOUND)) {
3148 3153 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3149 3154 "fca_ub_release failed: Port not bound. count=%d "
3150 3155 "token[0]=%p",
3151 3156 count, tokens[0]);
3152 3157
3153 3158 return (FC_UNBOUND);
3154 3159 }
3155 3160
3156 3161 mutex_enter(&EMLXS_UB_LOCK);
3157 3162
3158 3163 if (!port->ub_pool) {
3159 3164 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3160 3165 "fca_ub_release failed: No pools! count=%d token[0]=%p",
3161 3166 count, tokens[0]);
3162 3167
3163 3168 mutex_exit(&EMLXS_UB_LOCK);
3164 3169 return (FC_UB_BADTOKEN);
3165 3170 }
3166 3171
3167 3172 for (i = 0; i < count; i++) {
3168 3173 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
3169 3174
3170 3175 if (!ubp) {
3171 3176 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3172 3177 "fca_ub_release failed: count=%d tokens[%d]=0",
3173 3178 count, i);
3174 3179
3175 3180 mutex_exit(&EMLXS_UB_LOCK);
3176 3181 return (FC_UB_BADTOKEN);
3177 3182 }
3178 3183
3179 3184 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
3180 3185
3181 3186 if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) {
3182 3187 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3183 3188 "fca_ub_release failed: Dead buffer found. ubp=%p",
3184 3189 ubp);
3185 3190
3186 3191 mutex_exit(&EMLXS_UB_LOCK);
3187 3192 return (FC_UB_BADTOKEN);
3188 3193 }
3189 3194
3190 3195 if (ub_priv->flags == EMLXS_UB_FREE) {
3191 3196 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3192 3197 "fca_ub_release: Buffer already free! ubp=%p "
3193 3198 "token=%x",
3194 3199 ubp, ub_priv->token);
3195 3200
3196 3201 continue;
3197 3202 }
3198 3203
3199 3204 /* Check for dropped els buffer */
3200 3205 /* ULP will do this sometimes without sending a reply */
3201 3206 if ((ubp->ub_frame.r_ctl == FC_ELS_REQ) &&
3202 3207 !(ub_priv->flags & EMLXS_UB_REPLY)) {
3203 3208 emlxs_ub_els_reject(port, ubp);
3204 3209 }
3205 3210
3206 3211 /* Mark the buffer free */
3207 3212 ub_priv->flags = EMLXS_UB_FREE;
3208 3213 bzero(ubp->ub_buffer, ubp->ub_bufsize);
3209 3214
3210 3215 time = hba->timer_tics - ub_priv->time;
3211 3216 ub_priv->time = 0;
3212 3217 ub_priv->timeout = 0;
3213 3218
3214 3219 pool = ub_priv->pool;
3215 3220
3216 3221 if (ub_priv->flags & EMLXS_UB_RESV) {
3217 3222 pool->pool_free_resv++;
3218 3223 } else {
3219 3224 pool->pool_free++;
3220 3225 }
3221 3226
3222 3227 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
3223 3228 "fca_ub_release: ubp=%p token=%x time=%d av=%d "
3224 3229 "(%d,%d,%d,%d)",
3225 3230 ubp, ub_priv->token, time, ub_priv->available,
3226 3231 pool->pool_nentries, pool->pool_available,
3227 3232 pool->pool_free, pool->pool_free_resv);
3228 3233
3229 3234 /* Check if pool can be destroyed now */
3230 3235 if ((pool->pool_available == 0) &&
3231 3236 (pool->pool_free + pool->pool_free_resv ==
3232 3237 pool->pool_nentries)) {
3233 3238 emlxs_ub_destroy(port, pool);
3234 3239 }
3235 3240 }
3236 3241
3237 3242 mutex_exit(&EMLXS_UB_LOCK);
3238 3243
3239 3244 return (FC_SUCCESS);
3240 3245
3241 3246 } /* emlxs_fca_ub_release() */
3242 3247
3243 3248
3244 3249 static int
3245 3250 emlxs_fca_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[])
3246 3251 {
3247 3252 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
3248 3253 emlxs_unsol_buf_t *pool;
3249 3254 fc_unsol_buf_t *ubp;
3250 3255 emlxs_ub_priv_t *ub_priv;
3251 3256 uint32_t i;
3252 3257
3253 3258 if (!(port->flag & EMLXS_INI_ENABLED)) {
3254 3259 return (FC_SUCCESS);
3255 3260 }
3256 3261
3257 3262 if (count == 0) {
3258 3263 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3259 3264 "fca_ub_free: Nothing to do. count=%d token[0]=%p", count,
3260 3265 tokens[0]);
3261 3266
3262 3267 return (FC_SUCCESS);
3263 3268 }
3264 3269
3265 3270 if (!(port->flag & EMLXS_INI_BOUND)) {
3266 3271 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3267 3272 "fca_ub_free: Port not bound. count=%d token[0]=%p", count,
3268 3273 tokens[0]);
3269 3274
3270 3275 return (FC_SUCCESS);
3271 3276 }
3272 3277
3273 3278 mutex_enter(&EMLXS_UB_LOCK);
3274 3279
3275 3280 if (!port->ub_pool) {
3276 3281 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3277 3282 "fca_ub_free failed: No pools! count=%d token[0]=%p", count,
3278 3283 tokens[0]);
3279 3284
3280 3285 mutex_exit(&EMLXS_UB_LOCK);
3281 3286 return (FC_UB_BADTOKEN);
3282 3287 }
3283 3288
3284 3289 /* Process buffer list */
3285 3290 for (i = 0; i < count; i++) {
3286 3291 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]);
3287 3292
3288 3293 if (!ubp) {
3289 3294 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3290 3295 "fca_ub_free failed: count=%d tokens[%d]=0", count,
3291 3296 i);
3292 3297
3293 3298 mutex_exit(&EMLXS_UB_LOCK);
3294 3299 return (FC_UB_BADTOKEN);
3295 3300 }
3296 3301
3297 3302 /* Mark buffer unavailable */
3298 3303 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
3299 3304
3300 3305 if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) {
3301 3306 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3302 3307 "fca_ub_free failed: Dead buffer found. ubp=%p",
3303 3308 ubp);
3304 3309
3305 3310 mutex_exit(&EMLXS_UB_LOCK);
3306 3311 return (FC_UB_BADTOKEN);
3307 3312 }
3308 3313
3309 3314 ub_priv->available = 0;
3310 3315
3311 3316 /* Mark one less buffer available in the parent pool */
3312 3317 pool = ub_priv->pool;
3313 3318
3314 3319 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
3315 3320 "fca_ub_free: ubp=%p token=%x (%d,%d,%d,%d)", ubp,
3316 3321 ub_priv->token, pool->pool_nentries,
3317 3322 pool->pool_available - 1, pool->pool_free,
3318 3323 pool->pool_free_resv);
3319 3324
3320 3325 if (pool->pool_available) {
3321 3326 pool->pool_available--;
3322 3327
3323 3328 /* Check if pool can be destroyed */
3324 3329 if ((pool->pool_available == 0) &&
3325 3330 (pool->pool_free + pool->pool_free_resv ==
3326 3331 pool->pool_nentries)) {
3327 3332 emlxs_ub_destroy(port, pool);
3328 3333 }
3329 3334 }
3330 3335 }
3331 3336
3332 3337 mutex_exit(&EMLXS_UB_LOCK);
3333 3338
3334 3339 return (FC_SUCCESS);
3335 3340
3336 3341 } /* emlxs_fca_ub_free() */
3337 3342
3338 3343
3339 3344 /* EMLXS_UB_LOCK must be held when calling this routine */
3340 3345 extern void
3341 3346 emlxs_ub_destroy(emlxs_port_t *port, emlxs_unsol_buf_t *pool)
3342 3347 {
3343 3348 emlxs_hba_t *hba = HBA;
3344 3349 emlxs_unsol_buf_t *next;
3345 3350 emlxs_unsol_buf_t *prev;
3346 3351 fc_unsol_buf_t *ubp;
3347 3352 uint32_t i;
3348 3353
3349 3354 /* Remove the pool object from the pool list */
3350 3355 next = pool->pool_next;
3351 3356 prev = pool->pool_prev;
3352 3357
3353 3358 if (port->ub_pool == pool) {
3354 3359 port->ub_pool = next;
3355 3360 }
3356 3361
3357 3362 if (prev) {
3358 3363 prev->pool_next = next;
3359 3364 }
3360 3365
3361 3366 if (next) {
3362 3367 next->pool_prev = prev;
3363 3368 }
3364 3369
3365 3370 pool->pool_prev = NULL;
3366 3371 pool->pool_next = NULL;
3367 3372
3368 3373 /* Clear the post counts */
3369 3374 switch (pool->pool_type) {
3370 3375 case FC_TYPE_IS8802_SNAP:
3371 3376 port->ub_post[hba->channel_ip] -= pool->pool_nentries;
3372 3377 break;
3373 3378
3374 3379 case FC_TYPE_EXTENDED_LS:
3375 3380 port->ub_post[hba->channel_els] -= pool->pool_nentries;
3376 3381 break;
3377 3382
3378 3383 case FC_TYPE_FC_SERVICES:
3379 3384 port->ub_post[hba->channel_ct] -= pool->pool_nentries;
3380 3385 break;
3381 3386 }
3382 3387
3383 3388 /* Now free the pool memory */
3384 3389 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3385 3390 "ub_destroy: pool=%p type=%d size=%d count=%d", pool,
3386 3391 pool->pool_type, pool->pool_buf_size, pool->pool_nentries);
3387 3392
3388 3393 /* Process the array of buffer objects in the pool */
3389 3394 for (i = 0; i < pool->pool_nentries; i++) {
3390 3395 /* Get the buffer object */
3391 3396 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i];
3392 3397
3393 3398 /* Free the memory the buffer object represents */
3394 3399 kmem_free(ubp->ub_buffer, ubp->ub_bufsize);
3395 3400
3396 3401 /* Free the private area of the buffer object */
3397 3402 kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t));
3398 3403 }
3399 3404
3400 3405 /* Free the array of buffer objects in the pool */
3401 3406 kmem_free((caddr_t)pool->fc_ubufs,
3402 3407 (sizeof (fc_unsol_buf_t)*pool->pool_nentries));
3403 3408
3404 3409 /* Free the pool object */
3405 3410 kmem_free((caddr_t)pool, sizeof (emlxs_unsol_buf_t));
3406 3411
3407 3412 return;
3408 3413
3409 3414 } /* emlxs_ub_destroy() */
3410 3415
3411 3416
3412 3417 /*ARGSUSED*/
3413 3418 extern int
3414 3419 emlxs_fca_pkt_abort(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep)
3415 3420 {
3416 3421 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
3417 3422 emlxs_hba_t *hba = HBA;
3418 3423 emlxs_config_t *cfg = &CFG;
3419 3424
3420 3425 emlxs_buf_t *sbp;
3421 3426 NODELIST *nlp;
3422 3427 NODELIST *prev_nlp;
3423 3428 uint8_t channelno;
3424 3429 CHANNEL *cp;
3425 3430 clock_t pkt_timeout;
3426 3431 clock_t timer;
3427 3432 clock_t time;
3428 3433 int32_t pkt_ret;
3429 3434 IOCBQ *iocbq;
3430 3435 IOCBQ *next;
3431 3436 IOCBQ *prev;
3432 3437 uint32_t found;
3433 3438 uint32_t pass = 0;
3434 3439
3435 3440 sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
3436 3441 iocbq = &sbp->iocbq;
3437 3442 nlp = (NODELIST *)sbp->node;
3438 3443 cp = (CHANNEL *)sbp->channel;
3439 3444 channelno = (cp) ? cp->channelno : 0;
3440 3445
3441 3446 if (!(port->flag & EMLXS_INI_BOUND)) {
3442 3447 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3443 3448 "Port not bound.");
3444 3449 return (FC_UNBOUND);
3445 3450 }
3446 3451
3447 3452 if (!(hba->flag & FC_ONLINE_MODE)) {
3448 3453 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3449 3454 "Adapter offline.");
3450 3455 return (FC_OFFLINE);
3451 3456 }
3452 3457
3453 3458 /* ULP requires the aborted pkt to be completed */
3454 3459 /* back to ULP before returning from this call. */
3455 3460 /* SUN knows of problems with this call so they suggested that we */
3456 3461 /* always return a FC_FAILURE for this call, until it is worked out. */
3457 3462
3458 3463 /* Check if pkt is no good */
3459 3464 if (!(sbp->pkt_flags & PACKET_VALID) ||
3460 3465 (sbp->pkt_flags & PACKET_ULP_OWNED)) {
3461 3466 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3462 3467 "Bad sbp. flags=%x", sbp->pkt_flags);
3463 3468 return (FC_FAILURE);
3464 3469 }
3465 3470
3466 3471 /* Tag this now */
3467 3472 /* This will prevent any thread except ours from completing it */
3468 3473 mutex_enter(&sbp->mtx);
3469 3474
3470 3475 /* Check again if we still own this */
3471 3476 if (!(sbp->pkt_flags & PACKET_VALID) ||
3472 3477 (sbp->pkt_flags & PACKET_ULP_OWNED)) {
3473 3478 mutex_exit(&sbp->mtx);
3474 3479 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3475 3480 "Bad sbp. flags=%x", sbp->pkt_flags);
3476 3481 return (FC_FAILURE);
3477 3482 }
3478 3483
3479 3484 /* Check if pkt is a real polled command */
3480 3485 if (!(sbp->pkt_flags & PACKET_IN_ABORT) &&
3481 3486 (sbp->pkt_flags & PACKET_POLLED)) {
3482 3487 mutex_exit(&sbp->mtx);
3483 3488
3484 3489 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3485 3490 "Attempting to abort a polled I/O. sbp=%p flags=%x", sbp,
3486 3491 sbp->pkt_flags);
3487 3492 return (FC_FAILURE);
3488 3493 }
3489 3494
3490 3495 sbp->pkt_flags |= PACKET_POLLED;
3491 3496 sbp->pkt_flags |= PACKET_IN_ABORT;
3492 3497
3493 3498 if (sbp->pkt_flags & (PACKET_IN_COMPLETION | PACKET_IN_FLUSH |
3494 3499 PACKET_IN_TIMEOUT)) {
3495 3500 mutex_exit(&sbp->mtx);
3496 3501
3497 3502 /* Do nothing, pkt already on its way out */
3498 3503 goto done;
3499 3504 }
3500 3505
3501 3506 mutex_exit(&sbp->mtx);
3502 3507
3503 3508 begin:
3504 3509 pass++;
3505 3510
3506 3511 mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
3507 3512
3508 3513 if (sbp->pkt_flags & PACKET_IN_TXQ) {
3509 3514 /* Find it on the queue */
3510 3515 found = 0;
3511 3516 if (iocbq->flag & IOCB_PRIORITY) {
3512 3517 /* Search the priority queue */
3513 3518 prev = NULL;
3514 3519 next = (IOCBQ *) nlp->nlp_ptx[channelno].q_first;
3515 3520
3516 3521 while (next) {
3517 3522 if (next == iocbq) {
3518 3523 /* Remove it */
3519 3524 if (prev) {
3520 3525 prev->next = iocbq->next;
3521 3526 }
3522 3527
3523 3528 if (nlp->nlp_ptx[channelno].q_last ==
3524 3529 (void *)iocbq) {
3525 3530 nlp->nlp_ptx[channelno].q_last =
3526 3531 (void *)prev;
3527 3532 }
3528 3533
3529 3534 if (nlp->nlp_ptx[channelno].q_first ==
3530 3535 (void *)iocbq) {
3531 3536 nlp->nlp_ptx[channelno].
3532 3537 q_first =
3533 3538 (void *)iocbq->next;
3534 3539 }
3535 3540
3536 3541 nlp->nlp_ptx[channelno].q_cnt--;
3537 3542 iocbq->next = NULL;
3538 3543 found = 1;
3539 3544 break;
3540 3545 }
3541 3546
3542 3547 prev = next;
3543 3548 next = next->next;
3544 3549 }
3545 3550 } else {
3546 3551 /* Search the normal queue */
3547 3552 prev = NULL;
3548 3553 next = (IOCBQ *) nlp->nlp_tx[channelno].q_first;
3549 3554
3550 3555 while (next) {
3551 3556 if (next == iocbq) {
3552 3557 /* Remove it */
3553 3558 if (prev) {
3554 3559 prev->next = iocbq->next;
3555 3560 }
3556 3561
3557 3562 if (nlp->nlp_tx[channelno].q_last ==
3558 3563 (void *)iocbq) {
3559 3564 nlp->nlp_tx[channelno].q_last =
3560 3565 (void *)prev;
3561 3566 }
3562 3567
3563 3568 if (nlp->nlp_tx[channelno].q_first ==
3564 3569 (void *)iocbq) {
3565 3570 nlp->nlp_tx[channelno].q_first =
3566 3571 (void *)iocbq->next;
3567 3572 }
3568 3573
3569 3574 nlp->nlp_tx[channelno].q_cnt--;
3570 3575 iocbq->next = NULL;
3571 3576 found = 1;
3572 3577 break;
3573 3578 }
3574 3579
3575 3580 prev = next;
3576 3581 next = (IOCBQ *) next->next;
3577 3582 }
3578 3583 }
3579 3584
3580 3585 if (!found) {
3581 3586 mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
3582 3587 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg,
3583 3588 "I/O not found in driver. sbp=%p flags=%x", sbp,
3584 3589 sbp->pkt_flags);
3585 3590 goto done;
3586 3591 }
3587 3592
3588 3593 /* Check if node still needs servicing */
3589 3594 if ((nlp->nlp_ptx[channelno].q_first) ||
3590 3595 (nlp->nlp_tx[channelno].q_first &&
3591 3596 !(nlp->nlp_flag[channelno] & NLP_CLOSED))) {
3592 3597
3593 3598 /*
3594 3599 * If this is the base node,
3595 3600 * then don't shift the pointers
3596 3601 */
3597 3602 /* We want to drain the base node before moving on */
3598 3603 if (!nlp->nlp_base) {
3599 3604 /* Just shift channel queue */
3600 3605 /* pointers to next node */
3601 3606 cp->nodeq.q_last = (void *) nlp;
3602 3607 cp->nodeq.q_first = nlp->nlp_next[channelno];
3603 3608 }
3604 3609 } else {
3605 3610 /* Remove node from channel queue */
3606 3611
3607 3612 /* If this is the only node on list */
3608 3613 if (cp->nodeq.q_first == (void *)nlp &&
3609 3614 cp->nodeq.q_last == (void *)nlp) {
3610 3615 cp->nodeq.q_last = NULL;
3611 3616 cp->nodeq.q_first = NULL;
3612 3617 cp->nodeq.q_cnt = 0;
3613 3618 } else if (cp->nodeq.q_first == (void *)nlp) {
3614 3619 cp->nodeq.q_first = nlp->nlp_next[channelno];
3615 3620 ((NODELIST *) cp->nodeq.q_last)->
3616 3621 nlp_next[channelno] = cp->nodeq.q_first;
3617 3622 cp->nodeq.q_cnt--;
3618 3623 } else {
3619 3624 /*
3620 3625 * This is a little more difficult find the
3621 3626 * previous node in the circular channel queue
3622 3627 */
3623 3628 prev_nlp = nlp;
3624 3629 while (prev_nlp->nlp_next[channelno] != nlp) {
3625 3630 prev_nlp = prev_nlp->
3626 3631 nlp_next[channelno];
3627 3632 }
3628 3633
3629 3634 prev_nlp->nlp_next[channelno] =
3630 3635 nlp->nlp_next[channelno];
3631 3636
3632 3637 if (cp->nodeq.q_last == (void *)nlp) {
3633 3638 cp->nodeq.q_last = (void *)prev_nlp;
3634 3639 }
3635 3640 cp->nodeq.q_cnt--;
3636 3641
3637 3642 }
3638 3643
3639 3644 /* Clear node */
3640 3645 nlp->nlp_next[channelno] = NULL;
3641 3646 }
3642 3647
3643 3648 /* Free the ULPIOTAG and the bmp */
3644 3649 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3645 3650 emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1);
3646 3651 } else {
3647 3652 (void) emlxs_unregister_pkt(cp, sbp->iotag, 1);
3648 3653 }
3649 3654
3650 3655
3651 3656 mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
3652 3657
3653 3658 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
3654 3659 IOERR_ABORT_REQUESTED, 1);
3655 3660
3656 3661 goto done;
3657 3662 }
3658 3663
3659 3664 mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
3660 3665
3661 3666
3662 3667 /* Check the chip queue */
3663 3668 mutex_enter(&EMLXS_FCTAB_LOCK);
3664 3669
3665 3670 if ((sbp->pkt_flags & PACKET_IN_CHIPQ) &&
3666 3671 !(sbp->pkt_flags & PACKET_XRI_CLOSED) &&
3667 3672 (sbp == hba->fc_table[sbp->iotag])) {
3668 3673
3669 3674 /* Create the abort IOCB */
3670 3675 if (hba->state >= FC_LINK_UP) {
3671 3676 iocbq =
3672 3677 emlxs_create_abort_xri_cn(port, sbp->node,
3673 3678 sbp->iotag, cp, sbp->class, ABORT_TYPE_ABTS);
3674 3679
3675 3680 mutex_enter(&sbp->mtx);
3676 3681 sbp->pkt_flags |= PACKET_XRI_CLOSED;
3677 3682 sbp->ticks =
3678 3683 hba->timer_tics + (4 * hba->fc_ratov) + 10;
3679 3684 sbp->abort_attempts++;
3680 3685 mutex_exit(&sbp->mtx);
3681 3686 } else {
3682 3687 iocbq =
3683 3688 emlxs_create_close_xri_cn(port, sbp->node,
3684 3689 sbp->iotag, cp);
3685 3690
3686 3691 mutex_enter(&sbp->mtx);
3687 3692 sbp->pkt_flags |= PACKET_XRI_CLOSED;
3688 3693 sbp->ticks = hba->timer_tics + 30;
3689 3694 sbp->abort_attempts++;
3690 3695 mutex_exit(&sbp->mtx);
3691 3696 }
3692 3697
3693 3698 mutex_exit(&EMLXS_FCTAB_LOCK);
3694 3699
3695 3700 /* Send this iocbq */
3696 3701 if (iocbq) {
3697 3702 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
3698 3703 iocbq = NULL;
3699 3704 }
3700 3705
3701 3706 goto done;
3702 3707 }
3703 3708
3704 3709 mutex_exit(&EMLXS_FCTAB_LOCK);
3705 3710
3706 3711 /* Pkt was not on any queues */
3707 3712
3708 3713 /* Check again if we still own this */
3709 3714 if (!(sbp->pkt_flags & PACKET_VALID) ||
3710 3715 (sbp->pkt_flags &
3711 3716 (PACKET_ULP_OWNED | PACKET_IN_COMPLETION |
3712 3717 PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
3713 3718 goto done;
3714 3719 }
3715 3720
3716 3721 if (!sleep) {
3717 3722 return (FC_FAILURE);
3718 3723 }
3719 3724
3720 3725 /* Apparently the pkt was not found. Let's delay and try again */
3721 3726 if (pass < 5) {
3722 3727 delay(drv_usectohz(5000000)); /* 5 seconds */
3723 3728
3724 3729 /* Check again if we still own this */
3725 3730 if (!(sbp->pkt_flags & PACKET_VALID) ||
3726 3731 (sbp->pkt_flags &
3727 3732 (PACKET_ULP_OWNED | PACKET_IN_COMPLETION |
3728 3733 PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
3729 3734 goto done;
3730 3735 }
3731 3736
3732 3737 goto begin;
3733 3738 }
3734 3739
3735 3740 force_it:
3736 3741
3737 3742 /* Force the completion now */
3738 3743 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3739 3744 "Abort: Completing an IO thats not outstanding: %x", sbp->iotag);
3740 3745
3741 3746 /* Now complete it */
3742 3747 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_ABORT_REQUESTED,
3743 3748 1);
3744 3749
3745 3750 done:
3746 3751
3747 3752 /* Now wait for the pkt to complete */
3748 3753 if (!(sbp->pkt_flags & PACKET_COMPLETED)) {
3749 3754 /* Set thread timeout */
3750 3755 pkt_timeout = emlxs_timeout(hba, 30);
3751 3756
3752 3757 /* Check for panic situation */
3753 3758 if (ddi_in_panic()) {
3754 3759
3755 3760 /*
3756 3761 * In panic situations there will be one thread with no
3757 3762 * interrrupts (hard or soft) and no timers
3758 3763 */
3759 3764
3760 3765 /*
3761 3766 * We must manually poll everything in this thread
3762 3767 * to keep the driver going.
3763 3768 */
3764 3769
3765 3770 /* Keep polling the chip until our IO is completed */
3766 3771 (void) drv_getparm(LBOLT, &time);
3767 3772 timer = time + drv_usectohz(1000000);
3768 3773 while ((time < pkt_timeout) &&
3769 3774 !(sbp->pkt_flags & PACKET_COMPLETED)) {
3770 3775 EMLXS_SLI_POLL_INTR(hba);
3771 3776 (void) drv_getparm(LBOLT, &time);
3772 3777
3773 3778 /* Trigger timer checks periodically */
3774 3779 if (time >= timer) {
3775 3780 emlxs_timer_checks(hba);
3776 3781 timer = time + drv_usectohz(1000000);
3777 3782 }
3778 3783 }
3779 3784 } else {
3780 3785 /* Wait for IO completion or pkt_timeout */
3781 3786 mutex_enter(&EMLXS_PKT_LOCK);
3782 3787 pkt_ret = 0;
3783 3788 while ((pkt_ret != -1) &&
3784 3789 !(sbp->pkt_flags & PACKET_COMPLETED)) {
3785 3790 pkt_ret =
3786 3791 cv_timedwait(&EMLXS_PKT_CV,
3787 3792 &EMLXS_PKT_LOCK, pkt_timeout);
3788 3793 }
3789 3794 mutex_exit(&EMLXS_PKT_LOCK);
3790 3795 }
3791 3796
3792 3797 /* Check if pkt_timeout occured. This is not good. */
3793 3798 /* Something happened to our IO. */
3794 3799 if (!(sbp->pkt_flags & PACKET_COMPLETED)) {
3795 3800 /* Force the completion now */
3796 3801 goto force_it;
3797 3802 }
3798 3803 }
3799 3804 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
3800 3805 emlxs_unswap_pkt(sbp);
3801 3806 #endif /* EMLXS_MODREV2X */
3802 3807
3803 3808 /* Check again if we still own this */
3804 3809 if ((sbp->pkt_flags & PACKET_VALID) &&
3805 3810 !(sbp->pkt_flags & PACKET_ULP_OWNED)) {
3806 3811 mutex_enter(&sbp->mtx);
3807 3812 if ((sbp->pkt_flags & PACKET_VALID) &&
3808 3813 !(sbp->pkt_flags & PACKET_ULP_OWNED)) {
3809 3814 sbp->pkt_flags |= PACKET_ULP_OWNED;
3810 3815 }
3811 3816 mutex_exit(&sbp->mtx);
3812 3817 }
3813 3818
3814 3819 #ifdef ULP_PATCH5
3815 3820 if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH5) {
3816 3821 return (FC_FAILURE);
3817 3822 }
3818 3823 #endif /* ULP_PATCH5 */
3819 3824
3820 3825 return (FC_SUCCESS);
3821 3826
3822 3827 } /* emlxs_fca_pkt_abort() */
3823 3828
3824 3829
3825 3830 static void
3826 3831 emlxs_abort_all(emlxs_hba_t *hba, uint32_t *tx, uint32_t *chip)
3827 3832 {
3828 3833 emlxs_port_t *port = &PPORT;
3829 3834 fc_packet_t *pkt;
3830 3835 emlxs_buf_t *sbp;
3831 3836 uint32_t i;
3832 3837 uint32_t flg;
3833 3838 uint32_t rc;
3834 3839 uint32_t txcnt;
3835 3840 uint32_t chipcnt;
3836 3841
3837 3842 txcnt = 0;
3838 3843 chipcnt = 0;
3839 3844
3840 3845 mutex_enter(&EMLXS_FCTAB_LOCK);
3841 3846 for (i = 0; i < hba->max_iotag; i++) {
3842 3847 sbp = hba->fc_table[i];
3843 3848 if (sbp == NULL || sbp == STALE_PACKET) {
3844 3849 continue;
3845 3850 }
3846 3851 flg = (sbp->pkt_flags & PACKET_IN_CHIPQ);
3847 3852 pkt = PRIV2PKT(sbp);
3848 3853 mutex_exit(&EMLXS_FCTAB_LOCK);
3849 3854 rc = emlxs_fca_pkt_abort(port, pkt, 0);
3850 3855 if (rc == FC_SUCCESS) {
3851 3856 if (flg) {
3852 3857 chipcnt++;
3853 3858 } else {
3854 3859 txcnt++;
3855 3860 }
3856 3861 }
3857 3862 mutex_enter(&EMLXS_FCTAB_LOCK);
3858 3863 }
3859 3864 mutex_exit(&EMLXS_FCTAB_LOCK);
3860 3865 *tx = txcnt;
3861 3866 *chip = chipcnt;
3862 3867 } /* emlxs_abort_all() */
3863 3868
3864 3869
3865 3870 extern int32_t
3866 3871 emlxs_reset(emlxs_port_t *port, uint32_t cmd)
3867 3872 {
3868 3873 emlxs_hba_t *hba = HBA;
3869 3874 int rval;
3870 3875 int i = 0;
3871 3876 int ret;
3872 3877 clock_t timeout;
3873 3878
3874 3879 switch (cmd) {
3875 3880 case FC_FCA_LINK_RESET:
3876 3881
3877 3882 mutex_enter(&EMLXS_PORT_LOCK);
3878 3883 if (!(hba->flag & FC_ONLINE_MODE) ||
3879 3884 (hba->state <= FC_LINK_DOWN)) {
3880 3885 mutex_exit(&EMLXS_PORT_LOCK);
3881 3886 return (FC_SUCCESS);
3882 3887 }
3883 3888
3884 3889 if (hba->reset_state &
3885 3890 (FC_LINK_RESET_INP | FC_PORT_RESET_INP)) {
3886 3891 mutex_exit(&EMLXS_PORT_LOCK);
3887 3892 return (FC_FAILURE);
3888 3893 }
3889 3894
3890 3895 hba->reset_state |= FC_LINK_RESET_INP;
3891 3896 hba->reset_request |= FC_LINK_RESET;
3892 3897 mutex_exit(&EMLXS_PORT_LOCK);
3893 3898
3894 3899 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3895 3900 "Resetting Link.");
3896 3901
3897 3902 mutex_enter(&EMLXS_LINKUP_LOCK);
3898 3903 hba->linkup_wait_flag = TRUE;
3899 3904 mutex_exit(&EMLXS_LINKUP_LOCK);
3900 3905
3901 3906 if (emlxs_reset_link(hba, 1, 1)) {
3902 3907 mutex_enter(&EMLXS_LINKUP_LOCK);
3903 3908 hba->linkup_wait_flag = FALSE;
3904 3909 mutex_exit(&EMLXS_LINKUP_LOCK);
3905 3910
3906 3911 mutex_enter(&EMLXS_PORT_LOCK);
3907 3912 hba->reset_state &= ~FC_LINK_RESET_INP;
3908 3913 hba->reset_request &= ~FC_LINK_RESET;
3909 3914 mutex_exit(&EMLXS_PORT_LOCK);
3910 3915
3911 3916 return (FC_FAILURE);
3912 3917 }
3913 3918
3914 3919 mutex_enter(&EMLXS_LINKUP_LOCK);
3915 3920 timeout = emlxs_timeout(hba, 60);
3916 3921 ret = 0;
3917 3922 while ((ret != -1) && (hba->linkup_wait_flag == TRUE)) {
3918 3923 ret =
3919 3924 cv_timedwait(&EMLXS_LINKUP_CV, &EMLXS_LINKUP_LOCK,
3920 3925 timeout);
3921 3926 }
3922 3927
3923 3928 hba->linkup_wait_flag = FALSE;
3924 3929 mutex_exit(&EMLXS_LINKUP_LOCK);
3925 3930
3926 3931 mutex_enter(&EMLXS_PORT_LOCK);
3927 3932 hba->reset_state &= ~FC_LINK_RESET_INP;
3928 3933 hba->reset_request &= ~FC_LINK_RESET;
3929 3934 mutex_exit(&EMLXS_PORT_LOCK);
3930 3935
3931 3936 if (ret == -1) {
3932 3937 return (FC_FAILURE);
3933 3938 }
3934 3939
3935 3940 return (FC_SUCCESS);
3936 3941
3937 3942 case FC_FCA_CORE:
3938 3943 #ifdef DUMP_SUPPORT
3939 3944 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3940 3945 "Dumping Core.");
3941 3946
3942 3947 /* Schedule a USER dump */
3943 3948 emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0);
3944 3949
3945 3950 /* Wait for dump to complete */
3946 3951 emlxs_dump_wait(hba);
3947 3952
3948 3953 return (FC_SUCCESS);
3949 3954 #endif /* DUMP_SUPPORT */
3950 3955
3951 3956 case FC_FCA_RESET:
3952 3957 case FC_FCA_RESET_CORE:
3953 3958
3954 3959 mutex_enter(&EMLXS_PORT_LOCK);
3955 3960 if (hba->reset_state & FC_PORT_RESET_INP) {
3956 3961 mutex_exit(&EMLXS_PORT_LOCK);
3957 3962 return (FC_FAILURE);
3958 3963 }
3959 3964
3960 3965 hba->reset_state |= FC_PORT_RESET_INP;
3961 3966 hba->reset_request |= (FC_PORT_RESET | FC_LINK_RESET);
3962 3967
3963 3968 /* wait for any pending link resets to complete */
3964 3969 while ((hba->reset_state & FC_LINK_RESET_INP) &&
3965 3970 (i++ < 1000)) {
3966 3971 mutex_exit(&EMLXS_PORT_LOCK);
3967 3972 delay(drv_usectohz(1000));
3968 3973 mutex_enter(&EMLXS_PORT_LOCK);
3969 3974 }
3970 3975
3971 3976 if (hba->reset_state & FC_LINK_RESET_INP) {
3972 3977 hba->reset_state &= ~FC_PORT_RESET_INP;
3973 3978 hba->reset_request &= ~(FC_PORT_RESET | FC_LINK_RESET);
3974 3979 mutex_exit(&EMLXS_PORT_LOCK);
3975 3980 return (FC_FAILURE);
3976 3981 }
3977 3982 mutex_exit(&EMLXS_PORT_LOCK);
3978 3983
3979 3984 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3980 3985 "Resetting Adapter.");
3981 3986
3982 3987 rval = FC_SUCCESS;
3983 3988
3984 3989 if (emlxs_offline(hba, 0) == 0) {
3985 3990 (void) emlxs_online(hba);
3986 3991 } else {
3987 3992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3988 3993 "Adapter reset failed. Device busy.");
3989 3994
3990 3995 rval = FC_DEVICE_BUSY;
3991 3996 }
3992 3997
3993 3998 mutex_enter(&EMLXS_PORT_LOCK);
3994 3999 hba->reset_state &= ~FC_PORT_RESET_INP;
3995 4000 hba->reset_request &= ~(FC_PORT_RESET | FC_LINK_RESET);
3996 4001 mutex_exit(&EMLXS_PORT_LOCK);
3997 4002
3998 4003 return (rval);
3999 4004
4000 4005 case EMLXS_DFC_RESET_ALL:
4001 4006 case EMLXS_DFC_RESET_ALL_FORCE_DUMP:
4002 4007
4003 4008 mutex_enter(&EMLXS_PORT_LOCK);
4004 4009 if (hba->reset_state & FC_PORT_RESET_INP) {
4005 4010 mutex_exit(&EMLXS_PORT_LOCK);
4006 4011 return (FC_FAILURE);
4007 4012 }
4008 4013
4009 4014 hba->reset_state |= FC_PORT_RESET_INP;
4010 4015 hba->reset_request |= (FC_PORT_RESET | FC_LINK_RESET);
4011 4016
4012 4017 /* wait for any pending link resets to complete */
4013 4018 while ((hba->reset_state & FC_LINK_RESET_INP) &&
4014 4019 (i++ < 1000)) {
4015 4020 mutex_exit(&EMLXS_PORT_LOCK);
4016 4021 delay(drv_usectohz(1000));
4017 4022 mutex_enter(&EMLXS_PORT_LOCK);
4018 4023 }
4019 4024
4020 4025 if (hba->reset_state & FC_LINK_RESET_INP) {
4021 4026 hba->reset_state &= ~FC_PORT_RESET_INP;
4022 4027 hba->reset_request &= ~(FC_PORT_RESET | FC_LINK_RESET);
4023 4028 mutex_exit(&EMLXS_PORT_LOCK);
4024 4029 return (FC_FAILURE);
4025 4030 }
4026 4031 mutex_exit(&EMLXS_PORT_LOCK);
4027 4032
4028 4033 rval = FC_SUCCESS;
4029 4034
4030 4035 if (cmd == EMLXS_DFC_RESET_ALL) {
4031 4036 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4032 4037 "Resetting Adapter (All Firmware Reset).");
4033 4038
4034 4039 emlxs_sli4_hba_reset_all(hba, 0);
4035 4040 } else {
4036 4041 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4037 4042 "Resetting Adapter "
4038 4043 "(All Firmware Reset, Force Dump).");
4039 4044
4040 4045 emlxs_sli4_hba_reset_all(hba, 1);
4041 4046 }
4042 4047
4043 4048 mutex_enter(&EMLXS_PORT_LOCK);
4044 4049 hba->reset_state &= ~FC_PORT_RESET_INP;
4045 4050 hba->reset_request &= ~(FC_PORT_RESET | FC_LINK_RESET);
4046 4051 mutex_exit(&EMLXS_PORT_LOCK);
4047 4052
4048 4053 /* Wait for the timer thread to detect the error condition */
4049 4054 delay(drv_usectohz(1000000));
4050 4055
4051 4056 /* Wait for the HBA to re-initialize */
4052 4057 i = 0;
4053 4058 mutex_enter(&EMLXS_PORT_LOCK);
4054 4059 while (!(hba->flag & FC_ONLINE_MODE) && (i++ < 30)) {
4055 4060 mutex_exit(&EMLXS_PORT_LOCK);
4056 4061 delay(drv_usectohz(1000000));
4057 4062 mutex_enter(&EMLXS_PORT_LOCK);
4058 4063 }
4059 4064
4060 4065 if (!(hba->flag & FC_ONLINE_MODE)) {
4061 4066 rval = FC_FAILURE;
4062 4067 }
4063 4068
4064 4069 mutex_exit(&EMLXS_PORT_LOCK);
4065 4070
4066 4071 return (rval);
4067 4072
4068 4073 default:
4069 4074 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4070 4075 "reset: Unknown command. cmd=%x", cmd);
4071 4076
4072 4077 break;
4073 4078 }
4074 4079
4075 4080 return (FC_FAILURE);
4076 4081
4077 4082 } /* emlxs_reset() */
4078 4083
4079 4084
4080 4085 extern int32_t
4081 4086 emlxs_fca_reset(opaque_t fca_port_handle, uint32_t cmd)
4082 4087 {
4083 4088 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
4084 4089 emlxs_hba_t *hba = HBA;
4085 4090 int32_t rval;
4086 4091
4087 4092 if (port->mode != MODE_INITIATOR) {
4088 4093 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4089 4094 "fca_reset failed. Port is not in initiator mode.");
4090 4095
4091 4096 return (FC_FAILURE);
4092 4097 }
4093 4098
4094 4099 if (!(port->flag & EMLXS_INI_BOUND)) {
4095 4100 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4096 4101 "fca_reset: Port not bound.");
4097 4102
4098 4103 return (FC_UNBOUND);
4099 4104 }
4100 4105
4101 4106 switch (cmd) {
4102 4107 case FC_FCA_LINK_RESET:
4103 4108 if (hba->fw_flag & FW_UPDATE_NEEDED) {
4104 4109 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4105 4110 "fca_reset: FC_FCA_LINK_RESET -> FC_FCA_RESET");
4106 4111 cmd = FC_FCA_RESET;
4107 4112 } else {
4108 4113 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4109 4114 "fca_reset: FC_FCA_LINK_RESET");
4110 4115 }
4111 4116 break;
4112 4117
4113 4118 case FC_FCA_CORE:
4114 4119 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4115 4120 "fca_reset: FC_FCA_CORE");
4116 4121 break;
4117 4122
4118 4123 case FC_FCA_RESET:
4119 4124 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4120 4125 "fca_reset: FC_FCA_RESET");
4121 4126 break;
4122 4127
4123 4128 case FC_FCA_RESET_CORE:
4124 4129 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4125 4130 "fca_reset: FC_FCA_RESET_CORE");
4126 4131 break;
4127 4132
4128 4133 default:
4129 4134 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4130 4135 "fca_reset: Unknown command. cmd=%x", cmd);
4131 4136 return (FC_FAILURE);
4132 4137 }
4133 4138
4134 4139 if (hba->fw_flag & FW_UPDATE_NEEDED) {
4135 4140 hba->fw_flag |= FW_UPDATE_KERNEL;
4136 4141 }
4137 4142
4138 4143 rval = emlxs_reset(port, cmd);
4139 4144
4140 4145 return (rval);
4141 4146
4142 4147 } /* emlxs_fca_reset() */
4143 4148
4144 4149
4145 4150 extern int
4146 4151 emlxs_fca_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm)
4147 4152 {
4148 4153 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle;
4149 4154 emlxs_hba_t *hba = HBA;
4150 4155 int32_t ret;
4151 4156 emlxs_vpd_t *vpd = &VPD;
4152 4157
4153 4158 ret = FC_SUCCESS;
4154 4159
4155 4160 #ifdef IDLE_TIMER
4156 4161 emlxs_pm_busy_component(hba);
4157 4162 #endif /* IDLE_TIMER */
4158 4163
4159 4164 switch (pm->pm_cmd_code) {
4160 4165
4161 4166 case FC_PORT_GET_FW_REV:
4162 4167 {
4163 4168 char buffer[128];
4164 4169
4165 4170 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4166 4171 "fca_port_manage: FC_PORT_GET_FW_REV");
4167 4172
4168 4173 (void) snprintf(buffer, (sizeof (buffer)-1),
4169 4174 "%s %s", hba->model_info.model,
4170 4175 vpd->fw_version);
4171 4176 bzero(pm->pm_data_buf, pm->pm_data_len);
4172 4177
4173 4178 if (pm->pm_data_len < strlen(buffer) + 1) {
4174 4179 ret = FC_NOMEM;
4175 4180
4176 4181 break;
4177 4182 }
4178 4183
4179 4184 (void) strncpy(pm->pm_data_buf, buffer,
4180 4185 (pm->pm_data_len-1));
4181 4186 break;
4182 4187 }
4183 4188
4184 4189 case FC_PORT_GET_FCODE_REV:
4185 4190 {
4186 4191 char buffer[128];
4187 4192
4188 4193 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4189 4194 "fca_port_manage: FC_PORT_GET_FCODE_REV");
4190 4195
4191 4196 /* Force update here just to be sure */
4192 4197 emlxs_get_fcode_version(hba);
4193 4198
4194 4199 (void) snprintf(buffer, (sizeof (buffer)-1),
4195 4200 "%s %s", hba->model_info.model,
4196 4201 vpd->fcode_version);
4197 4202 bzero(pm->pm_data_buf, pm->pm_data_len);
4198 4203
4199 4204 if (pm->pm_data_len < strlen(buffer) + 1) {
4200 4205 ret = FC_NOMEM;
4201 4206 break;
4202 4207 }
4203 4208
4204 4209 (void) strncpy(pm->pm_data_buf, buffer,
4205 4210 (pm->pm_data_len-1));
4206 4211 break;
4207 4212 }
4208 4213
4209 4214 case FC_PORT_GET_DUMP_SIZE:
4210 4215 {
4211 4216 #ifdef DUMP_SUPPORT
4212 4217 uint32_t dump_size = 0;
4213 4218
4214 4219 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4215 4220 "fca_port_manage: FC_PORT_GET_DUMP_SIZE");
4216 4221
4217 4222 if (pm->pm_data_len < sizeof (uint32_t)) {
4218 4223 ret = FC_NOMEM;
4219 4224 break;
4220 4225 }
4221 4226
4222 4227 (void) emlxs_get_dump(hba, NULL, &dump_size);
4223 4228
4224 4229 *((uint32_t *)pm->pm_data_buf) = dump_size;
4225 4230
4226 4231 #else
4227 4232 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4228 4233 "fca_port_manage: FC_PORT_GET_DUMP_SIZE unsupported.");
4229 4234
4230 4235 #endif /* DUMP_SUPPORT */
4231 4236
4232 4237 break;
4233 4238 }
4234 4239
4235 4240 case FC_PORT_GET_DUMP:
4236 4241 {
4237 4242 #ifdef DUMP_SUPPORT
4238 4243 uint32_t dump_size = 0;
4239 4244
4240 4245 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4241 4246 "fca_port_manage: FC_PORT_GET_DUMP");
4242 4247
4243 4248 (void) emlxs_get_dump(hba, NULL, &dump_size);
4244 4249
4245 4250 if (pm->pm_data_len < dump_size) {
4246 4251 ret = FC_NOMEM;
4247 4252 break;
4248 4253 }
4249 4254
4250 4255 (void) emlxs_get_dump(hba, (uint8_t *)pm->pm_data_buf,
4251 4256 (uint32_t *)&dump_size);
4252 4257 #else
4253 4258 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4254 4259 "fca_port_manage: FC_PORT_GET_DUMP unsupported.");
4255 4260
4256 4261 #endif /* DUMP_SUPPORT */
4257 4262
4258 4263 break;
4259 4264 }
4260 4265
4261 4266 case FC_PORT_FORCE_DUMP:
4262 4267 {
4263 4268 #ifdef DUMP_SUPPORT
4264 4269 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4265 4270 "fca_port_manage: FC_PORT_FORCE_DUMP");
4266 4271
4267 4272 /* Schedule a USER dump */
4268 4273 emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0);
4269 4274
4270 4275 /* Wait for dump to complete */
4271 4276 emlxs_dump_wait(hba);
4272 4277 #else
4273 4278 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4274 4279 "fca_port_manage: FC_PORT_FORCE_DUMP unsupported.");
4275 4280
4276 4281 #endif /* DUMP_SUPPORT */
4277 4282 break;
4278 4283 }
4279 4284
4280 4285 case FC_PORT_LINK_STATE:
4281 4286 {
4282 4287 uint32_t *link_state;
4283 4288
4284 4289 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4285 4290 "fca_port_manage: FC_PORT_LINK_STATE");
4286 4291
4287 4292 if (pm->pm_stat_len != sizeof (*link_state)) {
4288 4293 ret = FC_NOMEM;
4289 4294 break;
4290 4295 }
4291 4296
4292 4297 if (pm->pm_cmd_buf != NULL) {
4293 4298 /*
4294 4299 * Can't look beyond the FCA port.
4295 4300 */
4296 4301 ret = FC_INVALID_REQUEST;
4297 4302 break;
4298 4303 }
4299 4304
4300 4305 link_state = (uint32_t *)pm->pm_stat_buf;
4301 4306
4302 4307 /* Set the state */
4303 4308 if (hba->state >= FC_LINK_UP) {
4304 4309 /* Check for loop topology */
4305 4310 if (hba->topology == TOPOLOGY_LOOP) {
4306 4311 *link_state = FC_STATE_LOOP;
4307 4312 } else {
4308 4313 *link_state = FC_STATE_ONLINE;
4309 4314 }
4310 4315
4311 4316 /* Set the link speed */
4312 4317 switch (hba->linkspeed) {
4313 4318 case LA_2GHZ_LINK:
4314 4319 *link_state |= FC_STATE_2GBIT_SPEED;
4315 4320 break;
4316 4321 case LA_4GHZ_LINK:
4317 4322 *link_state |= FC_STATE_4GBIT_SPEED;
|
↓ open down ↓ |
2540 lines elided |
↑ open up ↑ |
4318 4323 break;
4319 4324 case LA_8GHZ_LINK:
4320 4325 *link_state |= FC_STATE_8GBIT_SPEED;
4321 4326 break;
4322 4327 case LA_10GHZ_LINK:
4323 4328 *link_state |= FC_STATE_10GBIT_SPEED;
4324 4329 break;
4325 4330 case LA_16GHZ_LINK:
4326 4331 *link_state |= FC_STATE_16GBIT_SPEED;
4327 4332 break;
4333 + case LA_32GHZ_LINK:
4334 + *link_state |= FC_STATE_32GBIT_SPEED;
4335 + break;
4328 4336 case LA_1GHZ_LINK:
4329 4337 default:
4330 4338 *link_state |= FC_STATE_1GBIT_SPEED;
4331 4339 break;
4332 4340 }
4333 4341 } else {
4334 4342 *link_state = FC_STATE_OFFLINE;
4335 4343 }
4336 4344
4337 4345 break;
4338 4346 }
4339 4347
4340 4348
4341 4349 case FC_PORT_ERR_STATS:
4342 4350 case FC_PORT_RLS:
4343 4351 {
4344 4352 MAILBOXQ *mbq;
4345 4353 MAILBOX *mb;
4346 4354 fc_rls_acc_t *bp;
4347 4355
4348 4356 if (!(hba->flag & FC_ONLINE_MODE)) {
4349 4357 return (FC_OFFLINE);
4350 4358 }
4351 4359 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4352 4360 "fca_port_manage: FC_PORT_RLS / FC_PORT_ERR_STATS");
4353 4361
4354 4362 if (pm->pm_data_len < sizeof (fc_rls_acc_t)) {
4355 4363 ret = FC_NOMEM;
4356 4364 break;
4357 4365 }
4358 4366
4359 4367 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba,
4360 4368 MEM_MBOX)) == 0) {
4361 4369 ret = FC_NOMEM;
4362 4370 break;
4363 4371 }
4364 4372 mb = (MAILBOX *)mbq;
4365 4373
4366 4374 emlxs_mb_read_lnk_stat(hba, mbq);
4367 4375 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
4368 4376 != MBX_SUCCESS) {
4369 4377 ret = FC_PBUSY;
4370 4378 } else {
4371 4379 bp = (fc_rls_acc_t *)pm->pm_data_buf;
4372 4380
4373 4381 bp->rls_link_fail = mb->un.varRdLnk.linkFailureCnt;
4374 4382 bp->rls_sync_loss = mb->un.varRdLnk.lossSyncCnt;
4375 4383 bp->rls_sig_loss = mb->un.varRdLnk.lossSignalCnt;
4376 4384 bp->rls_prim_seq_err = mb->un.varRdLnk.primSeqErrCnt;
4377 4385 bp->rls_invalid_word =
4378 4386 mb->un.varRdLnk.invalidXmitWord;
4379 4387 bp->rls_invalid_crc = mb->un.varRdLnk.crcCnt;
4380 4388 }
4381 4389
4382 4390 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
4383 4391 break;
4384 4392 }
4385 4393
4386 4394 case FC_PORT_DOWNLOAD_FW:
4387 4395 if (!(hba->flag & FC_ONLINE_MODE)) {
4388 4396 return (FC_OFFLINE);
4389 4397 }
4390 4398 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4391 4399 "fca_port_manage: FC_PORT_DOWNLOAD_FW");
4392 4400 ret = emlxs_fw_download(hba, pm->pm_data_buf,
4393 4401 pm->pm_data_len, 1);
4394 4402 break;
4395 4403
4396 4404 case FC_PORT_DOWNLOAD_FCODE:
4397 4405 if (!(hba->flag & FC_ONLINE_MODE)) {
4398 4406 return (FC_OFFLINE);
4399 4407 }
4400 4408 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4401 4409 "fca_port_manage: FC_PORT_DOWNLOAD_FCODE");
4402 4410 ret = emlxs_fw_download(hba, pm->pm_data_buf,
4403 4411 pm->pm_data_len, 1);
4404 4412 break;
4405 4413
4406 4414 case FC_PORT_DIAG:
4407 4415 {
4408 4416 uint32_t errno = 0;
4409 4417 uint32_t did = 0;
4410 4418 uint32_t pattern = 0;
4411 4419
4412 4420 switch (pm->pm_cmd_flags) {
4413 4421 case EMLXS_DIAG_BIU:
4414 4422
4415 4423 if (!(hba->flag & FC_ONLINE_MODE)) {
4416 4424 return (FC_OFFLINE);
4417 4425 }
4418 4426 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4419 4427 "fca_port_manage: DIAG_BIU");
4420 4428
4421 4429 if (pm->pm_data_len) {
4422 4430 pattern = *((uint32_t *)pm->pm_data_buf);
4423 4431 }
4424 4432
4425 4433 errno = emlxs_diag_biu_run(hba, pattern);
4426 4434
4427 4435 if (pm->pm_stat_len == sizeof (errno)) {
4428 4436 *(int *)pm->pm_stat_buf = errno;
4429 4437 }
4430 4438
4431 4439 break;
4432 4440
4433 4441
4434 4442 case EMLXS_DIAG_POST:
4435 4443
4436 4444 if (!(hba->flag & FC_ONLINE_MODE)) {
4437 4445 return (FC_OFFLINE);
4438 4446 }
4439 4447 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4440 4448 "fca_port_manage: DIAG_POST");
4441 4449
4442 4450 errno = emlxs_diag_post_run(hba);
4443 4451
4444 4452 if (pm->pm_stat_len == sizeof (errno)) {
4445 4453 *(int *)pm->pm_stat_buf = errno;
4446 4454 }
4447 4455
4448 4456 break;
4449 4457
4450 4458
4451 4459 case EMLXS_DIAG_ECHO:
4452 4460
4453 4461 if (!(hba->flag & FC_ONLINE_MODE)) {
4454 4462 return (FC_OFFLINE);
4455 4463 }
4456 4464 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4457 4465 "fca_port_manage: DIAG_ECHO");
4458 4466
4459 4467 if (pm->pm_cmd_len != sizeof (uint32_t)) {
4460 4468 ret = FC_INVALID_REQUEST;
4461 4469 break;
4462 4470 }
4463 4471
4464 4472 did = *((uint32_t *)pm->pm_cmd_buf);
4465 4473
4466 4474 if (pm->pm_data_len) {
4467 4475 pattern = *((uint32_t *)pm->pm_data_buf);
4468 4476 }
4469 4477
4470 4478 errno = emlxs_diag_echo_run(port, did, pattern);
4471 4479
4472 4480 if (pm->pm_stat_len == sizeof (errno)) {
4473 4481 *(int *)pm->pm_stat_buf = errno;
4474 4482 }
4475 4483
4476 4484 break;
4477 4485
4478 4486
4479 4487 case EMLXS_PARM_GET_NUM:
4480 4488 {
4481 4489 uint32_t *num;
4482 4490 emlxs_config_t *cfg;
4483 4491 uint32_t i;
4484 4492 uint32_t count;
4485 4493 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4486 4494 "fca_port_manage: PARM_GET_NUM");
4487 4495
4488 4496 if (pm->pm_stat_len < sizeof (uint32_t)) {
4489 4497 ret = FC_NOMEM;
4490 4498 break;
4491 4499 }
4492 4500
4493 4501 num = (uint32_t *)pm->pm_stat_buf;
4494 4502 count = 0;
4495 4503 cfg = &CFG;
4496 4504 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
4497 4505 if (!(cfg->flags & PARM_HIDDEN)) {
4498 4506 count++;
4499 4507 }
4500 4508
4501 4509 }
4502 4510
4503 4511 *num = count;
4504 4512
4505 4513 break;
4506 4514 }
4507 4515
4508 4516 case EMLXS_PARM_GET_LIST:
4509 4517 {
4510 4518 emlxs_parm_t *parm;
4511 4519 emlxs_config_t *cfg;
4512 4520 uint32_t i;
4513 4521 uint32_t max_count;
4514 4522
4515 4523 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4516 4524 "fca_port_manage: PARM_GET_LIST");
4517 4525
4518 4526 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
4519 4527 ret = FC_NOMEM;
4520 4528 break;
4521 4529 }
4522 4530
4523 4531 max_count = pm->pm_stat_len / sizeof (emlxs_parm_t);
4524 4532
4525 4533 parm = (emlxs_parm_t *)pm->pm_stat_buf;
4526 4534 cfg = &CFG;
4527 4535 for (i = 0; i < NUM_CFG_PARAM && max_count; i++,
4528 4536 cfg++) {
4529 4537 if (!(cfg->flags & PARM_HIDDEN)) {
4530 4538 (void) strncpy(parm->label, cfg->string,
4531 4539 (sizeof (parm->label)-1));
4532 4540 parm->min = cfg->low;
4533 4541 parm->max = cfg->hi;
4534 4542 parm->def = cfg->def;
4535 4543 parm->current = cfg->current;
4536 4544 parm->flags = cfg->flags;
4537 4545 (void) strncpy(parm->help, cfg->help,
4538 4546 (sizeof (parm->help)-1));
4539 4547 parm++;
4540 4548 max_count--;
4541 4549 }
4542 4550 }
4543 4551
4544 4552 break;
4545 4553 }
4546 4554
4547 4555 case EMLXS_PARM_GET:
4548 4556 {
4549 4557 emlxs_parm_t *parm_in;
4550 4558 emlxs_parm_t *parm_out;
4551 4559 emlxs_config_t *cfg;
4552 4560 uint32_t i;
4553 4561 uint32_t len;
4554 4562
4555 4563 if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) {
4556 4564 EMLXS_MSGF(EMLXS_CONTEXT,
4557 4565 &emlxs_sfs_debug_msg,
4558 4566 "fca_port_manage: PARM_GET. "
4559 4567 "inbuf too small.");
4560 4568
4561 4569 ret = FC_BADCMD;
4562 4570 break;
4563 4571 }
4564 4572
4565 4573 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
4566 4574 EMLXS_MSGF(EMLXS_CONTEXT,
4567 4575 &emlxs_sfs_debug_msg,
4568 4576 "fca_port_manage: PARM_GET. "
4569 4577 "outbuf too small");
4570 4578
4571 4579 ret = FC_BADCMD;
4572 4580 break;
4573 4581 }
4574 4582
4575 4583 parm_in = (emlxs_parm_t *)pm->pm_cmd_buf;
4576 4584 parm_out = (emlxs_parm_t *)pm->pm_stat_buf;
4577 4585 len = strlen(parm_in->label);
4578 4586 cfg = &CFG;
4579 4587 ret = FC_BADOBJECT;
4580 4588
4581 4589 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4582 4590 "fca_port_manage: PARM_GET: %s=0x%x,%d",
4583 4591 parm_in->label, parm_in->current,
4584 4592 parm_in->current);
4585 4593
4586 4594 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
4587 4595 if (len == strlen(cfg->string) &&
4588 4596 (strcmp(parm_in->label,
4589 4597 cfg->string) == 0)) {
4590 4598 (void) strncpy(parm_out->label,
4591 4599 cfg->string,
4592 4600 (sizeof (parm_out->label)-1));
4593 4601 parm_out->min = cfg->low;
4594 4602 parm_out->max = cfg->hi;
4595 4603 parm_out->def = cfg->def;
4596 4604 parm_out->current = cfg->current;
4597 4605 parm_out->flags = cfg->flags;
4598 4606 (void) strncpy(parm_out->help,
4599 4607 cfg->help,
4600 4608 (sizeof (parm_out->help)-1));
4601 4609
4602 4610 ret = FC_SUCCESS;
4603 4611 break;
4604 4612 }
4605 4613 }
4606 4614
4607 4615 break;
4608 4616 }
4609 4617
4610 4618 case EMLXS_PARM_SET:
4611 4619 {
4612 4620 emlxs_parm_t *parm_in;
4613 4621 emlxs_parm_t *parm_out;
4614 4622 emlxs_config_t *cfg;
4615 4623 uint32_t i;
4616 4624 uint32_t len;
4617 4625
4618 4626 if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) {
4619 4627 EMLXS_MSGF(EMLXS_CONTEXT,
4620 4628 &emlxs_sfs_debug_msg,
4621 4629 "fca_port_manage: PARM_GET. "
4622 4630 "inbuf too small.");
4623 4631
4624 4632 ret = FC_BADCMD;
4625 4633 break;
4626 4634 }
4627 4635
4628 4636 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) {
4629 4637 EMLXS_MSGF(EMLXS_CONTEXT,
4630 4638 &emlxs_sfs_debug_msg,
4631 4639 "fca_port_manage: PARM_GET. "
4632 4640 "outbuf too small");
4633 4641 ret = FC_BADCMD;
4634 4642 break;
4635 4643 }
4636 4644
4637 4645 parm_in = (emlxs_parm_t *)pm->pm_cmd_buf;
4638 4646 parm_out = (emlxs_parm_t *)pm->pm_stat_buf;
4639 4647 len = strlen(parm_in->label);
4640 4648 cfg = &CFG;
4641 4649 ret = FC_BADOBJECT;
4642 4650
4643 4651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4644 4652 "fca_port_manage: PARM_SET: %s=0x%x,%d",
4645 4653 parm_in->label, parm_in->current,
4646 4654 parm_in->current);
4647 4655
4648 4656 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
4649 4657 /* Find matching parameter string */
4650 4658 if (len == strlen(cfg->string) &&
4651 4659 (strcmp(parm_in->label,
4652 4660 cfg->string) == 0)) {
4653 4661 /* Attempt to update parameter */
4654 4662 if (emlxs_set_parm(hba, i,
4655 4663 parm_in->current) == FC_SUCCESS) {
4656 4664 (void) strncpy(parm_out->label,
4657 4665 cfg->string,
4658 4666 (sizeof (parm_out->label)-
4659 4667 1));
4660 4668 parm_out->min = cfg->low;
4661 4669 parm_out->max = cfg->hi;
4662 4670 parm_out->def = cfg->def;
4663 4671 parm_out->current =
4664 4672 cfg->current;
4665 4673 parm_out->flags = cfg->flags;
4666 4674 (void) strncpy(parm_out->help,
4667 4675 cfg->help,
4668 4676 (sizeof (parm_out->help)-
4669 4677 1));
4670 4678
4671 4679 ret = FC_SUCCESS;
4672 4680 }
4673 4681
4674 4682 break;
4675 4683 }
4676 4684 }
4677 4685
4678 4686 break;
4679 4687 }
4680 4688
4681 4689 case EMLXS_LOG_GET:
4682 4690 {
4683 4691 emlxs_log_req_t *req;
4684 4692 emlxs_log_resp_t *resp;
4685 4693 uint32_t len;
4686 4694
4687 4695 /* Check command size */
4688 4696 if (pm->pm_cmd_len < sizeof (emlxs_log_req_t)) {
4689 4697 ret = FC_BADCMD;
4690 4698 break;
4691 4699 }
4692 4700
4693 4701 /* Get the request */
4694 4702 req = (emlxs_log_req_t *)pm->pm_cmd_buf;
4695 4703
4696 4704 /* Calculate the response length from the request */
4697 4705 len = sizeof (emlxs_log_resp_t) +
4698 4706 (req->count * MAX_LOG_MSG_LENGTH);
4699 4707
4700 4708 /* Check the response buffer length */
4701 4709 if (pm->pm_stat_len < len) {
4702 4710 ret = FC_BADCMD;
4703 4711 break;
4704 4712 }
4705 4713
4706 4714 /* Get the response pointer */
4707 4715 resp = (emlxs_log_resp_t *)pm->pm_stat_buf;
4708 4716
4709 4717 /* Get the request log enties */
4710 4718 (void) emlxs_msg_log_get(hba, req, resp);
4711 4719
4712 4720 ret = FC_SUCCESS;
4713 4721 break;
4714 4722 }
4715 4723
4716 4724 case EMLXS_GET_BOOT_REV:
4717 4725 {
4718 4726 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4719 4727 "fca_port_manage: GET_BOOT_REV");
4720 4728
4721 4729 if (pm->pm_stat_len < strlen(vpd->boot_version)) {
4722 4730 ret = FC_NOMEM;
4723 4731 break;
4724 4732 }
4725 4733
4726 4734 bzero(pm->pm_stat_buf, pm->pm_stat_len);
4727 4735 (void) snprintf(pm->pm_stat_buf, pm->pm_stat_len,
4728 4736 "%s %s", hba->model_info.model, vpd->boot_version);
4729 4737
4730 4738 break;
4731 4739 }
4732 4740
4733 4741 case EMLXS_DOWNLOAD_BOOT:
4734 4742 if (!(hba->flag & FC_ONLINE_MODE)) {
4735 4743 return (FC_OFFLINE);
4736 4744 }
4737 4745 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4738 4746 "fca_port_manage: DOWNLOAD_BOOT");
4739 4747
4740 4748 ret = emlxs_fw_download(hba, pm->pm_data_buf,
4741 4749 pm->pm_data_len, 1);
4742 4750 break;
4743 4751
4744 4752 case EMLXS_DOWNLOAD_CFL:
4745 4753 {
4746 4754 uint32_t *buffer;
4747 4755 uint32_t region;
4748 4756 uint32_t length;
4749 4757
4750 4758 if (!(hba->flag & FC_ONLINE_MODE)) {
4751 4759 return (FC_OFFLINE);
4752 4760 }
4753 4761
4754 4762 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4755 4763 "fca_port_manage: DOWNLOAD_CFL");
4756 4764
4757 4765 /* Extract the region number from the first word. */
4758 4766 buffer = (uint32_t *)pm->pm_data_buf;
4759 4767 region = *buffer++;
4760 4768
4761 4769 /* Adjust the image length for the header word */
4762 4770 length = pm->pm_data_len - 4;
4763 4771
4764 4772 ret =
4765 4773 emlxs_cfl_download(hba, region, (caddr_t)buffer,
4766 4774 length);
4767 4775 break;
4768 4776 }
4769 4777
4770 4778 case EMLXS_VPD_GET:
4771 4779 {
4772 4780 emlxs_vpd_desc_t *vpd_out;
4773 4781
4774 4782 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4775 4783 "fca_port_manage: VPD_GET");
4776 4784
4777 4785 if (pm->pm_stat_len < sizeof (emlxs_vpd_desc_t)) {
4778 4786 ret = FC_BADCMD;
4779 4787 break;
4780 4788 }
4781 4789
4782 4790 vpd_out = (emlxs_vpd_desc_t *)pm->pm_stat_buf;
4783 4791 bzero(vpd_out, pm->pm_stat_len);
4784 4792
4785 4793 (void) strncpy(vpd_out->id, vpd->id,
4786 4794 (sizeof (vpd_out->id)-1));
4787 4795 (void) strncpy(vpd_out->part_num, vpd->part_num,
4788 4796 (sizeof (vpd_out->part_num)-1));
4789 4797 (void) strncpy(vpd_out->eng_change, vpd->eng_change,
4790 4798 (sizeof (vpd_out->eng_change)-1));
4791 4799 (void) strncpy(vpd_out->manufacturer, vpd->manufacturer,
4792 4800 (sizeof (vpd_out->manufacturer)-1));
4793 4801 (void) strncpy(vpd_out->serial_num, vpd->serial_num,
4794 4802 (sizeof (vpd_out->serial_num)-1));
4795 4803 (void) strncpy(vpd_out->model, vpd->model,
4796 4804 (sizeof (vpd_out->model)-1));
4797 4805 (void) strncpy(vpd_out->model_desc, vpd->model_desc,
4798 4806 (sizeof (vpd_out->model_desc)-1));
4799 4807 (void) strncpy(vpd_out->port_num, vpd->port_num,
4800 4808 (sizeof (vpd_out->port_num)-1));
4801 4809 (void) strncpy(vpd_out->prog_types, vpd->prog_types,
4802 4810 (sizeof (vpd_out->prog_types)-1));
4803 4811
4804 4812 ret = FC_SUCCESS;
4805 4813
4806 4814 break;
4807 4815 }
4808 4816
4809 4817 case EMLXS_VPD_GET_V2:
4810 4818 {
4811 4819 emlxs_vpd_desc_v2_t *vpd_out;
4812 4820
4813 4821 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4814 4822 "fca_port_manage: VPD_GET_V2");
4815 4823
4816 4824 if (pm->pm_stat_len < sizeof (emlxs_vpd_desc_v2_t)) {
4817 4825 ret = FC_BADCMD;
4818 4826 break;
4819 4827 }
4820 4828
4821 4829 vpd_out = (emlxs_vpd_desc_v2_t *)pm->pm_stat_buf;
4822 4830 bzero(vpd_out, pm->pm_stat_len);
4823 4831
4824 4832 (void) strncpy(vpd_out->id, vpd->id,
4825 4833 (sizeof (vpd_out->id)-1));
4826 4834 (void) strncpy(vpd_out->part_num, vpd->part_num,
4827 4835 (sizeof (vpd_out->part_num)-1));
4828 4836 (void) strncpy(vpd_out->eng_change, vpd->eng_change,
4829 4837 (sizeof (vpd_out->eng_change)-1));
4830 4838 (void) strncpy(vpd_out->manufacturer, vpd->manufacturer,
4831 4839 (sizeof (vpd_out->manufacturer)-1));
4832 4840 (void) strncpy(vpd_out->serial_num, vpd->serial_num,
4833 4841 (sizeof (vpd_out->serial_num)-1));
4834 4842 (void) strncpy(vpd_out->model, vpd->model,
4835 4843 (sizeof (vpd_out->model)-1));
4836 4844 (void) strncpy(vpd_out->model_desc, vpd->model_desc,
4837 4845 (sizeof (vpd_out->model_desc)-1));
4838 4846 (void) strncpy(vpd_out->port_num, vpd->port_num,
4839 4847 (sizeof (vpd_out->port_num)-1));
4840 4848 (void) strncpy(vpd_out->prog_types, vpd->prog_types,
4841 4849 (sizeof (vpd_out->prog_types)-1));
4842 4850
4843 4851 ret = FC_SUCCESS;
4844 4852
4845 4853 break;
4846 4854 }
4847 4855
4848 4856 case EMLXS_PHY_GET:
4849 4857 {
4850 4858 emlxs_phy_desc_t *phy_out;
4851 4859 MAILBOXQ *mbq;
4852 4860 MAILBOX4 *mb;
4853 4861 IOCTL_COMMON_GET_PHY_DETAILS *phy;
4854 4862 mbox_req_hdr_t *hdr_req;
4855 4863
4856 4864 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4857 4865 "fca_port_manage: EMLXS_PHY_GET");
4858 4866
4859 4867 if (pm->pm_stat_len < sizeof (emlxs_phy_desc_t)) {
4860 4868 ret = FC_BADCMD;
4861 4869 break;
4862 4870 }
4863 4871
4864 4872 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4865 4873 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4866 4874 "Invalid sli_mode. mode=%d", hba->sli_mode);
4867 4875 ret = FC_BADCMD;
4868 4876 break;
4869 4877 }
4870 4878
4871 4879 phy_out = (emlxs_phy_desc_t *)pm->pm_stat_buf;
4872 4880 bzero(phy_out, sizeof (emlxs_phy_desc_t));
4873 4881
4874 4882 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba,
4875 4883 MEM_MBOX)) == 0) {
4876 4884 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4877 4885 "Unable to allocate mailbox buffer.");
4878 4886 ret = FC_NOMEM;
4879 4887 break;
4880 4888 }
4881 4889
4882 4890 mb = (MAILBOX4*)mbq;
4883 4891
4884 4892 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
4885 4893
4886 4894 mb->un.varSLIConfig.be.embedded = 1;
4887 4895 mbq->mbox_cmpl = NULL;
4888 4896
4889 4897 mb->mbxCommand = MBX_SLI_CONFIG;
4890 4898 mb->mbxOwner = OWN_HOST;
4891 4899
4892 4900 hdr_req = (mbox_req_hdr_t *)
4893 4901 &mb->un.varSLIConfig.be.un_hdr.hdr_req;
4894 4902 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
4895 4903 hdr_req->opcode = COMMON_OPCODE_GET_PHY_DETAILS;
4896 4904 hdr_req->timeout = 0;
4897 4905 hdr_req->req_length =
4898 4906 sizeof (IOCTL_COMMON_GET_PHY_DETAILS);
4899 4907
4900 4908 phy = (IOCTL_COMMON_GET_PHY_DETAILS *)(hdr_req + 1);
4901 4909
4902 4910 /* Send read request */
4903 4911 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
4904 4912 MBX_SUCCESS) {
4905 4913 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4906 4914 "Unable to get PHY details. status=%x",
4907 4915 mb->mbxStatus);
4908 4916
4909 4917 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
4910 4918
4911 4919 ret = FC_FAILURE;
4912 4920 break;
4913 4921 }
4914 4922
4915 4923 phy_out->phy_type = phy->params.response.phy_type;
4916 4924 phy_out->interface_type =
4917 4925 phy->params.response.interface_type;
4918 4926 phy_out->misc_params = phy->params.response.misc_params;
4919 4927 phy_out->rsvd[0] = phy->params.response.rsvd[0];
4920 4928 phy_out->rsvd[1] = phy->params.response.rsvd[1];
4921 4929 phy_out->rsvd[2] = phy->params.response.rsvd[2];
4922 4930 phy_out->rsvd[3] = phy->params.response.rsvd[3];
4923 4931
4924 4932 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
4925 4933
4926 4934 ret = FC_SUCCESS;
4927 4935 break;
4928 4936 }
4929 4937
4930 4938 #ifdef NODE_THROTTLE_SUPPORT
4931 4939 case EMLXS_SET_THROTTLE:
4932 4940 {
4933 4941 emlxs_node_t *node;
4934 4942 uint32_t scope = 0;
4935 4943 uint32_t i;
4936 4944 char buf1[32];
4937 4945 emlxs_throttle_desc_t *desc;
4938 4946
4939 4947 if ((pm->pm_data_buf == NULL) ||
4940 4948 (pm->pm_data_len !=
4941 4949 sizeof (emlxs_throttle_desc_t))) {
4942 4950 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4943 4951 "fca_port_manage: EMLXS_SET_THROTTLE: "
4944 4952 "Descriptor buffer not valid. %d",
4945 4953 pm->pm_data_len);
4946 4954 ret = FC_BADCMD;
4947 4955 break;
4948 4956 }
4949 4957
4950 4958 if ((pm->pm_cmd_buf != NULL) &&
4951 4959 (pm->pm_cmd_len == sizeof (uint32_t))) {
4952 4960 scope = *(uint32_t *)pm->pm_cmd_buf;
4953 4961 }
4954 4962
4955 4963 desc = (emlxs_throttle_desc_t *)pm->pm_data_buf;
4956 4964 desc->throttle = MIN(desc->throttle, MAX_NODE_THROTTLE);
4957 4965
4958 4966 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4959 4967 "fca_port_manage: EMLXS_SET_THROTTLE: scope=%d "
4960 4968 "depth=%d",
4961 4969 scope, desc->throttle);
4962 4970
4963 4971 rw_enter(&port->node_rwlock, RW_WRITER);
4964 4972 switch (scope) {
4965 4973 case 1: /* all */
4966 4974 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
4967 4975 node = port->node_table[i];
4968 4976 while (node != NULL) {
4969 4977 node->io_throttle = desc->throttle;
4970 4978
4971 4979 EMLXS_MSGF(EMLXS_CONTEXT,
4972 4980 &emlxs_sfs_debug_msg,
4973 4981 "EMLXS_SET_THROTTLE: wwpn=%s "
4974 4982 "depth=%d",
4975 4983 emlxs_wwn_xlate(buf1, sizeof (buf1),
4976 4984 (uint8_t *)&node->nlp_portname),
4977 4985 node->io_throttle);
4978 4986
4979 4987 node = (NODELIST *)node->nlp_list_next;
4980 4988 }
4981 4989 }
4982 4990 break;
4983 4991
4984 4992 case 2: /* FCP */
4985 4993 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
4986 4994 node = port->node_table[i];
4987 4995 while (node != NULL) {
4988 4996 if (!(node->nlp_fcp_info &
4989 4997 NLP_FCP_TGT_DEVICE)) {
4990 4998 node = (NODELIST *)
4991 4999 node->nlp_list_next;
4992 5000 continue;
4993 5001 }
4994 5002
4995 5003 node->io_throttle = desc->throttle;
4996 5004
4997 5005 EMLXS_MSGF(EMLXS_CONTEXT,
4998 5006 &emlxs_sfs_debug_msg,
4999 5007 "EMLXS_SET_THROTTLE: wwpn=%s "
5000 5008 "depth=%d",
5001 5009 emlxs_wwn_xlate(buf1, sizeof (buf1),
5002 5010 (uint8_t *)&node->nlp_portname),
5003 5011 node->io_throttle);
5004 5012
5005 5013 node = (NODELIST *)node->nlp_list_next;
5006 5014 }
5007 5015 }
5008 5016 break;
5009 5017
5010 5018 case 0: /* WWPN */
5011 5019 default:
5012 5020 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
5013 5021 node = port->node_table[i];
5014 5022 while (node != NULL) {
5015 5023 if (bcmp((caddr_t)&node->nlp_portname,
5016 5024 desc->wwpn, 8)) {
5017 5025 node = (NODELIST *)
5018 5026 node->nlp_list_next;
5019 5027 continue;
5020 5028 }
5021 5029
5022 5030 node->io_throttle = desc->throttle;
5023 5031
5024 5032 EMLXS_MSGF(EMLXS_CONTEXT,
5025 5033 &emlxs_sfs_debug_msg,
5026 5034 "EMLXS_SET_THROTTLE: wwpn=%s "
5027 5035 "depth=%d",
5028 5036 emlxs_wwn_xlate(buf1, sizeof (buf1),
5029 5037 (uint8_t *)&node->nlp_portname),
5030 5038 node->io_throttle);
5031 5039
5032 5040 goto set_throttle_done;
5033 5041 }
5034 5042 }
5035 5043 set_throttle_done:
5036 5044 break;
5037 5045 }
5038 5046
5039 5047 rw_exit(&port->node_rwlock);
5040 5048 ret = FC_SUCCESS;
5041 5049
5042 5050 break;
5043 5051 }
5044 5052
5045 5053 case EMLXS_GET_THROTTLE:
5046 5054 {
5047 5055 emlxs_node_t *node;
5048 5056 uint32_t i;
5049 5057 uint32_t j;
5050 5058 char buf1[32];
5051 5059 uint32_t count;
5052 5060 emlxs_throttle_desc_t *desc;
5053 5061
5054 5062 if (pm->pm_stat_len == sizeof (uint32_t)) {
5055 5063 count = emlxs_nport_count(port);
5056 5064 *(uint32_t *)pm->pm_stat_buf = count;
5057 5065
5058 5066 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5059 5067 "fca_port_manage: EMLXS_GET_THROTTLE: "
5060 5068 "count=%d",
5061 5069 count);
5062 5070
5063 5071 ret = FC_SUCCESS;
5064 5072 break;
5065 5073 }
5066 5074
5067 5075 if ((pm->pm_stat_buf == NULL) ||
5068 5076 (pm->pm_stat_len <
5069 5077 sizeof (emlxs_throttle_desc_t))) {
5070 5078 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5071 5079 "fca_port_manage: EMLXS_GET_THROTTLE: "
5072 5080 "Descriptor buffer too small. %d",
5073 5081 pm->pm_data_len);
5074 5082 ret = FC_BADCMD;
5075 5083 break;
5076 5084 }
5077 5085
5078 5086 count = pm->pm_stat_len /
5079 5087 sizeof (emlxs_throttle_desc_t);
5080 5088 desc = (emlxs_throttle_desc_t *)pm->pm_stat_buf;
5081 5089
5082 5090 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5083 5091 "fca_port_manage: EMLXS_GET_THROTTLE: max=%d",
5084 5092 count);
5085 5093
5086 5094 rw_enter(&port->node_rwlock, RW_READER);
5087 5095 j = 0;
5088 5096 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
5089 5097 node = port->node_table[i];
5090 5098 while (node != NULL) {
5091 5099 if ((node->nlp_DID & 0xFFF000) ==
5092 5100 0xFFF000) {
5093 5101 node = (NODELIST *)
5094 5102 node->nlp_list_next;
5095 5103 continue;
5096 5104 }
5097 5105
5098 5106 bcopy((uint8_t *)&node->nlp_portname,
5099 5107 desc[j].wwpn, 8);
5100 5108 desc[j].throttle = node->io_throttle;
5101 5109
5102 5110 EMLXS_MSGF(EMLXS_CONTEXT,
5103 5111 &emlxs_sfs_debug_msg,
5104 5112 "EMLXS_GET_THROTTLE: wwpn=%s "
5105 5113 "depth=%d",
5106 5114 emlxs_wwn_xlate(buf1, sizeof (buf1),
5107 5115 desc[j].wwpn),
5108 5116 desc[j].throttle);
5109 5117
5110 5118 j++;
5111 5119 if (j >= count) {
5112 5120 goto get_throttle_done;
5113 5121 }
5114 5122
5115 5123 node = (NODELIST *)node->nlp_list_next;
5116 5124 }
5117 5125 }
5118 5126 get_throttle_done:
5119 5127 rw_exit(&port->node_rwlock);
5120 5128 ret = FC_SUCCESS;
5121 5129
5122 5130 break;
5123 5131 }
5124 5132 #endif /* NODE_THROTTLE_SUPPORT */
5125 5133
5126 5134 case EMLXS_GET_FCIO_REV:
5127 5135 {
5128 5136 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5129 5137 "fca_port_manage: GET_FCIO_REV");
5130 5138
5131 5139 if (pm->pm_stat_len < sizeof (uint32_t)) {
5132 5140 ret = FC_NOMEM;
5133 5141 break;
5134 5142 }
5135 5143
5136 5144 bzero(pm->pm_stat_buf, pm->pm_stat_len);
5137 5145 *(uint32_t *)pm->pm_stat_buf = FCIO_REV;
5138 5146
5139 5147 break;
5140 5148 }
5141 5149
5142 5150 case EMLXS_GET_DFC_REV:
5143 5151 {
5144 5152 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5145 5153 "fca_port_manage: GET_DFC_REV");
5146 5154
5147 5155 if (pm->pm_stat_len < sizeof (uint32_t)) {
5148 5156 ret = FC_NOMEM;
5149 5157 break;
5150 5158 }
5151 5159
5152 5160 bzero(pm->pm_stat_buf, pm->pm_stat_len);
5153 5161 *(uint32_t *)pm->pm_stat_buf = DFC_REV;
5154 5162
5155 5163 break;
5156 5164 }
5157 5165
5158 5166 case EMLXS_SET_BOOT_STATE:
5159 5167 case EMLXS_SET_BOOT_STATE_old:
5160 5168 {
5161 5169 uint32_t state;
5162 5170
5163 5171 if (!(hba->flag & FC_ONLINE_MODE)) {
5164 5172 return (FC_OFFLINE);
5165 5173 }
5166 5174 if (pm->pm_cmd_len < sizeof (uint32_t)) {
5167 5175 EMLXS_MSGF(EMLXS_CONTEXT,
5168 5176 &emlxs_sfs_debug_msg,
5169 5177 "fca_port_manage: SET_BOOT_STATE");
5170 5178 ret = FC_BADCMD;
5171 5179 break;
5172 5180 }
5173 5181
5174 5182 state = *(uint32_t *)pm->pm_cmd_buf;
5175 5183
5176 5184 if (state == 0) {
5177 5185 EMLXS_MSGF(EMLXS_CONTEXT,
5178 5186 &emlxs_sfs_debug_msg,
5179 5187 "fca_port_manage: SET_BOOT_STATE: "
5180 5188 "Disable");
5181 5189 ret = emlxs_boot_code_disable(hba);
5182 5190 } else {
5183 5191 EMLXS_MSGF(EMLXS_CONTEXT,
5184 5192 &emlxs_sfs_debug_msg,
5185 5193 "fca_port_manage: SET_BOOT_STATE: "
5186 5194 "Enable");
5187 5195 ret = emlxs_boot_code_enable(hba);
5188 5196 }
5189 5197
5190 5198 break;
5191 5199 }
5192 5200
5193 5201 case EMLXS_GET_BOOT_STATE:
5194 5202 case EMLXS_GET_BOOT_STATE_old:
5195 5203 {
5196 5204 if (!(hba->flag & FC_ONLINE_MODE)) {
5197 5205 return (FC_OFFLINE);
5198 5206 }
5199 5207 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5200 5208 "fca_port_manage: GET_BOOT_STATE");
5201 5209
5202 5210 if (pm->pm_stat_len < sizeof (uint32_t)) {
5203 5211 ret = FC_NOMEM;
5204 5212 break;
5205 5213 }
5206 5214 bzero(pm->pm_stat_buf, pm->pm_stat_len);
5207 5215
5208 5216 ret = emlxs_boot_code_state(hba);
5209 5217
5210 5218 if (ret == FC_SUCCESS) {
5211 5219 *(uint32_t *)pm->pm_stat_buf = 1;
5212 5220 ret = FC_SUCCESS;
5213 5221 } else if (ret == FC_FAILURE) {
5214 5222 ret = FC_SUCCESS;
5215 5223 }
5216 5224
5217 5225 break;
5218 5226 }
5219 5227
5220 5228 case EMLXS_HW_ERROR_TEST:
5221 5229 {
5222 5230 /*
5223 5231 * This command is used for simulating HW ERROR
5224 5232 * on SLI4 only.
5225 5233 */
5226 5234 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5227 5235 ret = FC_INVALID_REQUEST;
5228 5236 break;
5229 5237 }
5230 5238 hba->sli.sli4.flag |= EMLXS_SLI4_HW_ERROR;
5231 5239 break;
5232 5240 }
5233 5241
5234 5242 case EMLXS_MB_TIMEOUT_TEST:
5235 5243 {
5236 5244 if (!(hba->flag & FC_ONLINE_MODE)) {
5237 5245 return (FC_OFFLINE);
5238 5246 }
5239 5247
5240 5248 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5241 5249 "fca_port_manage: HW_ERROR_TEST");
5242 5250
5243 5251 /* Trigger a mailbox timeout */
5244 5252 hba->mbox_timer = hba->timer_tics;
5245 5253
5246 5254 break;
5247 5255 }
5248 5256
5249 5257 case EMLXS_TEST_CODE:
5250 5258 {
5251 5259 uint32_t *cmd;
5252 5260
5253 5261 if (!(hba->flag & FC_ONLINE_MODE)) {
5254 5262 return (FC_OFFLINE);
5255 5263 }
5256 5264
5257 5265 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5258 5266 "fca_port_manage: TEST_CODE");
5259 5267
5260 5268 if (pm->pm_cmd_len < sizeof (uint32_t)) {
5261 5269 EMLXS_MSGF(EMLXS_CONTEXT,
5262 5270 &emlxs_sfs_debug_msg,
5263 5271 "fca_port_manage: TEST_CODE. "
5264 5272 "inbuf to small.");
5265 5273
5266 5274 ret = FC_BADCMD;
5267 5275 break;
5268 5276 }
5269 5277
5270 5278 cmd = (uint32_t *)pm->pm_cmd_buf;
5271 5279
5272 5280 ret = emlxs_test(hba, cmd[0],
5273 5281 (pm->pm_cmd_len/sizeof (uint32_t)) - 1, &cmd[1]);
5274 5282
5275 5283 break;
5276 5284 }
5277 5285
5278 5286 case EMLXS_BAR_IO:
5279 5287 {
5280 5288 uint32_t *cmd;
5281 5289 uint32_t *datap;
5282 5290 FCIO_Q_STAT_t *qp;
5283 5291 clock_t time;
5284 5292 uint32_t offset;
5285 5293 caddr_t addr;
5286 5294 uint32_t i;
5287 5295 uint32_t tx_cnt;
5288 5296 uint32_t chip_cnt;
5289 5297
5290 5298 cmd = (uint32_t *)pm->pm_cmd_buf;
5291 5299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5292 5300 "fca_port_manage: BAR_IO %x %x %x",
5293 5301 cmd[0], cmd[1], cmd[2]);
5294 5302
5295 5303 offset = cmd[1];
5296 5304
5297 5305 ret = FC_SUCCESS;
5298 5306
5299 5307 switch (cmd[0]) {
5300 5308 case 2: /* bar1read */
5301 5309 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5302 5310 return (FC_BADCMD);
5303 5311 }
5304 5312
5305 5313 /* Registers in this range are invalid */
5306 5314 if ((offset >= 0x4C00) && (offset < 0x5000)) {
5307 5315 return (FC_BADCMD);
5308 5316 }
5309 5317 if ((offset >= 0x5800) || (offset & 0x3)) {
5310 5318 return (FC_BADCMD);
5311 5319 }
5312 5320 datap = (uint32_t *)pm->pm_stat_buf;
5313 5321
5314 5322 for (i = 0; i < pm->pm_stat_len;
5315 5323 i += sizeof (uint32_t)) {
5316 5324 if ((offset >= 0x4C00) &&
5317 5325 (offset < 0x5000)) {
5318 5326 pm->pm_stat_len = i;
5319 5327 break;
5320 5328 }
5321 5329 if (offset >= 0x5800) {
5322 5330 pm->pm_stat_len = i;
5323 5331 break;
5324 5332 }
5325 5333 addr = hba->sli.sli4.bar1_addr + offset;
5326 5334 *datap = READ_BAR1_REG(hba, addr);
5327 5335 datap++;
5328 5336 offset += sizeof (uint32_t);
5329 5337 }
5330 5338 #ifdef FMA_SUPPORT
5331 5339 /* Access handle validation */
5332 5340 EMLXS_CHK_ACC_HANDLE(hba,
5333 5341 hba->sli.sli4.bar1_acc_handle);
5334 5342 #endif /* FMA_SUPPORT */
5335 5343 break;
5336 5344 case 3: /* bar2read */
5337 5345 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5338 5346 return (FC_BADCMD);
5339 5347 }
5340 5348 if ((offset >= 0x1000) || (offset & 0x3)) {
5341 5349 return (FC_BADCMD);
5342 5350 }
5343 5351 datap = (uint32_t *)pm->pm_stat_buf;
5344 5352
5345 5353 for (i = 0; i < pm->pm_stat_len;
5346 5354 i += sizeof (uint32_t)) {
5347 5355 *datap = READ_BAR2_REG(hba,
5348 5356 hba->sli.sli4.bar2_addr + offset);
5349 5357 datap++;
5350 5358 offset += sizeof (uint32_t);
5351 5359 }
5352 5360 #ifdef FMA_SUPPORT
5353 5361 /* Access handle validation */
5354 5362 EMLXS_CHK_ACC_HANDLE(hba,
5355 5363 hba->sli.sli4.bar2_acc_handle);
5356 5364 #endif /* FMA_SUPPORT */
5357 5365 break;
5358 5366 case 4: /* bar1write */
5359 5367 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5360 5368 return (FC_BADCMD);
5361 5369 }
5362 5370 WRITE_BAR1_REG(hba, hba->sli.sli4.bar1_addr +
5363 5371 offset, cmd[2]);
5364 5372 #ifdef FMA_SUPPORT
5365 5373 /* Access handle validation */
5366 5374 EMLXS_CHK_ACC_HANDLE(hba,
5367 5375 hba->sli.sli4.bar1_acc_handle);
5368 5376 #endif /* FMA_SUPPORT */
5369 5377 break;
5370 5378 case 5: /* bar2write */
5371 5379 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5372 5380 return (FC_BADCMD);
5373 5381 }
5374 5382 WRITE_BAR2_REG(hba, hba->sli.sli4.bar2_addr +
5375 5383 offset, cmd[2]);
5376 5384 #ifdef FMA_SUPPORT
5377 5385 /* Access handle validation */
5378 5386 EMLXS_CHK_ACC_HANDLE(hba,
5379 5387 hba->sli.sli4.bar2_acc_handle);
5380 5388 #endif /* FMA_SUPPORT */
5381 5389 break;
5382 5390 case 6: /* dumpbsmbox */
5383 5391 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5384 5392 return (FC_BADCMD);
5385 5393 }
5386 5394 if (offset != 0) {
5387 5395 return (FC_BADCMD);
5388 5396 }
5389 5397
5390 5398 bcopy((caddr_t)hba->sli.sli4.bootstrapmb.virt,
5391 5399 (caddr_t)pm->pm_stat_buf, 256);
5392 5400 break;
5393 5401 case 7: /* pciread */
5394 5402 if ((offset >= 0x200) || (offset & 0x3)) {
5395 5403 return (FC_BADCMD);
5396 5404 }
5397 5405 datap = (uint32_t *)pm->pm_stat_buf;
5398 5406 for (i = 0; i < pm->pm_stat_len;
5399 5407 i += sizeof (uint32_t)) {
5400 5408 *datap = ddi_get32(hba->pci_acc_handle,
5401 5409 (uint32_t *)(hba->pci_addr +
5402 5410 offset));
5403 5411 datap++;
5404 5412 offset += sizeof (uint32_t);
5405 5413 }
5406 5414 #ifdef FMA_SUPPORT
5407 5415 /* Access handle validation */
5408 5416 EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
5409 5417 #endif /* FMA_SUPPORT */
5410 5418 break;
5411 5419 case 8: /* abortall */
5412 5420 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5413 5421 return (FC_BADCMD);
5414 5422 }
5415 5423 emlxs_abort_all(hba, &tx_cnt, &chip_cnt);
5416 5424 datap = (uint32_t *)pm->pm_stat_buf;
5417 5425 *datap++ = tx_cnt;
5418 5426 *datap = chip_cnt;
5419 5427 break;
5420 5428 case 9: /* get_q_info */
5421 5429 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5422 5430 return (FC_BADCMD);
5423 5431 }
5424 5432 qp = (FCIO_Q_STAT_t *)pm->pm_stat_buf;
5425 5433 for (i = 0; i < FCIO_MAX_EQS; i++) {
5426 5434 addr = hba->sli.sli4.eq[i].addr.virt;
5427 5435 qp->eq[i].host_index =
5428 5436 hba->sli.sli4.eq[i].host_index;
5429 5437 qp->eq[i].max_index =
5430 5438 hba->sli.sli4.eq[i].max_index;
5431 5439 qp->eq[i].qid =
5432 5440 hba->sli.sli4.eq[i].qid;
5433 5441 qp->eq[i].msix_vector =
5434 5442 hba->sli.sli4.eq[i].msix_vector;
5435 5443 qp->eq[i].phys =
5436 5444 hba->sli.sli4.eq[i].addr.phys;
5437 5445 qp->eq[i].virt = PADDR_LO(
5438 5446 (uintptr_t)addr);
5439 5447 qp->eq[i].virt_hi = PADDR_HI(
5440 5448 (uintptr_t)addr);
5441 5449 qp->eq[i].max_proc =
5442 5450 hba->sli.sli4.eq[i].max_proc;
5443 5451 qp->eq[i].isr_count =
5444 5452 hba->sli.sli4.eq[i].isr_count;
5445 5453 qp->eq[i].num_proc =
5446 5454 hba->sli.sli4.eq[i].num_proc;
5447 5455 }
5448 5456 for (i = 0; i < FCIO_MAX_CQS; i++) {
5449 5457 addr = hba->sli.sli4.cq[i].addr.virt;
5450 5458 qp->cq[i].host_index =
5451 5459 hba->sli.sli4.cq[i].host_index;
5452 5460 qp->cq[i].max_index =
5453 5461 hba->sli.sli4.cq[i].max_index;
5454 5462 qp->cq[i].qid =
5455 5463 hba->sli.sli4.cq[i].qid;
5456 5464 qp->cq[i].eqid =
5457 5465 hba->sli.sli4.cq[i].eqid;
5458 5466 qp->cq[i].type =
5459 5467 hba->sli.sli4.cq[i].type;
5460 5468 qp->cq[i].phys =
5461 5469 hba->sli.sli4.cq[i].addr.phys;
5462 5470 qp->cq[i].virt = PADDR_LO(
5463 5471 (uintptr_t)addr);
5464 5472 qp->cq[i].virt_hi = PADDR_HI(
5465 5473 (uintptr_t)addr);
5466 5474 qp->cq[i].max_proc =
5467 5475 hba->sli.sli4.cq[i].max_proc;
5468 5476 qp->cq[i].isr_count =
5469 5477 hba->sli.sli4.cq[i].isr_count;
5470 5478 qp->cq[i].num_proc =
5471 5479 hba->sli.sli4.cq[i].num_proc;
5472 5480 }
5473 5481 for (i = 0; i < FCIO_MAX_WQS; i++) {
5474 5482 addr = hba->sli.sli4.wq[i].addr.virt;
5475 5483 qp->wq[i].host_index =
5476 5484 hba->sli.sli4.wq[i].host_index;
5477 5485 qp->wq[i].max_index =
5478 5486 hba->sli.sli4.wq[i].max_index;
5479 5487 qp->wq[i].port_index =
5480 5488 hba->sli.sli4.wq[i].port_index;
5481 5489 qp->wq[i].release_depth =
5482 5490 hba->sli.sli4.wq[i].release_depth;
5483 5491 qp->wq[i].qid =
5484 5492 hba->sli.sli4.wq[i].qid;
5485 5493 qp->wq[i].cqid =
5486 5494 hba->sli.sli4.wq[i].cqid;
5487 5495 qp->wq[i].phys =
5488 5496 hba->sli.sli4.wq[i].addr.phys;
5489 5497 qp->wq[i].virt = PADDR_LO(
5490 5498 (uintptr_t)addr);
5491 5499 qp->wq[i].virt_hi = PADDR_HI(
5492 5500 (uintptr_t)addr);
5493 5501 qp->wq[i].num_proc =
5494 5502 hba->sli.sli4.wq[i].num_proc;
5495 5503 qp->wq[i].num_busy =
5496 5504 hba->sli.sli4.wq[i].num_busy;
5497 5505 }
5498 5506 for (i = 0; i < FCIO_MAX_RQS; i++) {
5499 5507 addr = hba->sli.sli4.rq[i].addr.virt;
5500 5508 qp->rq[i].qid =
5501 5509 hba->sli.sli4.rq[i].qid;
5502 5510 qp->rq[i].cqid =
5503 5511 hba->sli.sli4.rq[i].cqid;
5504 5512 qp->rq[i].host_index =
5505 5513 hba->sli.sli4.rq[i].host_index;
5506 5514 qp->rq[i].max_index =
5507 5515 hba->sli.sli4.rq[i].max_index;
5508 5516 qp->rq[i].phys =
5509 5517 hba->sli.sli4.rq[i].addr.phys;
5510 5518 qp->rq[i].virt = PADDR_LO(
5511 5519 (uintptr_t)addr);
5512 5520 qp->rq[i].virt_hi = PADDR_HI(
5513 5521 (uintptr_t)addr);
5514 5522 qp->rq[i].num_proc =
5515 5523 hba->sli.sli4.rq[i].num_proc;
5516 5524 }
5517 5525 qp->que_start_timer =
5518 5526 hba->sli.sli4.que_stat_timer;
5519 5527 (void) drv_getparm(LBOLT, &time);
5520 5528 qp->que_current_timer = (uint32_t)time;
5521 5529 qp->intr_count = hba->intr_count;
5522 5530 break;
5523 5531 case 10: /* zero_q_stat */
5524 5532 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
5525 5533 return (FC_BADCMD);
5526 5534 }
5527 5535 emlxs_sli4_zero_queue_stat(hba);
5528 5536 break;
5529 5537 default:
5530 5538 ret = FC_BADCMD;
5531 5539 break;
5532 5540 }
5533 5541 break;
5534 5542 }
5535 5543
5536 5544 default:
5537 5545
5538 5546 ret = FC_INVALID_REQUEST;
5539 5547 break;
5540 5548 }
5541 5549
5542 5550 break;
5543 5551
5544 5552 }
5545 5553
5546 5554 case FC_PORT_INITIALIZE:
5547 5555 if (!(hba->flag & FC_ONLINE_MODE)) {
5548 5556 return (FC_OFFLINE);
5549 5557 }
5550 5558 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5551 5559 "fca_port_manage: FC_PORT_INITIALIZE");
5552 5560 break;
5553 5561
5554 5562 case FC_PORT_LOOPBACK:
5555 5563 if (!(hba->flag & FC_ONLINE_MODE)) {
5556 5564 return (FC_OFFLINE);
5557 5565 }
5558 5566 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5559 5567 "fca_port_manage: FC_PORT_LOOPBACK");
5560 5568 break;
5561 5569
5562 5570 case FC_PORT_BYPASS:
5563 5571 if (!(hba->flag & FC_ONLINE_MODE)) {
5564 5572 return (FC_OFFLINE);
5565 5573 }
5566 5574 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5567 5575 "fca_port_manage: FC_PORT_BYPASS");
5568 5576 ret = FC_INVALID_REQUEST;
5569 5577 break;
5570 5578
5571 5579 case FC_PORT_UNBYPASS:
5572 5580 if (!(hba->flag & FC_ONLINE_MODE)) {
5573 5581 return (FC_OFFLINE);
5574 5582 }
5575 5583 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5576 5584 "fca_port_manage: FC_PORT_UNBYPASS");
5577 5585 ret = FC_INVALID_REQUEST;
5578 5586 break;
5579 5587
5580 5588 case FC_PORT_GET_NODE_ID:
5581 5589 {
5582 5590 fc_rnid_t *rnid;
5583 5591
5584 5592 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5585 5593 "fca_port_manage: FC_PORT_GET_NODE_ID");
5586 5594
5587 5595 bzero(pm->pm_data_buf, pm->pm_data_len);
5588 5596
5589 5597 if (pm->pm_data_len < sizeof (fc_rnid_t)) {
5590 5598 ret = FC_NOMEM;
5591 5599 break;
5592 5600 }
5593 5601
5594 5602 rnid = (fc_rnid_t *)pm->pm_data_buf;
5595 5603
5596 5604 (void) snprintf((char *)rnid->global_id,
5597 5605 (sizeof (rnid->global_id)-1),
5598 5606 "%01x%01x%02x%02x%02x%02x%02x%02x%02x",
5599 5607 hba->wwpn.nameType, hba->wwpn.IEEEextMsn,
5600 5608 hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0],
5601 5609 hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3],
5602 5610 hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
5603 5611
5604 5612 rnid->unit_type = RNID_HBA;
5605 5613 rnid->port_id = port->did;
5606 5614 rnid->ip_version = RNID_IPV4;
5607 5615
5608 5616 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5609 5617 "GET_NODE_ID: wwpn: %s", rnid->global_id);
5610 5618 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5611 5619 "GET_NODE_ID: unit_type: 0x%x", rnid->unit_type);
5612 5620 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5613 5621 "GET_NODE_ID: port_id: 0x%x", rnid->port_id);
5614 5622 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5615 5623 "GET_NODE_ID: num_attach: %d", rnid->num_attached);
5616 5624 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5617 5625 "GET_NODE_ID: ip_version: 0x%x", rnid->ip_version);
5618 5626 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5619 5627 "GET_NODE_ID: udp_port: 0x%x", rnid->udp_port);
5620 5628 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5621 5629 "GET_NODE_ID: ip_addr: %s", rnid->ip_addr);
5622 5630 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5623 5631 "GET_NODE_ID: resv: 0x%x", rnid->specific_id_resv);
5624 5632 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5625 5633 "GET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags);
5626 5634
5627 5635 ret = FC_SUCCESS;
5628 5636 break;
5629 5637 }
5630 5638
5631 5639 case FC_PORT_SET_NODE_ID:
5632 5640 {
5633 5641 fc_rnid_t *rnid;
5634 5642
5635 5643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5636 5644 "fca_port_manage: FC_PORT_SET_NODE_ID");
5637 5645
5638 5646 if (pm->pm_data_len < sizeof (fc_rnid_t)) {
5639 5647 ret = FC_NOMEM;
5640 5648 break;
5641 5649 }
5642 5650
5643 5651 rnid = (fc_rnid_t *)pm->pm_data_buf;
5644 5652
5645 5653 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5646 5654 "SET_NODE_ID: wwpn: %s", rnid->global_id);
5647 5655 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5648 5656 "SET_NODE_ID: unit_type: 0x%x", rnid->unit_type);
5649 5657 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5650 5658 "SET_NODE_ID: port_id: 0x%x", rnid->port_id);
5651 5659 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5652 5660 "SET_NODE_ID: num_attach: %d", rnid->num_attached);
5653 5661 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5654 5662 "SET_NODE_ID: ip_version: 0x%x", rnid->ip_version);
5655 5663 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5656 5664 "SET_NODE_ID: udp_port: 0x%x", rnid->udp_port);
5657 5665 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5658 5666 "SET_NODE_ID: ip_addr: %s", rnid->ip_addr);
5659 5667 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5660 5668 "SET_NODE_ID: resv: 0x%x", rnid->specific_id_resv);
5661 5669 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5662 5670 "SET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags);
5663 5671
5664 5672 ret = FC_SUCCESS;
5665 5673 break;
5666 5674 }
5667 5675
5668 5676 #ifdef S11
5669 5677 case FC_PORT_GET_P2P_INFO:
5670 5678 {
5671 5679 fc_fca_p2p_info_t *p2p_info;
5672 5680 NODELIST *ndlp;
5673 5681
5674 5682 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5675 5683 "fca_port_manage: FC_PORT_GET_P2P_INFO");
5676 5684
5677 5685 bzero(pm->pm_data_buf, pm->pm_data_len);
5678 5686
5679 5687 if (pm->pm_data_len < sizeof (fc_fca_p2p_info_t)) {
5680 5688 ret = FC_NOMEM;
5681 5689 break;
5682 5690 }
5683 5691
5684 5692 p2p_info = (fc_fca_p2p_info_t *)pm->pm_data_buf;
5685 5693
5686 5694 if (hba->state >= FC_LINK_UP) {
5687 5695 if ((hba->topology == TOPOLOGY_PT_PT) &&
5688 5696 (hba->flag & FC_PT_TO_PT)) {
5689 5697 p2p_info->fca_d_id = port->did;
5690 5698 p2p_info->d_id = port->rdid;
5691 5699
5692 5700 ndlp = emlxs_node_find_did(port,
5693 5701 port->rdid, 1);
5694 5702
5695 5703 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5696 5704 "FC_PORT_GET_P2P_INFO: fca_d_id: 0x%x, "
5697 5705 "d_id: 0x%x, ndlp: 0x%p", port->did,
5698 5706 port->rdid, ndlp);
5699 5707 if (ndlp) {
5700 5708 bcopy(&ndlp->nlp_portname,
5701 5709 (caddr_t)&p2p_info->pwwn,
5702 5710 sizeof (la_wwn_t));
5703 5711 bcopy(&ndlp->nlp_nodename,
5704 5712 (caddr_t)&p2p_info->nwwn,
5705 5713 sizeof (la_wwn_t));
5706 5714
5707 5715 ret = FC_SUCCESS;
5708 5716 break;
5709 5717
5710 5718 }
5711 5719 }
5712 5720 }
5713 5721
5714 5722 ret = FC_FAILURE;
5715 5723 break;
5716 5724 }
5717 5725 #endif /* S11 */
5718 5726
5719 5727 default:
5720 5728 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5721 5729 "fca_port_manage: code=%x", pm->pm_cmd_code);
5722 5730 ret = FC_INVALID_REQUEST;
5723 5731 break;
5724 5732
5725 5733 }
5726 5734
5727 5735 return (ret);
5728 5736
5729 5737 } /* emlxs_fca_port_manage() */
5730 5738
5731 5739
5732 5740 /*ARGSUSED*/
5733 5741 static uint32_t
5734 5742 emlxs_test(emlxs_hba_t *hba, uint32_t test_code, uint32_t args,
5735 5743 uint32_t *arg)
5736 5744 {
5737 5745 uint32_t rval = 0;
5738 5746 emlxs_port_t *port = &PPORT;
5739 5747
5740 5748 switch (test_code) {
5741 5749 #ifdef TEST_SUPPORT
5742 5750 case 1: /* SCSI underrun */
5743 5751 {
5744 5752 hba->underrun_counter = (args)? arg[0]:1;
5745 5753 break;
5746 5754 }
5747 5755 #endif /* TEST_SUPPORT */
5748 5756
5749 5757 default:
5750 5758 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5751 5759 "test: Unsupported test code. (0x%x)", test_code);
5752 5760 rval = FC_INVALID_REQUEST;
5753 5761 }
5754 5762
5755 5763 return (rval);
5756 5764
5757 5765 } /* emlxs_test() */
5758 5766
5759 5767
5760 5768 /*
5761 5769 * Given the device number, return the devinfo pointer or the ddiinst number.
5762 5770 * Note: this routine must be successful on DDI_INFO_DEVT2INSTANCE even
5763 5771 * before attach.
5764 5772 *
5765 5773 * Translate "dev_t" to a pointer to the associated "dev_info_t".
5766 5774 */
5767 5775 /*ARGSUSED*/
5768 5776 static int
5769 5777 emlxs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
5770 5778 {
5771 5779 emlxs_hba_t *hba;
5772 5780 int32_t ddiinst;
5773 5781
5774 5782 ddiinst = getminor((dev_t)arg);
5775 5783
5776 5784 switch (infocmd) {
5777 5785 case DDI_INFO_DEVT2DEVINFO:
5778 5786 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5779 5787 if (hba)
5780 5788 *result = hba->dip;
5781 5789 else
5782 5790 *result = NULL;
5783 5791 break;
5784 5792
5785 5793 case DDI_INFO_DEVT2INSTANCE:
5786 5794 *result = (void *)((unsigned long)ddiinst);
5787 5795 break;
5788 5796
5789 5797 default:
5790 5798 return (DDI_FAILURE);
5791 5799 }
5792 5800
5793 5801 return (DDI_SUCCESS);
5794 5802
5795 5803 } /* emlxs_info() */
5796 5804
5797 5805
5798 5806 static int32_t
5799 5807 emlxs_power(dev_info_t *dip, int32_t comp, int32_t level)
5800 5808 {
5801 5809 emlxs_hba_t *hba;
5802 5810 emlxs_port_t *port;
5803 5811 int32_t ddiinst;
5804 5812 int rval = DDI_SUCCESS;
5805 5813
5806 5814 ddiinst = ddi_get_instance(dip);
5807 5815 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5808 5816 port = &PPORT;
5809 5817
5810 5818 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5811 5819 "fca_power: comp=%x level=%x", comp, level);
5812 5820
5813 5821 if (hba == NULL || comp != EMLXS_PM_ADAPTER) {
5814 5822 return (DDI_FAILURE);
5815 5823 }
5816 5824
5817 5825 mutex_enter(&EMLXS_PM_LOCK);
5818 5826
5819 5827 /* If we are already at the proper level then return success */
5820 5828 if (hba->pm_level == level) {
5821 5829 mutex_exit(&EMLXS_PM_LOCK);
5822 5830 return (DDI_SUCCESS);
5823 5831 }
5824 5832
5825 5833 switch (level) {
5826 5834 case EMLXS_PM_ADAPTER_UP:
5827 5835
5828 5836 /*
5829 5837 * If we are already in emlxs_attach,
5830 5838 * let emlxs_hba_attach take care of things
5831 5839 */
5832 5840 if (hba->pm_state & EMLXS_PM_IN_ATTACH) {
5833 5841 hba->pm_level = EMLXS_PM_ADAPTER_UP;
5834 5842 break;
5835 5843 }
5836 5844
5837 5845 /* Check if adapter is suspended */
5838 5846 if (hba->pm_state & EMLXS_PM_SUSPENDED) {
5839 5847 hba->pm_level = EMLXS_PM_ADAPTER_UP;
5840 5848
5841 5849 /* Try to resume the port */
5842 5850 rval = emlxs_hba_resume(dip);
5843 5851
5844 5852 if (rval != DDI_SUCCESS) {
5845 5853 hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
5846 5854 }
5847 5855 break;
5848 5856 }
5849 5857
5850 5858 /* Set adapter up */
5851 5859 hba->pm_level = EMLXS_PM_ADAPTER_UP;
5852 5860 break;
5853 5861
5854 5862 case EMLXS_PM_ADAPTER_DOWN:
5855 5863
5856 5864
5857 5865 /*
5858 5866 * If we are already in emlxs_detach,
5859 5867 * let emlxs_hba_detach take care of things
5860 5868 */
5861 5869 if (hba->pm_state & EMLXS_PM_IN_DETACH) {
5862 5870 hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
5863 5871 break;
5864 5872 }
5865 5873
5866 5874 /* Check if adapter is not suspended */
5867 5875 if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) {
5868 5876 hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
5869 5877
5870 5878 /* Try to suspend the port */
5871 5879 rval = emlxs_hba_suspend(dip);
5872 5880
5873 5881 if (rval != DDI_SUCCESS) {
5874 5882 hba->pm_level = EMLXS_PM_ADAPTER_UP;
5875 5883 }
5876 5884
5877 5885 break;
5878 5886 }
5879 5887
5880 5888 /* Set adapter down */
5881 5889 hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
5882 5890 break;
5883 5891
5884 5892 default:
5885 5893 rval = DDI_FAILURE;
5886 5894 break;
5887 5895
5888 5896 }
5889 5897
5890 5898 mutex_exit(&EMLXS_PM_LOCK);
5891 5899
5892 5900 return (rval);
5893 5901
5894 5902 } /* emlxs_power() */
5895 5903
5896 5904
5897 5905 #ifdef EMLXS_I386
5898 5906 #ifdef S11
5899 5907 /*
5900 5908 * quiesce(9E) entry point.
5901 5909 *
5902 5910 * This function is called when the system is single-thread at hight PIL
5903 5911 * with preemption disabled. Therefore, this function must not be blocked.
5904 5912 *
5905 5913 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
5906 5914 * DDI_FAILURE indicates an error condition and should almost never happen.
5907 5915 */
5908 5916 static int
5909 5917 emlxs_quiesce(dev_info_t *dip)
5910 5918 {
5911 5919 emlxs_hba_t *hba;
5912 5920 emlxs_port_t *port;
5913 5921 int32_t ddiinst;
5914 5922 int rval = DDI_SUCCESS;
5915 5923
5916 5924 ddiinst = ddi_get_instance(dip);
5917 5925 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5918 5926 port = &PPORT;
5919 5927
5920 5928 if (hba == NULL || port == NULL) {
5921 5929 return (DDI_FAILURE);
5922 5930 }
5923 5931
5924 5932 /* The fourth arg 1 indicates the call is from quiesce */
5925 5933 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 1) == 0) {
5926 5934 return (rval);
5927 5935 } else {
5928 5936 return (DDI_FAILURE);
5929 5937 }
5930 5938
5931 5939 } /* emlxs_quiesce */
5932 5940 #endif /* S11 */
5933 5941 #endif /* EMLXS_I386 */
5934 5942
5935 5943
5936 5944 static int
5937 5945 emlxs_open(dev_t *dev_p, int32_t flag, int32_t otype, cred_t *cred_p)
5938 5946 {
5939 5947 emlxs_hba_t *hba;
5940 5948 emlxs_port_t *port;
5941 5949 int ddiinst;
5942 5950
5943 5951 ddiinst = getminor(*dev_p);
5944 5952 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
5945 5953
5946 5954 if (hba == NULL) {
5947 5955 return (ENXIO);
5948 5956 }
5949 5957
5950 5958 port = &PPORT;
5951 5959
5952 5960 if (hba->pm_state & EMLXS_PM_SUSPENDED) {
5953 5961 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
5954 5962 "open failed: Driver suspended.");
5955 5963 return (ENXIO);
5956 5964 }
5957 5965
5958 5966 if (otype != OTYP_CHR) {
5959 5967 return (EINVAL);
5960 5968 }
5961 5969
5962 5970 if (drv_priv(cred_p)) {
5963 5971 return (EPERM);
5964 5972 }
5965 5973
5966 5974 mutex_enter(&EMLXS_IOCTL_LOCK);
5967 5975
5968 5976 if (hba->ioctl_flags & EMLXS_OPEN_EXCLUSIVE) {
5969 5977 mutex_exit(&EMLXS_IOCTL_LOCK);
5970 5978 return (EBUSY);
5971 5979 }
5972 5980
5973 5981 if (flag & FEXCL) {
5974 5982 if (hba->ioctl_flags & EMLXS_OPEN) {
5975 5983 mutex_exit(&EMLXS_IOCTL_LOCK);
5976 5984 return (EBUSY);
5977 5985 }
5978 5986
5979 5987 hba->ioctl_flags |= EMLXS_OPEN_EXCLUSIVE;
5980 5988 }
5981 5989
5982 5990 hba->ioctl_flags |= EMLXS_OPEN;
5983 5991
5984 5992 mutex_exit(&EMLXS_IOCTL_LOCK);
5985 5993
5986 5994 return (0);
5987 5995
5988 5996 } /* emlxs_open() */
5989 5997
5990 5998
5991 5999 /*ARGSUSED*/
5992 6000 static int
5993 6001 emlxs_close(dev_t dev, int32_t flag, int32_t otype, cred_t *cred_p)
5994 6002 {
5995 6003 emlxs_hba_t *hba;
5996 6004 int ddiinst;
5997 6005
5998 6006 ddiinst = getminor(dev);
5999 6007 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
6000 6008
6001 6009 if (hba == NULL) {
6002 6010 return (ENXIO);
6003 6011 }
6004 6012
6005 6013 if (otype != OTYP_CHR) {
6006 6014 return (EINVAL);
6007 6015 }
6008 6016
6009 6017 mutex_enter(&EMLXS_IOCTL_LOCK);
6010 6018
6011 6019 if (!(hba->ioctl_flags & EMLXS_OPEN)) {
6012 6020 mutex_exit(&EMLXS_IOCTL_LOCK);
6013 6021 return (ENODEV);
6014 6022 }
6015 6023
6016 6024 hba->ioctl_flags &= ~EMLXS_OPEN;
6017 6025 hba->ioctl_flags &= ~EMLXS_OPEN_EXCLUSIVE;
6018 6026
6019 6027 mutex_exit(&EMLXS_IOCTL_LOCK);
6020 6028
6021 6029 return (0);
6022 6030
6023 6031 } /* emlxs_close() */
6024 6032
6025 6033
6026 6034 /*ARGSUSED*/
6027 6035 static int
6028 6036 emlxs_ioctl(dev_t dev, int32_t cmd, intptr_t arg, int32_t mode,
6029 6037 cred_t *cred_p, int32_t *rval_p)
6030 6038 {
6031 6039 emlxs_hba_t *hba;
6032 6040 emlxs_port_t *port;
6033 6041 int rval = 0; /* return code */
6034 6042 int ddiinst;
6035 6043
6036 6044 ddiinst = getminor(dev);
6037 6045 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
6038 6046
6039 6047 if (hba == NULL) {
6040 6048 return (ENXIO);
6041 6049 }
6042 6050
6043 6051 port = &PPORT;
6044 6052
6045 6053 if (hba->pm_state & EMLXS_PM_SUSPENDED) {
6046 6054 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
6047 6055 "ioctl failed: Driver suspended.");
6048 6056
6049 6057 return (ENXIO);
6050 6058 }
6051 6059
6052 6060 mutex_enter(&EMLXS_IOCTL_LOCK);
6053 6061 if (!(hba->ioctl_flags & EMLXS_OPEN)) {
6054 6062 mutex_exit(&EMLXS_IOCTL_LOCK);
6055 6063 return (ENXIO);
6056 6064 }
6057 6065 mutex_exit(&EMLXS_IOCTL_LOCK);
6058 6066
6059 6067 #ifdef IDLE_TIMER
6060 6068 emlxs_pm_busy_component(hba);
6061 6069 #endif /* IDLE_TIMER */
6062 6070
6063 6071 switch (cmd) {
6064 6072 case EMLXS_DFC_COMMAND:
6065 6073 rval = emlxs_dfc_manage(hba, (void *)arg, mode);
6066 6074 break;
6067 6075
6068 6076 default:
6069 6077 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg,
6070 6078 "ioctl: Invalid command received. cmd=%x", cmd);
6071 6079 rval = EINVAL;
6072 6080 }
6073 6081
6074 6082 done:
6075 6083 return (rval);
6076 6084
6077 6085 } /* emlxs_ioctl() */
6078 6086
6079 6087
6080 6088
6081 6089 /*
6082 6090 *
6083 6091 * Device Driver Common Routines
6084 6092 *
6085 6093 */
6086 6094
6087 6095 /* EMLXS_PM_LOCK must be held for this call */
6088 6096 static int
6089 6097 emlxs_hba_resume(dev_info_t *dip)
6090 6098 {
6091 6099 emlxs_hba_t *hba;
6092 6100 emlxs_port_t *port;
6093 6101 int ddiinst;
6094 6102
6095 6103 ddiinst = ddi_get_instance(dip);
6096 6104 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
6097 6105 port = &PPORT;
6098 6106
6099 6107 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_msg, NULL);
6100 6108
6101 6109 if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) {
6102 6110 return (DDI_SUCCESS);
6103 6111 }
6104 6112
6105 6113 hba->pm_state &= ~EMLXS_PM_SUSPENDED;
6106 6114
6107 6115 /* Re-enable the physical port on this HBA */
6108 6116 port->flag |= EMLXS_PORT_ENABLED;
6109 6117
6110 6118 /* Take the adapter online */
6111 6119 if (emlxs_power_up(hba)) {
6112 6120 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_failed_msg,
6113 6121 "Unable to take adapter online.");
6114 6122
6115 6123 hba->pm_state |= EMLXS_PM_SUSPENDED;
6116 6124
6117 6125 return (DDI_FAILURE);
6118 6126 }
6119 6127
6120 6128 return (DDI_SUCCESS);
6121 6129
6122 6130 } /* emlxs_hba_resume() */
6123 6131
6124 6132
6125 6133 /* EMLXS_PM_LOCK must be held for this call */
6126 6134 static int
6127 6135 emlxs_hba_suspend(dev_info_t *dip)
6128 6136 {
6129 6137 emlxs_hba_t *hba;
6130 6138 emlxs_port_t *port;
6131 6139 int ddiinst;
6132 6140
6133 6141 ddiinst = ddi_get_instance(dip);
6134 6142 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
6135 6143 port = &PPORT;
6136 6144
6137 6145 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_msg, NULL);
6138 6146
6139 6147 if (hba->pm_state & EMLXS_PM_SUSPENDED) {
6140 6148 return (DDI_SUCCESS);
6141 6149 }
6142 6150
6143 6151 hba->pm_state |= EMLXS_PM_SUSPENDED;
6144 6152
6145 6153 /* Take the adapter offline */
6146 6154 if (emlxs_power_down(hba)) {
6147 6155 hba->pm_state &= ~EMLXS_PM_SUSPENDED;
6148 6156
6149 6157 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_failed_msg,
6150 6158 "Unable to take adapter offline.");
6151 6159
6152 6160 return (DDI_FAILURE);
6153 6161 }
6154 6162
6155 6163 return (DDI_SUCCESS);
6156 6164
6157 6165 } /* emlxs_hba_suspend() */
6158 6166
6159 6167
6160 6168
6161 6169 static void
6162 6170 emlxs_lock_init(emlxs_hba_t *hba)
6163 6171 {
6164 6172 emlxs_port_t *port = &PPORT;
6165 6173 uint32_t i;
6166 6174
6167 6175 /* Initialize the power management */
6168 6176 mutex_init(&EMLXS_PM_LOCK, NULL, MUTEX_DRIVER,
6169 6177 DDI_INTR_PRI(hba->intr_arg));
6170 6178
6171 6179 mutex_init(&EMLXS_TIMER_LOCK, NULL, MUTEX_DRIVER,
6172 6180 DDI_INTR_PRI(hba->intr_arg));
6173 6181
6174 6182 cv_init(&hba->timer_lock_cv, NULL, CV_DRIVER, NULL);
6175 6183
6176 6184 mutex_init(&EMLXS_PORT_LOCK, NULL, MUTEX_DRIVER,
6177 6185 DDI_INTR_PRI(hba->intr_arg));
6178 6186
6179 6187 mutex_init(&EMLXS_MBOX_LOCK, NULL, MUTEX_DRIVER,
6180 6188 DDI_INTR_PRI(hba->intr_arg));
6181 6189
6182 6190 cv_init(&EMLXS_MBOX_CV, NULL, CV_DRIVER, NULL);
6183 6191
6184 6192 mutex_init(&EMLXS_LINKUP_LOCK, NULL, MUTEX_DRIVER,
6185 6193 DDI_INTR_PRI(hba->intr_arg));
6186 6194
6187 6195 cv_init(&EMLXS_LINKUP_CV, NULL, CV_DRIVER, NULL);
6188 6196
6189 6197 mutex_init(&EMLXS_TX_CHANNEL_LOCK, NULL, MUTEX_DRIVER,
6190 6198 DDI_INTR_PRI(hba->intr_arg));
6191 6199
6192 6200 for (i = 0; i < MAX_RINGS; i++) {
6193 6201 mutex_init(&EMLXS_CMD_RING_LOCK(i), NULL, MUTEX_DRIVER,
6194 6202 DDI_INTR_PRI(hba->intr_arg));
6195 6203 }
6196 6204
6197 6205
6198 6206 for (i = 0; i < EMLXS_MAX_WQS; i++) {
6199 6207 mutex_init(&EMLXS_QUE_LOCK(i), NULL, MUTEX_DRIVER,
6200 6208 DDI_INTR_PRI(hba->intr_arg));
6201 6209 }
6202 6210
6203 6211 mutex_init(&EMLXS_MSIID_LOCK, NULL, MUTEX_DRIVER,
6204 6212 DDI_INTR_PRI(hba->intr_arg));
6205 6213
6206 6214 mutex_init(&EMLXS_FCTAB_LOCK, NULL, MUTEX_DRIVER,
6207 6215 DDI_INTR_PRI(hba->intr_arg));
6208 6216
6209 6217 mutex_init(&EMLXS_MEMGET_LOCK, NULL, MUTEX_DRIVER,
6210 6218 DDI_INTR_PRI(hba->intr_arg));
6211 6219
6212 6220 mutex_init(&EMLXS_MEMPUT_LOCK, NULL, MUTEX_DRIVER,
6213 6221 DDI_INTR_PRI(hba->intr_arg));
6214 6222
6215 6223 mutex_init(&EMLXS_IOCTL_LOCK, NULL, MUTEX_DRIVER,
6216 6224 DDI_INTR_PRI(hba->intr_arg));
6217 6225
6218 6226 #ifdef DUMP_SUPPORT
6219 6227 mutex_init(&EMLXS_DUMP_LOCK, NULL, MUTEX_DRIVER,
6220 6228 DDI_INTR_PRI(hba->intr_arg));
6221 6229 #endif /* DUMP_SUPPORT */
6222 6230
6223 6231 mutex_init(&EMLXS_SPAWN_LOCK, NULL, MUTEX_DRIVER,
6224 6232 DDI_INTR_PRI(hba->intr_arg));
6225 6233
6226 6234 /* Create per port locks */
6227 6235 for (i = 0; i < MAX_VPORTS; i++) {
6228 6236 port = &VPORT(i);
6229 6237
6230 6238 rw_init(&port->node_rwlock, NULL, RW_DRIVER, NULL);
6231 6239
6232 6240 if (i == 0) {
6233 6241 mutex_init(&EMLXS_PKT_LOCK, NULL, MUTEX_DRIVER,
6234 6242 DDI_INTR_PRI(hba->intr_arg));
6235 6243
6236 6244 cv_init(&EMLXS_PKT_CV, NULL, CV_DRIVER, NULL);
6237 6245
6238 6246 mutex_init(&EMLXS_UB_LOCK, NULL, MUTEX_DRIVER,
6239 6247 DDI_INTR_PRI(hba->intr_arg));
6240 6248 } else {
6241 6249 mutex_init(&EMLXS_PKT_LOCK, NULL, MUTEX_DRIVER,
6242 6250 DDI_INTR_PRI(hba->intr_arg));
6243 6251
6244 6252 cv_init(&EMLXS_PKT_CV, NULL, CV_DRIVER, NULL);
6245 6253
6246 6254 mutex_init(&EMLXS_UB_LOCK, NULL, MUTEX_DRIVER,
6247 6255 DDI_INTR_PRI(hba->intr_arg));
6248 6256 }
6249 6257 }
6250 6258
6251 6259 return;
6252 6260
6253 6261 } /* emlxs_lock_init() */
6254 6262
6255 6263
6256 6264
6257 6265 static void
6258 6266 emlxs_lock_destroy(emlxs_hba_t *hba)
6259 6267 {
6260 6268 emlxs_port_t *port = &PPORT;
6261 6269 uint32_t i;
6262 6270
6263 6271 mutex_destroy(&EMLXS_TIMER_LOCK);
6264 6272 cv_destroy(&hba->timer_lock_cv);
6265 6273
6266 6274 mutex_destroy(&EMLXS_PORT_LOCK);
6267 6275
6268 6276 cv_destroy(&EMLXS_MBOX_CV);
6269 6277 cv_destroy(&EMLXS_LINKUP_CV);
6270 6278
6271 6279 mutex_destroy(&EMLXS_LINKUP_LOCK);
6272 6280 mutex_destroy(&EMLXS_MBOX_LOCK);
6273 6281
6274 6282 mutex_destroy(&EMLXS_TX_CHANNEL_LOCK);
6275 6283
6276 6284 for (i = 0; i < MAX_RINGS; i++) {
6277 6285 mutex_destroy(&EMLXS_CMD_RING_LOCK(i));
6278 6286 }
6279 6287
6280 6288 for (i = 0; i < EMLXS_MAX_WQS; i++) {
6281 6289 mutex_destroy(&EMLXS_QUE_LOCK(i));
6282 6290 }
6283 6291
6284 6292 mutex_destroy(&EMLXS_MSIID_LOCK);
6285 6293
6286 6294 mutex_destroy(&EMLXS_FCTAB_LOCK);
6287 6295 mutex_destroy(&EMLXS_MEMGET_LOCK);
6288 6296 mutex_destroy(&EMLXS_MEMPUT_LOCK);
6289 6297 mutex_destroy(&EMLXS_IOCTL_LOCK);
6290 6298 mutex_destroy(&EMLXS_SPAWN_LOCK);
6291 6299 mutex_destroy(&EMLXS_PM_LOCK);
6292 6300
6293 6301 #ifdef DUMP_SUPPORT
6294 6302 mutex_destroy(&EMLXS_DUMP_LOCK);
6295 6303 #endif /* DUMP_SUPPORT */
6296 6304
6297 6305 /* Destroy per port locks */
6298 6306 for (i = 0; i < MAX_VPORTS; i++) {
6299 6307 port = &VPORT(i);
6300 6308 rw_destroy(&port->node_rwlock);
6301 6309 mutex_destroy(&EMLXS_PKT_LOCK);
6302 6310 cv_destroy(&EMLXS_PKT_CV);
6303 6311 mutex_destroy(&EMLXS_UB_LOCK);
6304 6312 }
6305 6313
6306 6314 return;
6307 6315
6308 6316 } /* emlxs_lock_destroy() */
6309 6317
6310 6318
6311 6319 /* init_flag values */
6312 6320 #define ATTACH_SOFT_STATE 0x00000001
6313 6321 #define ATTACH_FCA_TRAN 0x00000002
6314 6322 #define ATTACH_HBA 0x00000004
6315 6323 #define ATTACH_LOG 0x00000008
6316 6324 #define ATTACH_MAP_BUS 0x00000010
6317 6325 #define ATTACH_INTR_INIT 0x00000020
6318 6326 #define ATTACH_PROP 0x00000040
6319 6327 #define ATTACH_LOCK 0x00000080
6320 6328 #define ATTACH_THREAD 0x00000100
6321 6329 #define ATTACH_INTR_ADD 0x00000200
6322 6330 #define ATTACH_ONLINE 0x00000400
6323 6331 #define ATTACH_NODE 0x00000800
6324 6332 #define ATTACH_FCT 0x00001000
6325 6333 #define ATTACH_FCA 0x00002000
6326 6334 #define ATTACH_KSTAT 0x00004000
6327 6335 #define ATTACH_DHCHAP 0x00008000
6328 6336 #define ATTACH_FM 0x00010000
6329 6337 #define ATTACH_MAP_SLI 0x00020000
6330 6338 #define ATTACH_SPAWN 0x00040000
6331 6339 #define ATTACH_EVENTS 0x00080000
6332 6340
6333 6341 static void
6334 6342 emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, uint32_t failed)
6335 6343 {
6336 6344 emlxs_hba_t *hba = NULL;
6337 6345 int ddiinst;
6338 6346
6339 6347 ddiinst = ddi_get_instance(dip);
6340 6348
6341 6349 if (init_flag & ATTACH_HBA) {
6342 6350 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
6343 6351
6344 6352 if (init_flag & ATTACH_SPAWN) {
6345 6353 emlxs_thread_spawn_destroy(hba);
6346 6354 }
6347 6355
6348 6356 if (init_flag & ATTACH_EVENTS) {
6349 6357 (void) emlxs_event_queue_destroy(hba);
6350 6358 }
6351 6359
6352 6360 if (init_flag & ATTACH_ONLINE) {
6353 6361 (void) emlxs_offline(hba, 1);
6354 6362 }
6355 6363
6356 6364 if (init_flag & ATTACH_INTR_ADD) {
6357 6365 (void) EMLXS_INTR_REMOVE(hba);
6358 6366 }
6359 6367 #ifdef SFCT_SUPPORT
6360 6368 if (init_flag & ATTACH_FCT) {
6361 6369 emlxs_fct_detach(hba);
6362 6370 emlxs_fct_modclose();
6363 6371 }
6364 6372 #endif /* SFCT_SUPPORT */
6365 6373
6366 6374 #ifdef DHCHAP_SUPPORT
6367 6375 if (init_flag & ATTACH_DHCHAP) {
6368 6376 emlxs_dhc_detach(hba);
6369 6377 }
6370 6378 #endif /* DHCHAP_SUPPORT */
6371 6379
6372 6380 if (init_flag & ATTACH_KSTAT) {
6373 6381 kstat_delete(hba->kstat);
6374 6382 }
6375 6383
6376 6384 if (init_flag & ATTACH_FCA) {
6377 6385 emlxs_fca_detach(hba);
6378 6386 }
6379 6387
6380 6388 if (init_flag & ATTACH_NODE) {
6381 6389 (void) ddi_remove_minor_node(hba->dip, "devctl");
6382 6390 }
6383 6391
6384 6392 if (init_flag & ATTACH_THREAD) {
6385 6393 emlxs_thread_destroy(&hba->iodone_thread);
6386 6394 }
6387 6395
6388 6396 if (init_flag & ATTACH_PROP) {
6389 6397 (void) ddi_prop_remove_all(hba->dip);
6390 6398 }
6391 6399
6392 6400 if (init_flag & ATTACH_LOCK) {
6393 6401 emlxs_lock_destroy(hba);
6394 6402 }
6395 6403
6396 6404 if (init_flag & ATTACH_INTR_INIT) {
6397 6405 (void) EMLXS_INTR_UNINIT(hba);
6398 6406 }
6399 6407
6400 6408 if (init_flag & ATTACH_MAP_BUS) {
6401 6409 emlxs_unmap_bus(hba);
6402 6410 }
6403 6411
6404 6412 if (init_flag & ATTACH_MAP_SLI) {
6405 6413 EMLXS_SLI_UNMAP_HDW(hba);
6406 6414 }
6407 6415
6408 6416 #ifdef FMA_SUPPORT
6409 6417 if (init_flag & ATTACH_FM) {
6410 6418 emlxs_fm_fini(hba);
6411 6419 }
6412 6420 #endif /* FMA_SUPPORT */
6413 6421
6414 6422 if (init_flag & ATTACH_LOG) {
6415 6423 emlxs_msg_log_destroy(hba);
6416 6424 }
6417 6425
6418 6426 if (init_flag & ATTACH_FCA_TRAN) {
6419 6427 (void) ddi_set_driver_private(hba->dip, NULL);
6420 6428 kmem_free(hba->fca_tran, sizeof (fc_fca_tran_t));
6421 6429 hba->fca_tran = NULL;
6422 6430 }
6423 6431
6424 6432 if (init_flag & ATTACH_HBA) {
6425 6433 emlxs_device.log[hba->emlxinst] = 0;
6426 6434 emlxs_device.hba[hba->emlxinst] =
6427 6435 (emlxs_hba_t *)((unsigned long)((failed) ? -1 : 0));
6428 6436 #ifdef DUMP_SUPPORT
6429 6437 emlxs_device.dump_txtfile[hba->emlxinst] = 0;
6430 6438 emlxs_device.dump_dmpfile[hba->emlxinst] = 0;
6431 6439 emlxs_device.dump_ceefile[hba->emlxinst] = 0;
6432 6440 #endif /* DUMP_SUPPORT */
6433 6441
6434 6442 }
6435 6443 }
6436 6444
6437 6445 if (init_flag & ATTACH_SOFT_STATE) {
6438 6446 (void) ddi_soft_state_free(emlxs_soft_state, ddiinst);
6439 6447 }
6440 6448
6441 6449 return;
6442 6450
6443 6451 } /* emlxs_driver_remove() */
6444 6452
6445 6453
6446 6454 /* This determines which ports will be initiator mode */
6447 6455 static uint32_t
6448 6456 emlxs_fca_init(emlxs_hba_t *hba)
6449 6457 {
6450 6458 emlxs_port_t *port = &PPORT;
6451 6459
6452 6460 /* Check if SFS present */
6453 6461 if (((void *)MODSYM(fc_fca_init) == NULL) ||
6454 6462 ((void *)MODSYM(fc_fca_attach) == NULL)) {
6455 6463 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6456 6464 "SFS not present.");
6457 6465 return (1);
6458 6466 }
6459 6467
6460 6468 /* Check if our SFS driver interface matches the current SFS stack */
6461 6469 if (MODSYM(fc_fca_attach) (hba->dip, hba->fca_tran) != DDI_SUCCESS) {
6462 6470 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6463 6471 "SFS/FCA version mismatch. FCA=0x%x",
6464 6472 hba->fca_tran->fca_version);
6465 6473 return (1);
6466 6474 }
6467 6475
6468 6476 return (0);
6469 6477
6470 6478 } /* emlxs_fca_init() */
6471 6479
6472 6480
6473 6481 /* This determines which ports will be initiator or target mode */
6474 6482 static void
6475 6483 emlxs_mode_init(emlxs_hba_t *hba)
6476 6484 {
6477 6485 emlxs_port_t *port = &PPORT;
6478 6486 emlxs_config_t *cfg = &CFG;
6479 6487 emlxs_port_t *vport;
6480 6488 uint32_t i;
6481 6489 uint32_t mode_mask;
6482 6490
6483 6491 /* Initialize mode masks */
6484 6492 (void) emlxs_mode_init_masks(hba);
6485 6493
6486 6494 if (!(port->mode_mask & MODE_INITIATOR)) {
6487 6495 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6488 6496 "Initiator mode not enabled.");
6489 6497
6490 6498 #ifdef SFCT_SUPPORT
6491 6499 /* Disable dynamic target mode */
6492 6500 cfg[CFG_DTM_ENABLE].current = 0;
6493 6501 #endif /* SFCT_SUPPORT */
6494 6502
6495 6503 goto done1;
6496 6504 }
6497 6505
6498 6506 /* Try to initialize fca interface */
6499 6507 if (emlxs_fca_init(hba) != 0) {
6500 6508 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6501 6509 "Initiator mode disabled.");
6502 6510
6503 6511 /* Disable initiator mode */
6504 6512 port->mode_mask &= ~MODE_INITIATOR;
6505 6513
6506 6514 #ifdef SFCT_SUPPORT
6507 6515 /* Disable dynamic target mode */
6508 6516 cfg[CFG_DTM_ENABLE].current = 0;
6509 6517 #endif /* SFCT_SUPPORT */
6510 6518
6511 6519 goto done1;
6512 6520 }
6513 6521
6514 6522 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6515 6523 "Initiator mode enabled.");
6516 6524
6517 6525 done1:
6518 6526
6519 6527 #ifdef SFCT_SUPPORT
6520 6528 if (!(port->mode_mask & MODE_TARGET)) {
6521 6529 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6522 6530 "Target mode not enabled.");
6523 6531
6524 6532 /* Disable target modes */
6525 6533 cfg[CFG_DTM_ENABLE].current = 0;
6526 6534 cfg[CFG_TARGET_MODE].current = 0;
6527 6535
6528 6536 goto done2;
6529 6537 }
6530 6538
6531 6539 /* Try to open the COMSTAR module */
6532 6540 if (emlxs_fct_modopen() != 0) {
6533 6541 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6534 6542 "Target mode disabled.");
6535 6543
6536 6544 /* Disable target modes */
6537 6545 port->mode_mask &= ~MODE_TARGET;
6538 6546 cfg[CFG_DTM_ENABLE].current = 0;
6539 6547 cfg[CFG_TARGET_MODE].current = 0;
6540 6548
6541 6549 goto done2;
6542 6550 }
6543 6551
6544 6552 /* Try to initialize fct interface */
6545 6553 if (emlxs_fct_init(hba) != 0) {
6546 6554 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6547 6555 "Target mode disabled.");
6548 6556
6549 6557 /* Disable target modes */
6550 6558 port->mode_mask &= ~MODE_TARGET;
6551 6559 cfg[CFG_DTM_ENABLE].current = 0;
6552 6560 cfg[CFG_TARGET_MODE].current = 0;
6553 6561
6554 6562 goto done2;
6555 6563 }
6556 6564
6557 6565 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6558 6566 "Target mode enabled.");
6559 6567
6560 6568 done2:
6561 6569 /* Adjust target mode parameter flags */
6562 6570 if (cfg[CFG_DTM_ENABLE].current) {
6563 6571 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6564 6572 "Dynamic target mode enabled.");
6565 6573
6566 6574 cfg[CFG_TARGET_MODE].flags |= PARM_DYNAMIC;
6567 6575 } else {
6568 6576 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6569 6577 "Dynamic target mode disabled.");
6570 6578
6571 6579 cfg[CFG_TARGET_MODE].flags &= ~PARM_DYNAMIC;
6572 6580 }
6573 6581 #endif /* SFCT_SUPPORT */
6574 6582
6575 6583 /* Now set port flags */
6576 6584 mutex_enter(&EMLXS_PORT_LOCK);
6577 6585
6578 6586 /* Set flags for physical port */
6579 6587 if (port->mode_mask & MODE_INITIATOR) {
6580 6588 port->flag |= EMLXS_INI_ENABLED;
6581 6589 } else {
6582 6590 port->flag &= ~EMLXS_INI_ENABLED;
6583 6591 }
6584 6592
6585 6593 if (port->mode_mask & MODE_TARGET) {
6586 6594 port->flag |= EMLXS_TGT_ENABLED;
6587 6595 } else {
6588 6596 port->flag &= ~EMLXS_TGT_ENABLED;
6589 6597 }
6590 6598
6591 6599 for (i = 1; i < MAX_VPORTS; i++) {
6592 6600 vport = &VPORT(i);
6593 6601
6594 6602 /* Physical port mask has only allowable bits */
6595 6603 mode_mask = vport->mode_mask & port->mode_mask;
6596 6604
6597 6605 /* Set flags for physical port */
6598 6606 if (mode_mask & MODE_INITIATOR) {
6599 6607 vport->flag |= EMLXS_INI_ENABLED;
6600 6608 } else {
6601 6609 vport->flag &= ~EMLXS_INI_ENABLED;
6602 6610 }
6603 6611
6604 6612 if (mode_mask & MODE_TARGET) {
6605 6613 vport->flag |= EMLXS_TGT_ENABLED;
6606 6614 } else {
6607 6615 vport->flag &= ~EMLXS_TGT_ENABLED;
6608 6616 }
6609 6617 }
6610 6618
6611 6619 /* Set initial driver mode */
6612 6620 emlxs_mode_set(hba);
6613 6621
6614 6622 mutex_exit(&EMLXS_PORT_LOCK);
6615 6623
6616 6624 /* Recheck possible mode dependent parameters */
6617 6625 /* in case conditions have changed. */
6618 6626 if (port->mode != MODE_NONE) {
6619 6627 for (i = 0; i < NUM_CFG_PARAM; i++) {
6620 6628 cfg = &hba->config[i];
6621 6629 cfg->current = emlxs_check_parm(hba, i, cfg->current);
6622 6630 }
6623 6631 }
6624 6632
6625 6633 return;
6626 6634
6627 6635 } /* emlxs_mode_init() */
6628 6636
6629 6637
6630 6638 /* This must be called while holding the EMLXS_PORT_LOCK */
6631 6639 extern void
6632 6640 emlxs_mode_set(emlxs_hba_t *hba)
6633 6641 {
6634 6642 emlxs_port_t *port = &PPORT;
6635 6643 #ifdef SFCT_SUPPORT
6636 6644 emlxs_config_t *cfg = &CFG;
6637 6645 #endif /* SFCT_SUPPORT */
6638 6646 emlxs_port_t *vport;
6639 6647 uint32_t i;
6640 6648 uint32_t cfg_tgt_mode = 0;
6641 6649
6642 6650 /* mutex_enter(&EMLXS_PORT_LOCK); */
6643 6651
6644 6652 #ifdef SFCT_SUPPORT
6645 6653 cfg_tgt_mode = cfg[CFG_TARGET_MODE].current;
6646 6654 #endif /* SFCT_SUPPORT */
6647 6655
6648 6656 /* Initiator mode requested */
6649 6657 if (!cfg_tgt_mode) {
6650 6658 for (i = 0; i < MAX_VPORTS; i++) {
6651 6659 vport = &VPORT(i);
6652 6660 vport->mode = (vport->flag & EMLXS_INI_ENABLED)?
6653 6661 MODE_INITIATOR:MODE_NONE;
6654 6662 }
6655 6663 #ifdef SFCT_SUPPORT
6656 6664 /* Target mode requested */
6657 6665 } else {
6658 6666 for (i = 0; i < MAX_VPORTS; i++) {
6659 6667 vport = &VPORT(i);
6660 6668 vport->mode = (vport->flag & EMLXS_TGT_ENABLED)?
6661 6669 MODE_TARGET:MODE_NONE;
6662 6670 }
6663 6671 #endif /* SFCT_SUPPORT */
6664 6672 }
6665 6673
6666 6674 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
6667 6675 "MODE: %s", emlxs_mode_xlate(port->mode));
6668 6676
6669 6677 /* mutex_exit(&EMLXS_PORT_LOCK); */
6670 6678
6671 6679 return;
6672 6680
6673 6681 } /* emlxs_mode_set() */
6674 6682
6675 6683
6676 6684 static void
6677 6685 emlxs_mode_init_masks(emlxs_hba_t *hba)
6678 6686 {
6679 6687 emlxs_port_t *port = &PPORT;
6680 6688 emlxs_port_t *vport;
6681 6689 uint32_t i;
6682 6690
6683 6691 #ifdef SFCT_SUPPORT
6684 6692 emlxs_config_t *cfg = &CFG;
6685 6693 uint32_t vport_mode_mask;
6686 6694 uint32_t cfg_vport_mode_mask;
6687 6695 uint32_t mode_mask;
6688 6696 char string[256];
6689 6697
6690 6698 port->mode_mask = 0;
6691 6699
6692 6700 if (!cfg[CFG_TARGET_MODE].current ||
6693 6701 cfg[CFG_DTM_ENABLE].current) {
6694 6702 port->mode_mask |= MODE_INITIATOR;
6695 6703 }
6696 6704
6697 6705 if (cfg[CFG_TARGET_MODE].current ||
6698 6706 cfg[CFG_DTM_ENABLE].current) {
6699 6707 port->mode_mask |= MODE_TARGET;
6700 6708 }
6701 6709
6702 6710 /* Physical port mask has only allowable bits */
6703 6711 vport_mode_mask = port->mode_mask;
6704 6712 cfg_vport_mode_mask = cfg[CFG_VPORT_MODE_MASK].current;
6705 6713
6706 6714 /* Check dynamic target mode value for virtual ports */
6707 6715 if (cfg[CFG_DTM_ENABLE].current == 0) {
6708 6716 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6709 6717 "%s = 0: Virtual target ports are not supported.",
6710 6718 cfg[CFG_DTM_ENABLE].string);
6711 6719
6712 6720 vport_mode_mask &= ~MODE_TARGET;
6713 6721 }
6714 6722
6715 6723 cfg_vport_mode_mask &= vport_mode_mask;
6716 6724
6717 6725 if (cfg[CFG_VPORT_MODE_MASK].current != cfg_vport_mode_mask) {
6718 6726 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6719 6727 "%s: Changing 0x%x --> 0x%x",
6720 6728 cfg[CFG_VPORT_MODE_MASK].string,
6721 6729 cfg[CFG_VPORT_MODE_MASK].current,
6722 6730 cfg_vport_mode_mask);
6723 6731
6724 6732 cfg[CFG_VPORT_MODE_MASK].current = cfg_vport_mode_mask;
6725 6733 }
6726 6734
6727 6735 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6728 6736 "pport-mode-mask: %s", emlxs_mode_xlate(port->mode_mask));
6729 6737
6730 6738 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6731 6739 "vport-mode-mask: %s", emlxs_mode_xlate(cfg_vport_mode_mask));
6732 6740
6733 6741 for (i = 1; i < MAX_VPORTS; i++) {
6734 6742 vport = &VPORT(i);
6735 6743
6736 6744 (void) snprintf(string, sizeof (string),
6737 6745 "%s%d-vport%d-mode-mask", DRIVER_NAME, hba->ddiinst, i);
6738 6746
6739 6747 mode_mask = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
6740 6748 (void *)hba->dip, DDI_PROP_DONTPASS, string,
6741 6749 cfg_vport_mode_mask);
6742 6750
6743 6751 vport->mode_mask = mode_mask & vport_mode_mask;
6744 6752
6745 6753 if (vport->mode_mask != cfg_vport_mode_mask) {
6746 6754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
6747 6755 "vport%d-mode-mask: %s",
6748 6756 i, emlxs_mode_xlate(vport->mode_mask));
6749 6757 }
6750 6758 }
6751 6759 #else
6752 6760 port->mode_mask = MODE_INITIATOR;
6753 6761 for (i = 1; i < MAX_VPORTS; i++) {
6754 6762 vport = &VPORT(i);
6755 6763 vport->mode_mask = MODE_INITIATOR;
6756 6764 }
6757 6765 #endif /* SFCT_SUPPORT */
6758 6766
6759 6767 return;
6760 6768
6761 6769 } /* emlxs_mode_init_masks() */
6762 6770
6763 6771
6764 6772 static void
6765 6773 emlxs_fca_attach(emlxs_hba_t *hba)
6766 6774 {
6767 6775 emlxs_port_t *port;
6768 6776 uint32_t i;
6769 6777
6770 6778 /* Update our transport structure */
6771 6779 hba->fca_tran->fca_iblock = (ddi_iblock_cookie_t *)&hba->intr_arg;
6772 6780 hba->fca_tran->fca_cmd_max = hba->io_throttle;
6773 6781
6774 6782 for (i = 0; i < MAX_VPORTS; i++) {
6775 6783 port = &VPORT(i);
6776 6784 port->ub_count = EMLXS_UB_TOKEN_OFFSET;
6777 6785 port->ub_pool = NULL;
6778 6786 }
6779 6787
6780 6788 #if (EMLXS_MODREV >= EMLXS_MODREV5)
6781 6789 bcopy((caddr_t)&hba->wwpn, (caddr_t)&hba->fca_tran->fca_perm_pwwn,
6782 6790 sizeof (NAME_TYPE));
6783 6791 #endif /* >= EMLXS_MODREV5 */
6784 6792
6785 6793 return;
6786 6794
6787 6795 } /* emlxs_fca_attach() */
6788 6796
6789 6797
6790 6798 static void
6791 6799 emlxs_fca_detach(emlxs_hba_t *hba)
6792 6800 {
6793 6801 emlxs_port_t *port = &PPORT;
6794 6802 uint32_t i;
6795 6803 emlxs_port_t *vport;
6796 6804
6797 6805 if (!(port->flag & EMLXS_INI_ENABLED)) {
6798 6806 return;
6799 6807 }
6800 6808
6801 6809 if ((void *)MODSYM(fc_fca_detach) != NULL) {
6802 6810 MODSYM(fc_fca_detach)(hba->dip);
6803 6811 }
6804 6812
6805 6813 /* Disable INI mode for all ports */
6806 6814 for (i = 0; i < MAX_VPORTS; i++) {
6807 6815 vport = &VPORT(i);
6808 6816 vport->flag &= ~EMLXS_INI_ENABLED;
6809 6817 }
6810 6818
6811 6819 return;
6812 6820
6813 6821 } /* emlxs_fca_detach() */
6814 6822
6815 6823
6816 6824 static void
6817 6825 emlxs_drv_banner(emlxs_hba_t *hba)
6818 6826 {
6819 6827 emlxs_port_t *port = &PPORT;
6820 6828 uint32_t i;
6821 6829 char sli_mode[16];
6822 6830 char msi_mode[16];
6823 6831 char npiv_mode[16];
6824 6832 emlxs_vpd_t *vpd = &VPD;
6825 6833 uint8_t *wwpn;
6826 6834 uint8_t *wwnn;
6827 6835 uint32_t fw_show = 0;
6828 6836
6829 6837 /* Display firmware library one time for all driver instances */
6830 6838 mutex_enter(&emlxs_device.lock);
6831 6839 if (!(emlxs_instance_flag & EMLXS_FW_SHOW)) {
6832 6840 emlxs_instance_flag |= EMLXS_FW_SHOW;
6833 6841 fw_show = 1;
6834 6842 }
6835 6843 mutex_exit(&emlxs_device.lock);
6836 6844
6837 6845 if (fw_show) {
6838 6846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s",
6839 6847 emlxs_copyright);
6840 6848 emlxs_fw_show(hba);
6841 6849 }
6842 6850
6843 6851 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s (%s)", emlxs_label,
6844 6852 emlxs_revision);
6845 6853
6846 6854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
6847 6855 "%s Dev_id:%x Sub_id:%x Id:%d", hba->model_info.model,
6848 6856 hba->model_info.device_id, hba->model_info.ssdid,
6849 6857 hba->model_info.id);
6850 6858
6851 6859 #ifdef EMLXS_I386
6852 6860
6853 6861 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
6854 6862 "Firmware:%s (%s) Boot:%s", vpd->fw_version, vpd->fw_label,
6855 6863 vpd->boot_version);
6856 6864
6857 6865 #else /* EMLXS_SPARC */
6858 6866
6859 6867 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
6860 6868 "Firmware:%s (%s) Boot:%s Fcode:%s", vpd->fw_version,
6861 6869 vpd->fw_label, vpd->boot_version, vpd->fcode_version);
6862 6870
6863 6871 #endif /* EMLXS_I386 */
6864 6872
6865 6873 if (hba->sli_mode > 3) {
6866 6874 (void) snprintf(sli_mode, sizeof (sli_mode), "SLI:%d(%s)",
6867 6875 hba->sli_mode,
6868 6876 ((hba->flag & FC_FIP_SUPPORTED) ? "FIP" : "nonFIP"));
6869 6877 } else {
6870 6878 (void) snprintf(sli_mode, sizeof (sli_mode), "SLI:%d",
6871 6879 hba->sli_mode);
6872 6880 }
6873 6881
6874 6882 (void) strlcpy(msi_mode, " INTX:1", sizeof (msi_mode));
6875 6883
6876 6884 #ifdef MSI_SUPPORT
6877 6885 if (hba->intr_flags & EMLXS_MSI_ENABLED) {
6878 6886 switch (hba->intr_type) {
6879 6887 case DDI_INTR_TYPE_FIXED:
6880 6888 (void) strlcpy(msi_mode, " MSI:0", sizeof (msi_mode));
6881 6889 break;
6882 6890
6883 6891 case DDI_INTR_TYPE_MSI:
6884 6892 (void) snprintf(msi_mode, sizeof (msi_mode), " MSI:%d",
6885 6893 hba->intr_count);
6886 6894 break;
6887 6895
6888 6896 case DDI_INTR_TYPE_MSIX:
6889 6897 (void) snprintf(msi_mode, sizeof (msi_mode), " MSIX:%d",
6890 6898 hba->intr_count);
6891 6899 break;
6892 6900 }
6893 6901 }
6894 6902 #endif /* MSI_SUPPORT */
6895 6903
6896 6904 (void) strlcpy(npiv_mode, "", sizeof (npiv_mode));
6897 6905
6898 6906 if (hba->flag & FC_NPIV_ENABLED) {
6899 6907 (void) snprintf(npiv_mode, sizeof (npiv_mode), " NPIV:%d",
6900 6908 hba->vpi_max+1);
6901 6909 } else {
6902 6910 (void) strlcpy(npiv_mode, " NPIV:0", sizeof (npiv_mode));
6903 6911 }
6904 6912
6905 6913 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
6906 6914 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s%s%s%s%s%s",
6907 6915 sli_mode, msi_mode, npiv_mode,
6908 6916 ((port->flag & EMLXS_INI_ENABLED)? " FCA":""),
6909 6917 ((port->flag & EMLXS_TGT_ENABLED)? " FCT":""),
6910 6918 ((SLI4_FCOE_MODE)? " FCoE":" FC"));
6911 6919 } else {
6912 6920 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s%s%s%s%s",
6913 6921 sli_mode, msi_mode, npiv_mode,
6914 6922 ((port->flag & EMLXS_INI_ENABLED)? " FCA":""),
6915 6923 ((port->flag & EMLXS_TGT_ENABLED)? " FCT":""));
6916 6924 }
6917 6925
6918 6926 wwpn = (uint8_t *)&hba->wwpn;
6919 6927 wwnn = (uint8_t *)&hba->wwnn;
6920 6928 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
6921 6929 "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X "
6922 6930 "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X",
6923 6931 wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6],
6924 6932 wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3], wwnn[4], wwnn[5],
6925 6933 wwnn[6], wwnn[7]);
6926 6934
6927 6935 for (i = 0; i < MAX_VPORTS; i++) {
6928 6936 port = &VPORT(i);
6929 6937
6930 6938 if (!(port->flag & EMLXS_PORT_CONFIG)) {
6931 6939 continue;
6932 6940 }
6933 6941
6934 6942 wwpn = (uint8_t *)&port->wwpn;
6935 6943 wwnn = (uint8_t *)&port->wwnn;
6936 6944
6937 6945 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg,
6938 6946 "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X "
6939 6947 "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X",
6940 6948 wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5],
6941 6949 wwpn[6], wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3],
6942 6950 wwnn[4], wwnn[5], wwnn[6], wwnn[7]);
6943 6951 }
6944 6952
6945 6953 /*
6946 6954 * Announce the device: ddi_report_dev() prints a banner at boot time,
6947 6955 * announcing the device pointed to by dip.
6948 6956 */
6949 6957 (void) ddi_report_dev(hba->dip);
6950 6958
6951 6959 return;
6952 6960
6953 6961 } /* emlxs_drv_banner() */
6954 6962
6955 6963
6956 6964 extern void
6957 6965 emlxs_get_fcode_version(emlxs_hba_t *hba)
6958 6966 {
6959 6967 emlxs_vpd_t *vpd = &VPD;
6960 6968 char *prop_str;
6961 6969 int status;
6962 6970
6963 6971 /* Setup fcode version property */
6964 6972 prop_str = NULL;
6965 6973 status =
6966 6974 ddi_prop_lookup_string(DDI_DEV_T_ANY, (dev_info_t *)hba->dip, 0,
6967 6975 "fcode-version", (char **)&prop_str);
6968 6976
6969 6977 if (status == DDI_PROP_SUCCESS) {
6970 6978 bcopy(prop_str, vpd->fcode_version, strlen(prop_str));
6971 6979 (void) ddi_prop_free((void *)prop_str);
6972 6980 } else {
6973 6981 (void) strncpy(vpd->fcode_version, "none",
6974 6982 (sizeof (vpd->fcode_version)-1));
6975 6983 }
6976 6984
6977 6985 return;
6978 6986
6979 6987 } /* emlxs_get_fcode_version() */
6980 6988
6981 6989
6982 6990 static int
6983 6991 emlxs_hba_attach(dev_info_t *dip)
6984 6992 {
6985 6993 emlxs_hba_t *hba;
6986 6994 emlxs_port_t *port;
6987 6995 emlxs_config_t *cfg;
6988 6996 char *prop_str;
6989 6997 int ddiinst;
6990 6998 int32_t emlxinst;
6991 6999 int status;
6992 7000 uint32_t rval;
6993 7001 uint32_t init_flag = 0;
6994 7002 char local_pm_components[32];
6995 7003 uint32_t i;
6996 7004
6997 7005 ddiinst = ddi_get_instance(dip);
6998 7006 emlxinst = emlxs_add_instance(ddiinst);
6999 7007
7000 7008 if (emlxinst >= MAX_FC_BRDS) {
7001 7009 cmn_err(CE_WARN,
7002 7010 "?%s: fca_hba_attach failed. Too many driver ddiinsts. "
7003 7011 "inst=%x", DRIVER_NAME, ddiinst);
7004 7012 return (DDI_FAILURE);
7005 7013 }
7006 7014
7007 7015 if (emlxs_device.hba[emlxinst] == (emlxs_hba_t *)-1) {
7008 7016 return (DDI_FAILURE);
7009 7017 }
7010 7018
7011 7019 if (emlxs_device.hba[emlxinst]) {
7012 7020 return (DDI_SUCCESS);
7013 7021 }
7014 7022
7015 7023 /* An adapter can accidentally be plugged into a slave-only PCI slot */
7016 7024 if (ddi_slaveonly(dip) == DDI_SUCCESS) {
7017 7025 cmn_err(CE_WARN,
7018 7026 "?%s%d: fca_hba_attach failed. Device in slave-only slot.",
7019 7027 DRIVER_NAME, ddiinst);
7020 7028 return (DDI_FAILURE);
7021 7029 }
7022 7030
7023 7031 /* Allocate emlxs_dev_ctl structure. */
7024 7032 if (ddi_soft_state_zalloc(emlxs_soft_state, ddiinst) != DDI_SUCCESS) {
7025 7033 cmn_err(CE_WARN,
7026 7034 "?%s%d: fca_hba_attach failed. Unable to allocate soft "
7027 7035 "state.", DRIVER_NAME, ddiinst);
7028 7036 return (DDI_FAILURE);
7029 7037 }
7030 7038 init_flag |= ATTACH_SOFT_STATE;
7031 7039
7032 7040 if ((hba = (emlxs_hba_t *)ddi_get_soft_state(emlxs_soft_state,
7033 7041 ddiinst)) == NULL) {
7034 7042 cmn_err(CE_WARN,
7035 7043 "?%s%d: fca_hba_attach failed. Unable to get soft state.",
7036 7044 DRIVER_NAME, ddiinst);
7037 7045 goto failed;
7038 7046 }
7039 7047 bzero((char *)hba, sizeof (emlxs_hba_t));
7040 7048
7041 7049 emlxs_device.hba[emlxinst] = hba;
7042 7050 emlxs_device.log[emlxinst] = &hba->log;
7043 7051
7044 7052 #ifdef DUMP_SUPPORT
7045 7053 emlxs_device.dump_txtfile[emlxinst] = &hba->dump_txtfile;
7046 7054 emlxs_device.dump_dmpfile[emlxinst] = &hba->dump_dmpfile;
7047 7055 emlxs_device.dump_ceefile[emlxinst] = &hba->dump_ceefile;
7048 7056 #endif /* DUMP_SUPPORT */
7049 7057
7050 7058 hba->dip = dip;
7051 7059 hba->emlxinst = emlxinst;
7052 7060 hba->ddiinst = ddiinst;
7053 7061
7054 7062 init_flag |= ATTACH_HBA;
7055 7063
7056 7064 /* Enable the physical port on this HBA */
7057 7065 port = &PPORT;
7058 7066 port->hba = hba;
7059 7067 port->vpi = 0;
7060 7068 port->flag |= EMLXS_PORT_ENABLED;
7061 7069
7062 7070 /* Allocate a transport structure */
7063 7071 hba->fca_tran =
7064 7072 (fc_fca_tran_t *)kmem_zalloc(sizeof (fc_fca_tran_t), KM_NOSLEEP);
7065 7073 if (hba->fca_tran == NULL) {
7066 7074 cmn_err(CE_WARN,
7067 7075 "?%s%d: fca_hba_attach failed. Unable to allocate fca_tran "
7068 7076 "memory.", DRIVER_NAME, ddiinst);
7069 7077 goto failed;
7070 7078 }
7071 7079 bcopy((caddr_t)&emlxs_fca_tran, (caddr_t)hba->fca_tran,
7072 7080 sizeof (fc_fca_tran_t));
7073 7081
7074 7082 /*
7075 7083 * Copy the global ddi_dma_attr to the local hba fields
7076 7084 */
7077 7085 bcopy((caddr_t)&emlxs_dma_attr, (caddr_t)&hba->dma_attr,
7078 7086 sizeof (ddi_dma_attr_t));
7079 7087 bcopy((caddr_t)&emlxs_dma_attr_ro, (caddr_t)&hba->dma_attr_ro,
7080 7088 sizeof (ddi_dma_attr_t));
7081 7089 bcopy((caddr_t)&emlxs_dma_attr_1sg, (caddr_t)&hba->dma_attr_1sg,
7082 7090 sizeof (ddi_dma_attr_t));
7083 7091 bcopy((caddr_t)&emlxs_dma_attr_fcip_rsp,
7084 7092 (caddr_t)&hba->dma_attr_fcip_rsp, sizeof (ddi_dma_attr_t));
7085 7093
7086 7094 /* Reset the fca_tran dma_attr fields to the per-hba copies */
7087 7095 hba->fca_tran->fca_dma_attr = &hba->dma_attr;
7088 7096 hba->fca_tran->fca_dma_fcp_cmd_attr = &hba->dma_attr_1sg;
7089 7097 hba->fca_tran->fca_dma_fcp_rsp_attr = &hba->dma_attr_1sg;
7090 7098 hba->fca_tran->fca_dma_fcp_data_attr = &hba->dma_attr_ro;
7091 7099 hba->fca_tran->fca_dma_fcip_cmd_attr = &hba->dma_attr_1sg;
7092 7100 hba->fca_tran->fca_dma_fcip_rsp_attr = &hba->dma_attr_fcip_rsp;
7093 7101 hba->fca_tran->fca_dma_fcsm_cmd_attr = &hba->dma_attr_1sg;
7094 7102 hba->fca_tran->fca_dma_fcsm_rsp_attr = &hba->dma_attr;
7095 7103
7096 7104 /* Set the transport structure pointer in our dip */
7097 7105 /* SFS may panic if we are in target only mode */
7098 7106 /* We will update the transport structure later */
7099 7107 (void) ddi_set_driver_private(dip, (caddr_t)&emlxs_fca_tran);
7100 7108 init_flag |= ATTACH_FCA_TRAN;
7101 7109
7102 7110 /* Perform driver integrity check */
7103 7111 rval = emlxs_integrity_check(hba);
7104 7112 if (rval) {
7105 7113 cmn_err(CE_WARN,
7106 7114 "?%s%d: fca_hba_attach failed. Driver integrity check "
7107 7115 "failed. %d error(s) found.", DRIVER_NAME, ddiinst, rval);
7108 7116 goto failed;
7109 7117 }
7110 7118
7111 7119 cfg = &CFG;
7112 7120
7113 7121 bcopy((uint8_t *)&emlxs_cfg, (uint8_t *)cfg, sizeof (emlxs_cfg));
7114 7122 #ifdef MSI_SUPPORT
7115 7123 if ((void *)&ddi_intr_get_supported_types != NULL) {
7116 7124 hba->intr_flags |= EMLXS_MSI_ENABLED;
7117 7125 }
7118 7126 #endif /* MSI_SUPPORT */
7119 7127
7120 7128
7121 7129 /* Create the msg log file */
7122 7130 if (emlxs_msg_log_create(hba) == 0) {
7123 7131 cmn_err(CE_WARN,
7124 7132 "?%s%d: fca_hba_attach failed. Unable to create message "
7125 7133 "log", DRIVER_NAME, ddiinst);
7126 7134 goto failed;
7127 7135
7128 7136 }
7129 7137 init_flag |= ATTACH_LOG;
7130 7138
7131 7139 /* We can begin to use EMLXS_MSGF from this point on */
7132 7140
7133 7141 /*
7134 7142 * Find the I/O bus type If it is not a SBUS card,
7135 7143 * then it is a PCI card. Default is PCI_FC (0).
7136 7144 */
7137 7145 prop_str = NULL;
7138 7146 status = ddi_prop_lookup_string(DDI_DEV_T_ANY,
7139 7147 (dev_info_t *)dip, 0, "name", (char **)&prop_str);
7140 7148
7141 7149 if (status == DDI_PROP_SUCCESS) {
7142 7150 if (strncmp(prop_str, "lpfs", 4) == 0) {
7143 7151 hba->bus_type = SBUS_FC;
7144 7152 }
7145 7153
7146 7154 (void) ddi_prop_free((void *)prop_str);
7147 7155 }
7148 7156
7149 7157 /*
7150 7158 * Copy DDS from the config method and update configuration parameters
7151 7159 */
7152 7160 (void) emlxs_get_props(hba);
7153 7161
7154 7162 #ifdef FMA_SUPPORT
7155 7163 hba->fm_caps = cfg[CFG_FM_CAPS].current;
7156 7164
7157 7165 emlxs_fm_init(hba);
7158 7166
7159 7167 init_flag |= ATTACH_FM;
7160 7168 #endif /* FMA_SUPPORT */
7161 7169
7162 7170 if (emlxs_map_bus(hba)) {
7163 7171 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7164 7172 "Unable to map memory");
7165 7173 goto failed;
7166 7174
7167 7175 }
7168 7176 init_flag |= ATTACH_MAP_BUS;
7169 7177
7170 7178 /* Attempt to identify the adapter */
7171 7179 rval = emlxs_init_adapter_info(hba);
7172 7180
7173 7181 if (rval == 0) {
7174 7182 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7175 7183 "Unable to get adapter info. Id:%d Device id:0x%x "
7176 7184 "Model:%s", hba->model_info.id,
7177 7185 hba->model_info.device_id, hba->model_info.model);
7178 7186 goto failed;
7179 7187 }
7180 7188 #define FILTER_ORACLE_BRANDED
7181 7189 #ifdef FILTER_ORACLE_BRANDED
7182 7190
7183 7191 /* Oracle branded adapters are not supported in this driver */
7184 7192 if (hba->model_info.flags & EMLXS_ORACLE_BRANDED) {
7185 7193 hba->model_info.flags |= EMLXS_NOT_SUPPORTED;
7186 7194 }
7187 7195 #endif /* FILTER_ORACLE_BRANDED */
7188 7196
7189 7197 /* Check if adapter is not supported */
7190 7198 if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
7191 7199 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7192 7200 "Unsupported adapter found. Id:%d Device id:0x%x "
7193 7201 "SSDID:0x%x Model:%s", hba->model_info.id,
7194 7202 hba->model_info.device_id,
7195 7203 hba->model_info.ssdid, hba->model_info.model);
7196 7204 goto failed;
7197 7205 }
7198 7206
7199 7207 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
7200 7208 hba->sli.sli4.mem_sgl_size = MEM_SGL_SIZE;
7201 7209
7202 7210 #ifdef EMLXS_I386
7203 7211 /*
7204 7212 * TigerShark has 64K limit for SG element size
7205 7213 * Do this for x86 alone. For SPARC, the driver
7206 7214 * breaks up the single SGE later on.
7207 7215 */
7208 7216 hba->dma_attr_ro.dma_attr_count_max = 0xffff;
7209 7217
7210 7218 i = cfg[CFG_MAX_XFER_SIZE].current;
7211 7219 /* Update SGL size based on max_xfer_size */
7212 7220 if (i > 516096) {
7213 7221 /* 516096 = (((2048 / 16) - 2) * 4096) */
7214 7222 hba->sli.sli4.mem_sgl_size = 4096;
7215 7223 } else if (i > 253952) {
7216 7224 /* 253952 = (((1024 / 16) - 2) * 4096) */
7217 7225 hba->sli.sli4.mem_sgl_size = 2048;
7218 7226 } else {
7219 7227 hba->sli.sli4.mem_sgl_size = 1024;
7220 7228 }
7221 7229 #endif /* EMLXS_I386 */
7222 7230
7223 7231 i = SGL_TO_SGLLEN(hba->sli.sli4.mem_sgl_size);
7224 7232 } else {
7225 7233 hba->sli.sli3.mem_bpl_size = MEM_BPL_SIZE;
7226 7234
7227 7235 #ifdef EMLXS_I386
7228 7236 i = cfg[CFG_MAX_XFER_SIZE].current;
7229 7237 /* Update BPL size based on max_xfer_size */
7230 7238 if (i > 688128) {
7231 7239 /* 688128 = (((2048 / 12) - 2) * 4096) */
7232 7240 hba->sli.sli3.mem_bpl_size = 4096;
7233 7241 } else if (i > 339968) {
7234 7242 /* 339968 = (((1024 / 12) - 2) * 4096) */
7235 7243 hba->sli.sli3.mem_bpl_size = 2048;
7236 7244 } else {
7237 7245 hba->sli.sli3.mem_bpl_size = 1024;
7238 7246 }
7239 7247 #endif /* EMLXS_I386 */
7240 7248
7241 7249 i = BPL_TO_SGLLEN(hba->sli.sli3.mem_bpl_size);
7242 7250 }
7243 7251
7244 7252 /* Update dma_attr_sgllen based on true SGL length */
7245 7253 hba->dma_attr.dma_attr_sgllen = i;
7246 7254 hba->dma_attr_ro.dma_attr_sgllen = i;
7247 7255 hba->dma_attr_fcip_rsp.dma_attr_sgllen = i;
7248 7256
7249 7257 if (EMLXS_SLI_MAP_HDW(hba)) {
7250 7258 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7251 7259 "Unable to map memory");
7252 7260 goto failed;
7253 7261
7254 7262 }
7255 7263 init_flag |= ATTACH_MAP_SLI;
7256 7264
7257 7265 /* Initialize the interrupts. But don't add them yet */
7258 7266 status = EMLXS_INTR_INIT(hba, 0);
7259 7267 if (status != DDI_SUCCESS) {
7260 7268 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7261 7269 "Unable to initalize interrupt(s).");
7262 7270 goto failed;
7263 7271
7264 7272 }
7265 7273 init_flag |= ATTACH_INTR_INIT;
7266 7274
7267 7275 /* Initialize LOCKs */
7268 7276 emlxs_msg_lock_reinit(hba);
7269 7277 emlxs_lock_init(hba);
7270 7278 init_flag |= ATTACH_LOCK;
7271 7279
7272 7280 /* Create the event queue */
7273 7281 if (emlxs_event_queue_create(hba) == 0) {
7274 7282 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7275 7283 "Unable to create event queue");
7276 7284
7277 7285 goto failed;
7278 7286
7279 7287 }
7280 7288 init_flag |= ATTACH_EVENTS;
7281 7289
7282 7290 /* Initialize the power management */
7283 7291 mutex_enter(&EMLXS_PM_LOCK);
7284 7292 hba->pm_state = EMLXS_PM_IN_ATTACH;
7285 7293 hba->pm_level = EMLXS_PM_ADAPTER_DOWN;
7286 7294 hba->pm_busy = 0;
7287 7295 #ifdef IDLE_TIMER
7288 7296 hba->pm_active = 1;
7289 7297 hba->pm_idle_timer = 0;
7290 7298 #endif /* IDLE_TIMER */
7291 7299 mutex_exit(&EMLXS_PM_LOCK);
7292 7300
7293 7301 /* Set the pm component name */
7294 7302 (void) snprintf(local_pm_components, sizeof (local_pm_components),
7295 7303 "NAME=%s%d", DRIVER_NAME, ddiinst);
7296 7304 emlxs_pm_components[0] = local_pm_components;
7297 7305
7298 7306 /* Check if power management support is enabled */
7299 7307 if (cfg[CFG_PM_SUPPORT].current) {
7300 7308 if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
7301 7309 "pm-components", emlxs_pm_components,
7302 7310 sizeof (emlxs_pm_components) /
7303 7311 sizeof (emlxs_pm_components[0])) !=
7304 7312 DDI_PROP_SUCCESS) {
7305 7313 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7306 7314 "Unable to create pm components.");
7307 7315 goto failed;
7308 7316 }
7309 7317 }
7310 7318
7311 7319 /* Needed for suspend and resume support */
7312 7320 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "pm-hardware-state",
7313 7321 "needs-suspend-resume");
7314 7322 init_flag |= ATTACH_PROP;
7315 7323
7316 7324 emlxs_thread_spawn_create(hba);
7317 7325 init_flag |= ATTACH_SPAWN;
7318 7326
7319 7327 emlxs_thread_create(hba, &hba->iodone_thread);
7320 7328
7321 7329 init_flag |= ATTACH_THREAD;
7322 7330
7323 7331 retry:
7324 7332 /* Setup initiator / target ports */
7325 7333 emlxs_mode_init(hba);
7326 7334
7327 7335 /* If driver did not attach to either stack, */
7328 7336 /* then driver attach fails */
7329 7337 if (port->mode == MODE_NONE) {
7330 7338 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7331 7339 "Driver interfaces not enabled.");
7332 7340 goto failed;
7333 7341 }
7334 7342
7335 7343 /*
7336 7344 * Initialize HBA
7337 7345 */
7338 7346
7339 7347 /* Set initial state */
7340 7348 mutex_enter(&EMLXS_PORT_LOCK);
7341 7349 hba->flag |= FC_OFFLINE_MODE;
7342 7350 hba->flag &= ~(FC_ONLINE_MODE | FC_ONLINING_MODE | FC_OFFLINING_MODE);
7343 7351 mutex_exit(&EMLXS_PORT_LOCK);
7344 7352
7345 7353 if (status = emlxs_online(hba)) {
7346 7354 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7347 7355 "Unable to initialize adapter.");
7348 7356
7349 7357 if (status == EAGAIN) {
7350 7358 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7351 7359 "Retrying adapter initialization ...");
7352 7360 goto retry;
7353 7361 }
7354 7362 goto failed;
7355 7363 }
7356 7364 init_flag |= ATTACH_ONLINE;
7357 7365
7358 7366 /* This is to ensure that the model property is properly set */
7359 7367 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model",
7360 7368 hba->model_info.model);
7361 7369
7362 7370 /* Create the device node. */
7363 7371 if (ddi_create_minor_node(dip, "devctl", S_IFCHR, ddiinst, NULL, 0) ==
7364 7372 DDI_FAILURE) {
7365 7373 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
7366 7374 "Unable to create device node.");
7367 7375 goto failed;
7368 7376 }
7369 7377 init_flag |= ATTACH_NODE;
7370 7378
7371 7379 /* Attach initiator now */
7372 7380 /* This must come after emlxs_online() */
7373 7381 emlxs_fca_attach(hba);
7374 7382 init_flag |= ATTACH_FCA;
7375 7383
7376 7384 /* Initialize kstat information */
7377 7385 hba->kstat = kstat_create(DRIVER_NAME,
7378 7386 ddiinst, "statistics", "controller",
7379 7387 KSTAT_TYPE_RAW, sizeof (emlxs_stats_t),
7380 7388 KSTAT_FLAG_VIRTUAL);
7381 7389
7382 7390 if (hba->kstat == NULL) {
7383 7391 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
7384 7392 "kstat_create failed.");
7385 7393 } else {
7386 7394 hba->kstat->ks_data = (void *)&hba->stats;
7387 7395 kstat_install(hba->kstat);
7388 7396 init_flag |= ATTACH_KSTAT;
7389 7397 }
7390 7398
7391 7399 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4)
7392 7400 /* Setup virtual port properties */
7393 7401 emlxs_read_vport_prop(hba);
7394 7402 #endif /* EMLXS_MODREV3 || EMLXS_MODREV4 */
7395 7403
7396 7404
7397 7405 #ifdef DHCHAP_SUPPORT
7398 7406 emlxs_dhc_attach(hba);
7399 7407 init_flag |= ATTACH_DHCHAP;
7400 7408 #endif /* DHCHAP_SUPPORT */
7401 7409
7402 7410 /* Display the driver banner now */
7403 7411 emlxs_drv_banner(hba);
7404 7412
7405 7413 /* Raise the power level */
7406 7414
7407 7415 /*
7408 7416 * This will not execute emlxs_hba_resume because
7409 7417 * EMLXS_PM_IN_ATTACH is set
7410 7418 */
7411 7419 if (emlxs_pm_raise_power(dip) != DDI_SUCCESS) {
7412 7420 /* Set power up anyway. This should not happen! */
7413 7421 mutex_enter(&EMLXS_PM_LOCK);
7414 7422 hba->pm_level = EMLXS_PM_ADAPTER_UP;
7415 7423 hba->pm_state &= ~EMLXS_PM_IN_ATTACH;
7416 7424 mutex_exit(&EMLXS_PM_LOCK);
7417 7425 } else {
7418 7426 mutex_enter(&EMLXS_PM_LOCK);
7419 7427 hba->pm_state &= ~EMLXS_PM_IN_ATTACH;
7420 7428 mutex_exit(&EMLXS_PM_LOCK);
7421 7429 }
7422 7430
7423 7431 #ifdef SFCT_SUPPORT
7424 7432 if (port->flag & EMLXS_TGT_ENABLED) {
7425 7433 /* Do this last */
7426 7434 emlxs_fct_attach(hba);
7427 7435 init_flag |= ATTACH_FCT;
7428 7436 }
7429 7437 #endif /* SFCT_SUPPORT */
7430 7438
7431 7439 return (DDI_SUCCESS);
7432 7440
7433 7441 failed:
7434 7442
7435 7443 emlxs_driver_remove(dip, init_flag, 1);
7436 7444
7437 7445 return (DDI_FAILURE);
7438 7446
7439 7447 } /* emlxs_hba_attach() */
7440 7448
7441 7449
7442 7450 static int
7443 7451 emlxs_hba_detach(dev_info_t *dip)
7444 7452 {
7445 7453 emlxs_hba_t *hba;
7446 7454 emlxs_port_t *port;
7447 7455 int ddiinst;
7448 7456 int count;
7449 7457 uint32_t init_flag = (uint32_t)-1;
7450 7458
7451 7459 ddiinst = ddi_get_instance(dip);
7452 7460 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst);
7453 7461 port = &PPORT;
7454 7462
7455 7463 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, NULL);
7456 7464
7457 7465 mutex_enter(&EMLXS_PM_LOCK);
7458 7466 hba->pm_state |= EMLXS_PM_IN_DETACH;
7459 7467 mutex_exit(&EMLXS_PM_LOCK);
7460 7468
7461 7469 /* Lower the power level */
7462 7470 /*
7463 7471 * This will not suspend the driver since the
7464 7472 * EMLXS_PM_IN_DETACH has been set
7465 7473 */
7466 7474 if (emlxs_pm_lower_power(dip) != DDI_SUCCESS) {
7467 7475 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
7468 7476 "Unable to lower power.");
7469 7477
7470 7478 mutex_enter(&EMLXS_PM_LOCK);
7471 7479 hba->pm_state &= ~EMLXS_PM_IN_DETACH;
7472 7480 mutex_exit(&EMLXS_PM_LOCK);
7473 7481
7474 7482 return (DDI_FAILURE);
7475 7483 }
7476 7484
7477 7485 /* Take the adapter offline first, if not already */
7478 7486 if (emlxs_offline(hba, 1) != 0) {
7479 7487 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg,
7480 7488 "Unable to take adapter offline.");
7481 7489
7482 7490 mutex_enter(&EMLXS_PM_LOCK);
7483 7491 hba->pm_state &= ~EMLXS_PM_IN_DETACH;
7484 7492 mutex_exit(&EMLXS_PM_LOCK);
7485 7493
7486 7494 (void) emlxs_pm_raise_power(dip);
7487 7495
7488 7496 return (DDI_FAILURE);
7489 7497 }
7490 7498 /* Check ub buffer pools */
7491 7499 if (port->ub_pool) {
7492 7500 mutex_enter(&EMLXS_UB_LOCK);
7493 7501
7494 7502 /* Wait up to 10 seconds for all ub pools to be freed */
7495 7503 count = 10 * 2;
7496 7504 while (port->ub_pool && count) {
7497 7505 mutex_exit(&EMLXS_UB_LOCK);
7498 7506 delay(drv_usectohz(500000)); /* half second wait */
7499 7507 count--;
7500 7508 mutex_enter(&EMLXS_UB_LOCK);
7501 7509 }
7502 7510
7503 7511 if (port->ub_pool) {
7504 7512 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
7505 7513 "fca_unbind_port: Unsolicited buffers still "
7506 7514 "active. port=%p. Destroying...", port);
7507 7515
7508 7516 /* Destroy all pools */
7509 7517 while (port->ub_pool) {
7510 7518 emlxs_ub_destroy(port, port->ub_pool);
7511 7519 }
7512 7520 }
7513 7521
7514 7522 mutex_exit(&EMLXS_UB_LOCK);
7515 7523 }
7516 7524 init_flag &= ~ATTACH_ONLINE;
7517 7525
7518 7526 /* Remove the driver instance */
7519 7527 emlxs_driver_remove(dip, init_flag, 0);
7520 7528
7521 7529 return (DDI_SUCCESS);
7522 7530
7523 7531 } /* emlxs_hba_detach() */
7524 7532
7525 7533
7526 7534 extern int
7527 7535 emlxs_map_bus(emlxs_hba_t *hba)
7528 7536 {
7529 7537 emlxs_port_t *port = &PPORT;
7530 7538 dev_info_t *dip;
7531 7539 ddi_device_acc_attr_t dev_attr;
7532 7540 int status;
7533 7541
7534 7542 dip = (dev_info_t *)hba->dip;
7535 7543 dev_attr = emlxs_dev_acc_attr;
7536 7544
7537 7545 if (hba->bus_type == SBUS_FC) {
7538 7546 if (hba->pci_acc_handle == 0) {
7539 7547 status = ddi_regs_map_setup(dip,
7540 7548 SBUS_DFLY_PCI_CFG_RINDEX,
7541 7549 (caddr_t *)&hba->pci_addr,
7542 7550 0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle);
7543 7551 if (status != DDI_SUCCESS) {
7544 7552 EMLXS_MSGF(EMLXS_CONTEXT,
7545 7553 &emlxs_attach_failed_msg,
7546 7554 "(SBUS) ddi_regs_map_setup PCI failed. "
7547 7555 "status=%x", status);
7548 7556 goto failed;
7549 7557 }
7550 7558 }
7551 7559
7552 7560 if (hba->sbus_pci_handle == 0) {
7553 7561 status = ddi_regs_map_setup(dip,
7554 7562 SBUS_TITAN_PCI_CFG_RINDEX,
7555 7563 (caddr_t *)&hba->sbus_pci_addr,
7556 7564 0, 0, &dev_attr, &hba->sbus_pci_handle);
7557 7565 if (status != DDI_SUCCESS) {
7558 7566 EMLXS_MSGF(EMLXS_CONTEXT,
7559 7567 &emlxs_attach_failed_msg,
7560 7568 "(SBUS) ddi_regs_map_setup TITAN PCI "
7561 7569 "failed. status=%x", status);
7562 7570 goto failed;
7563 7571 }
7564 7572 }
7565 7573
7566 7574 } else { /* ****** PCI ****** */
7567 7575
7568 7576 if (hba->pci_acc_handle == 0) {
7569 7577 status = ddi_regs_map_setup(dip,
7570 7578 PCI_CFG_RINDEX,
7571 7579 (caddr_t *)&hba->pci_addr,
7572 7580 0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle);
7573 7581 if (status != DDI_SUCCESS) {
7574 7582 EMLXS_MSGF(EMLXS_CONTEXT,
7575 7583 &emlxs_attach_failed_msg,
7576 7584 "(PCI) ddi_regs_map_setup PCI failed. "
7577 7585 "status=%x", status);
7578 7586 goto failed;
7579 7587 }
7580 7588 }
7581 7589 #ifdef EMLXS_I386
7582 7590 /* Setting up PCI configure space */
7583 7591 (void) ddi_put16(hba->pci_acc_handle,
7584 7592 (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
7585 7593 CMD_CFG_VALUE | CMD_IO_ENBL);
7586 7594
7587 7595 #ifdef FMA_SUPPORT
7588 7596 if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
7589 7597 != DDI_FM_OK) {
7590 7598 EMLXS_MSGF(EMLXS_CONTEXT,
7591 7599 &emlxs_invalid_access_handle_msg, NULL);
7592 7600 goto failed;
7593 7601 }
7594 7602 #endif /* FMA_SUPPORT */
7595 7603
7596 7604 #endif /* EMLXS_I386 */
7597 7605
7598 7606 }
7599 7607 return (0);
7600 7608
7601 7609 failed:
7602 7610
7603 7611 emlxs_unmap_bus(hba);
7604 7612 return (ENOMEM);
7605 7613
7606 7614 } /* emlxs_map_bus() */
7607 7615
7608 7616
7609 7617 extern void
7610 7618 emlxs_unmap_bus(emlxs_hba_t *hba)
7611 7619 {
7612 7620 if (hba->pci_acc_handle) {
7613 7621 (void) ddi_regs_map_free(&hba->pci_acc_handle);
7614 7622 hba->pci_acc_handle = 0;
7615 7623 }
7616 7624
7617 7625 if (hba->sbus_pci_handle) {
7618 7626 (void) ddi_regs_map_free(&hba->sbus_pci_handle);
7619 7627 hba->sbus_pci_handle = 0;
7620 7628 }
7621 7629
7622 7630 return;
7623 7631
7624 7632 } /* emlxs_unmap_bus() */
7625 7633
7626 7634
7627 7635 static int
7628 7636 emlxs_get_props(emlxs_hba_t *hba)
7629 7637 {
7630 7638 emlxs_config_t *cfg;
7631 7639 uint32_t i;
7632 7640 char string[256];
7633 7641 uint32_t new_value;
7634 7642
7635 7643 /* Initialize each parameter */
7636 7644 for (i = 0; i < NUM_CFG_PARAM; i++) {
7637 7645 cfg = &hba->config[i];
7638 7646
7639 7647 /* Ensure strings are terminated */
7640 7648 cfg->string[(EMLXS_CFG_STR_SIZE-1)] = 0;
7641 7649 cfg->help[(EMLXS_CFG_HELP_SIZE-1)] = 0;
7642 7650
7643 7651 /* Set the current value to the default value */
7644 7652 new_value = cfg->def;
7645 7653
7646 7654 /* First check for the global setting */
7647 7655 new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7648 7656 (void *)hba->dip, DDI_PROP_DONTPASS,
7649 7657 cfg->string, new_value);
7650 7658
7651 7659 /* Now check for the per adapter ddiinst setting */
7652 7660 (void) snprintf(string, sizeof (string), "%s%d-%s", DRIVER_NAME,
7653 7661 hba->ddiinst, cfg->string);
7654 7662
7655 7663 new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7656 7664 (void *)hba->dip, DDI_PROP_DONTPASS, string, new_value);
7657 7665
7658 7666 /* Now check the parameter */
7659 7667 cfg->current = emlxs_check_parm(hba, i, new_value);
7660 7668 }
7661 7669
7662 7670 return (0);
7663 7671
7664 7672 } /* emlxs_get_props() */
7665 7673
7666 7674
7667 7675 extern uint32_t
7668 7676 emlxs_check_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value)
7669 7677 {
7670 7678 emlxs_port_t *port = &PPORT;
7671 7679 uint32_t i;
7672 7680 emlxs_config_t *cfg;
7673 7681 emlxs_vpd_t *vpd = &VPD;
7674 7682
7675 7683 if (index >= NUM_CFG_PARAM) {
7676 7684 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
7677 7685 "check_parm failed. Invalid index = %d", index);
7678 7686
7679 7687 return (new_value);
7680 7688 }
7681 7689
7682 7690 cfg = &hba->config[index];
7683 7691
7684 7692 if (new_value > cfg->hi) {
7685 7693 new_value = cfg->def;
7686 7694 } else if (new_value < cfg->low) {
7687 7695 new_value = cfg->def;
7688 7696 }
7689 7697
7690 7698 /* Perform additional checks */
7691 7699 switch (index) {
7692 7700 #ifdef SFCT_SUPPORT
7693 7701 case CFG_NPIV_ENABLE:
7694 7702 if (hba->config[CFG_TARGET_MODE].current &&
7695 7703 hba->config[CFG_DTM_ENABLE].current == 0) {
7696 7704 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
7697 7705 "enable-npiv: Not supported in pure target mode. "
7698 7706 "Disabling.");
7699 7707
7700 7708 new_value = 0;
7701 7709 }
7702 7710 break;
7703 7711 #endif /* SFCT_SUPPORT */
7704 7712
7705 7713
7706 7714 case CFG_NUM_NODES:
7707 7715 switch (new_value) {
7708 7716 case 1:
7709 7717 case 2:
7710 7718 /* Must have at least 3 if not 0 */
7711 7719 return (3);
7712 7720
7713 7721 default:
7714 7722 break;
7715 7723 }
7716 7724 break;
7717 7725
7718 7726 case CFG_FW_CHECK:
7719 7727 /* The 0x2 bit implies the 0x1 bit will also be set */
7720 7728 if (new_value & 0x2) {
7721 7729 new_value |= 0x1;
7722 7730 }
7723 7731
7724 7732 /* The 0x4 bit should not be set if 0x1 or 0x2 is not set */
7725 7733 if (!(new_value & 0x3) && (new_value & 0x4)) {
7726 7734 new_value &= ~0x4;
7727 7735 }
7728 7736 break;
7729 7737
7730 7738 case CFG_LINK_SPEED:
7731 7739 if ((new_value > 8) &&
7732 7740 (hba->config[CFG_TOPOLOGY].current == 4)) {
7733 7741 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
7734 7742 "link-speed: %dGb not supported in loop topology. "
7735 7743 "Switching to auto detect.",
7736 7744 new_value);
7737 7745
7738 7746 new_value = 0;
7739 7747 break;
7740 7748 }
7741 7749
7742 7750 if (vpd->link_speed) {
7743 7751 switch (new_value) {
7744 7752 case 0:
7745 7753 break;
7746 7754
7747 7755 case 1:
7748 7756 if (!(vpd->link_speed & LMT_1GB_CAPABLE)) {
7749 7757 new_value = 0;
7750 7758
7751 7759 EMLXS_MSGF(EMLXS_CONTEXT,
7752 7760 &emlxs_init_msg,
7753 7761 "link-speed: 1Gb not supported "
7754 7762 "by adapter. Switching to auto "
7755 7763 "detect.");
7756 7764 }
7757 7765 break;
7758 7766
7759 7767 case 2:
7760 7768 if (!(vpd->link_speed & LMT_2GB_CAPABLE)) {
7761 7769 new_value = 0;
7762 7770
7763 7771 EMLXS_MSGF(EMLXS_CONTEXT,
7764 7772 &emlxs_init_msg,
7765 7773 "link-speed: 2Gb not supported "
7766 7774 "by adapter. Switching to auto "
7767 7775 "detect.");
7768 7776 }
7769 7777 break;
7770 7778
7771 7779 case 4:
7772 7780 if (!(vpd->link_speed & LMT_4GB_CAPABLE)) {
7773 7781 new_value = 0;
7774 7782
7775 7783 EMLXS_MSGF(EMLXS_CONTEXT,
7776 7784 &emlxs_init_msg,
7777 7785 "link-speed: 4Gb not supported "
7778 7786 "by adapter. Switching to auto "
7779 7787 "detect.");
7780 7788 }
7781 7789 break;
7782 7790
7783 7791 case 8:
7784 7792 if (!(vpd->link_speed & LMT_8GB_CAPABLE)) {
7785 7793 new_value = 0;
7786 7794
7787 7795 EMLXS_MSGF(EMLXS_CONTEXT,
7788 7796 &emlxs_init_msg,
7789 7797 "link-speed: 8Gb not supported "
7790 7798 "by adapter. Switching to auto "
7791 7799 "detect.");
7792 7800 }
7793 7801 break;
7794 7802
7795 7803 case 16:
7796 7804 if (!(vpd->link_speed & LMT_16GB_CAPABLE)) {
7797 7805 new_value = 0;
7798 7806
7799 7807 EMLXS_MSGF(EMLXS_CONTEXT,
7800 7808 &emlxs_init_msg,
7801 7809 "link-speed: 16Gb not supported "
7802 7810 "by adapter. Switching to auto "
7803 7811 "detect.");
7804 7812 }
7805 7813 break;
7806 7814
7807 7815 default:
7808 7816 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
7809 7817 "link-speed: Invalid value=%d provided. "
7810 7818 "Switching to auto detect.",
7811 7819 new_value);
7812 7820
7813 7821 new_value = 0;
7814 7822 }
7815 7823 } else { /* Perform basic validity check */
7816 7824
7817 7825 /* Perform additional check on link speed */
7818 7826 switch (new_value) {
7819 7827 case 0:
7820 7828 case 1:
7821 7829 case 2:
7822 7830 case 4:
7823 7831 case 8:
7824 7832 case 16:
7825 7833 /* link-speed is a valid choice */
7826 7834 break;
7827 7835
7828 7836 default:
7829 7837 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
7830 7838 "link-speed: Invalid value=%d provided. "
7831 7839 "Switching to auto detect.",
7832 7840 new_value);
7833 7841
7834 7842 new_value = 0;
7835 7843 }
7836 7844 }
7837 7845 break;
7838 7846
7839 7847 case CFG_TOPOLOGY:
7840 7848 if ((new_value == 4) &&
7841 7849 (hba->config[CFG_LINK_SPEED].current > 8)) {
7842 7850 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
7843 7851 "topology: Loop topology not supported "
7844 7852 "with link speeds greater than 8Gb. "
7845 7853 "Switching to auto detect.");
7846 7854
7847 7855 new_value = 0;
7848 7856 break;
7849 7857 }
7850 7858
7851 7859 /* Perform additional check on topology */
7852 7860 switch (new_value) {
7853 7861 case 0:
7854 7862 case 2:
7855 7863 case 4:
7856 7864 case 6:
7857 7865 /* topology is a valid choice */
7858 7866 break;
7859 7867
7860 7868 default:
7861 7869 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
7862 7870 "topology: Invalid value=%d provided. "
7863 7871 "Switching to auto detect.",
7864 7872 new_value);
7865 7873
7866 7874 new_value = 0;
7867 7875 break;
7868 7876 }
7869 7877 break;
7870 7878
7871 7879 #ifdef DHCHAP_SUPPORT
7872 7880 case CFG_AUTH_TYPE:
7873 7881 {
7874 7882 uint32_t shift;
7875 7883 uint32_t mask;
7876 7884
7877 7885 /* Perform additional check on auth type */
7878 7886 shift = 12;
7879 7887 mask = 0xF000;
7880 7888 for (i = 0; i < 4; i++) {
7881 7889 if (((new_value & mask) >> shift) > DFC_AUTH_TYPE_MAX) {
7882 7890 return (cfg->def);
7883 7891 }
7884 7892
7885 7893 shift -= 4;
7886 7894 mask >>= 4;
7887 7895 }
7888 7896 break;
7889 7897 }
7890 7898
7891 7899 case CFG_AUTH_HASH:
7892 7900 {
7893 7901 uint32_t shift;
7894 7902 uint32_t mask;
7895 7903
7896 7904 /* Perform additional check on auth hash */
7897 7905 shift = 12;
7898 7906 mask = 0xF000;
7899 7907 for (i = 0; i < 4; i++) {
7900 7908 if (((new_value & mask) >> shift) > DFC_AUTH_HASH_MAX) {
7901 7909 return (cfg->def);
7902 7910 }
7903 7911
7904 7912 shift -= 4;
7905 7913 mask >>= 4;
7906 7914 }
7907 7915 break;
7908 7916 }
7909 7917
7910 7918 case CFG_AUTH_GROUP:
7911 7919 {
7912 7920 uint32_t shift;
7913 7921 uint32_t mask;
7914 7922
7915 7923 /* Perform additional check on auth group */
7916 7924 shift = 28;
7917 7925 mask = 0xF0000000;
7918 7926 for (i = 0; i < 8; i++) {
7919 7927 if (((new_value & mask) >> shift) >
7920 7928 DFC_AUTH_GROUP_MAX) {
7921 7929 return (cfg->def);
7922 7930 }
7923 7931
7924 7932 shift -= 4;
7925 7933 mask >>= 4;
7926 7934 }
7927 7935 break;
7928 7936 }
7929 7937
7930 7938 case CFG_AUTH_INTERVAL:
7931 7939 if (new_value < 10) {
7932 7940 return (10);
7933 7941 }
7934 7942 break;
7935 7943
7936 7944
7937 7945 #endif /* DHCHAP_SUPPORT */
7938 7946
7939 7947 } /* switch */
7940 7948
7941 7949 return (new_value);
7942 7950
7943 7951 } /* emlxs_check_parm() */
7944 7952
7945 7953
7946 7954 extern uint32_t
7947 7955 emlxs_set_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value)
7948 7956 {
7949 7957 emlxs_port_t *port = &PPORT;
7950 7958 emlxs_port_t *vport;
7951 7959 uint32_t vpi;
7952 7960 emlxs_config_t *cfg;
7953 7961 uint32_t old_value;
7954 7962
7955 7963 if (index >= NUM_CFG_PARAM) {
7956 7964 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
7957 7965 "set_parm failed. Invalid index = %d", index);
7958 7966
7959 7967 return ((uint32_t)FC_FAILURE);
7960 7968 }
7961 7969
7962 7970 cfg = &hba->config[index];
7963 7971
7964 7972 if (!(cfg->flags & PARM_DYNAMIC)) {
7965 7973 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
7966 7974 "set_parm failed. %s is not dynamic.", cfg->string);
7967 7975
7968 7976 return ((uint32_t)FC_FAILURE);
7969 7977 }
7970 7978
7971 7979 /* Check new value */
7972 7980 old_value = new_value;
7973 7981 new_value = emlxs_check_parm(hba, index, new_value);
7974 7982
7975 7983 if (old_value != new_value) {
7976 7984 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
7977 7985 "set_parm: %s invalid. 0x%x --> 0x%x",
7978 7986 cfg->string, old_value, new_value);
7979 7987 }
7980 7988
7981 7989 /* Return now if no actual change */
7982 7990 if (new_value == cfg->current) {
7983 7991 return (FC_SUCCESS);
7984 7992 }
7985 7993
7986 7994 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
7987 7995 "set_parm: %s changing. 0x%x --> 0x%x",
7988 7996 cfg->string, cfg->current, new_value);
7989 7997
7990 7998 old_value = cfg->current;
7991 7999 cfg->current = new_value;
7992 8000
7993 8001 /* React to change if needed */
7994 8002 switch (index) {
7995 8003
7996 8004 case CFG_PCI_MAX_READ:
7997 8005 /* Update MXR */
7998 8006 emlxs_pcix_mxr_update(hba, 1);
7999 8007 break;
8000 8008
8001 8009 #ifdef SFCT_SUPPORT
8002 8010 case CFG_TARGET_MODE:
8003 8011 (void) emlxs_reset(port, FC_FCA_LINK_RESET);
8004 8012 break;
8005 8013 #endif /* SFCT_SUPPORT */
8006 8014
8007 8015 case CFG_SLI_MODE:
8008 8016 /* Check SLI mode */
8009 8017 if ((hba->sli_mode == 3) && (new_value == 2)) {
8010 8018 /* All vports must be disabled first */
8011 8019 for (vpi = 1; vpi < MAX_VPORTS; vpi++) {
8012 8020 vport = &VPORT(vpi);
8013 8021
8014 8022 if (vport->flag & EMLXS_PORT_ENABLED) {
8015 8023 /* Reset current value */
8016 8024 cfg->current = old_value;
8017 8025
8018 8026 EMLXS_MSGF(EMLXS_CONTEXT,
8019 8027 &emlxs_sfs_debug_msg,
8020 8028 "set_parm failed. %s: vpi=%d "
8021 8029 "still enabled. Value restored to "
8022 8030 "0x%x.", cfg->string, vpi,
8023 8031 old_value);
8024 8032
8025 8033 return (2);
8026 8034 }
8027 8035 }
8028 8036 }
8029 8037
8030 8038 if ((hba->sli_mode >= 4) && (new_value < 4)) {
8031 8039 /*
8032 8040 * Not allow to set to SLI 2 or 3 if HBA supports SLI4
8033 8041 */
8034 8042 cfg->current = old_value;
8035 8043 return ((uint32_t)FC_FAILURE);
8036 8044 }
8037 8045
8038 8046 break;
8039 8047
8040 8048 case CFG_NPIV_ENABLE:
8041 8049 /* Check if NPIV is being disabled */
8042 8050 if ((old_value == 1) && (new_value == 0)) {
8043 8051 /* All vports must be disabled first */
8044 8052 for (vpi = 1; vpi < MAX_VPORTS; vpi++) {
8045 8053 vport = &VPORT(vpi);
8046 8054
8047 8055 if (vport->flag & EMLXS_PORT_ENABLED) {
8048 8056 /* Reset current value */
8049 8057 cfg->current = old_value;
8050 8058
8051 8059 EMLXS_MSGF(EMLXS_CONTEXT,
8052 8060 &emlxs_sfs_debug_msg,
8053 8061 "set_parm failed. %s: vpi=%d "
8054 8062 "still enabled. Value restored to "
8055 8063 "0x%x.", cfg->string, vpi,
8056 8064 old_value);
8057 8065
8058 8066 return (2);
8059 8067 }
8060 8068 }
8061 8069 }
8062 8070
8063 8071 /* Trigger adapter reset */
8064 8072 /* (void) emlxs_reset(port, FC_FCA_RESET); */
8065 8073
8066 8074 break;
8067 8075
8068 8076
8069 8077 case CFG_VPORT_RESTRICTED:
8070 8078 for (vpi = 0; vpi < MAX_VPORTS; vpi++) {
8071 8079 vport = &VPORT(vpi);
8072 8080
8073 8081 if (!(vport->flag & EMLXS_PORT_CONFIG)) {
8074 8082 continue;
8075 8083 }
8076 8084
8077 8085 if (vport->options & EMLXS_OPT_RESTRICT_MASK) {
8078 8086 continue;
8079 8087 }
8080 8088
8081 8089 if (new_value) {
8082 8090 vport->flag |= EMLXS_PORT_RESTRICTED;
8083 8091 } else {
8084 8092 vport->flag &= ~EMLXS_PORT_RESTRICTED;
8085 8093 }
8086 8094 }
8087 8095
8088 8096 break;
8089 8097
8090 8098 #ifdef DHCHAP_SUPPORT
8091 8099 case CFG_AUTH_ENABLE:
8092 8100 (void) emlxs_reset(port, FC_FCA_LINK_RESET);
8093 8101 break;
8094 8102
8095 8103 case CFG_AUTH_TMO:
8096 8104 hba->auth_cfg.authentication_timeout = cfg->current;
8097 8105 break;
8098 8106
8099 8107 case CFG_AUTH_MODE:
8100 8108 hba->auth_cfg.authentication_mode = cfg->current;
8101 8109 break;
8102 8110
8103 8111 case CFG_AUTH_BIDIR:
8104 8112 hba->auth_cfg.bidirectional = cfg->current;
8105 8113 break;
8106 8114
8107 8115 case CFG_AUTH_TYPE:
8108 8116 hba->auth_cfg.authentication_type_priority[0] =
8109 8117 (cfg->current & 0xF000) >> 12;
8110 8118 hba->auth_cfg.authentication_type_priority[1] =
8111 8119 (cfg->current & 0x0F00) >> 8;
8112 8120 hba->auth_cfg.authentication_type_priority[2] =
8113 8121 (cfg->current & 0x00F0) >> 4;
8114 8122 hba->auth_cfg.authentication_type_priority[3] =
8115 8123 (cfg->current & 0x000F);
8116 8124 break;
8117 8125
8118 8126 case CFG_AUTH_HASH:
8119 8127 hba->auth_cfg.hash_priority[0] =
8120 8128 (cfg->current & 0xF000) >> 12;
8121 8129 hba->auth_cfg.hash_priority[1] = (cfg->current & 0x0F00)>>8;
8122 8130 hba->auth_cfg.hash_priority[2] = (cfg->current & 0x00F0)>>4;
8123 8131 hba->auth_cfg.hash_priority[3] = (cfg->current & 0x000F);
8124 8132 break;
8125 8133
8126 8134 case CFG_AUTH_GROUP:
8127 8135 hba->auth_cfg.dh_group_priority[0] =
8128 8136 (cfg->current & 0xF0000000) >> 28;
8129 8137 hba->auth_cfg.dh_group_priority[1] =
8130 8138 (cfg->current & 0x0F000000) >> 24;
8131 8139 hba->auth_cfg.dh_group_priority[2] =
8132 8140 (cfg->current & 0x00F00000) >> 20;
8133 8141 hba->auth_cfg.dh_group_priority[3] =
8134 8142 (cfg->current & 0x000F0000) >> 16;
8135 8143 hba->auth_cfg.dh_group_priority[4] =
8136 8144 (cfg->current & 0x0000F000) >> 12;
8137 8145 hba->auth_cfg.dh_group_priority[5] =
8138 8146 (cfg->current & 0x00000F00) >> 8;
8139 8147 hba->auth_cfg.dh_group_priority[6] =
8140 8148 (cfg->current & 0x000000F0) >> 4;
8141 8149 hba->auth_cfg.dh_group_priority[7] =
8142 8150 (cfg->current & 0x0000000F);
8143 8151 break;
8144 8152
8145 8153 case CFG_AUTH_INTERVAL:
8146 8154 hba->auth_cfg.reauthenticate_time_interval = cfg->current;
8147 8155 break;
8148 8156 #endif /* DHCHAP_SUPPORT */
8149 8157
8150 8158 }
8151 8159
8152 8160 return (FC_SUCCESS);
8153 8161
8154 8162 } /* emlxs_set_parm() */
8155 8163
8156 8164
8157 8165 /*
8158 8166 * emlxs_mem_alloc OS specific routine for memory allocation / mapping
8159 8167 *
8160 8168 * The buf_info->flags field describes the memory operation requested.
8161 8169 *
8162 8170 * FC_MBUF_PHYSONLY set requests a supplied virtual address be mapped for DMA
8163 8171 * Virtual address is supplied in buf_info->virt
8164 8172 * DMA mapping flag is in buf_info->align
8165 8173 * (DMA_READ_ONLY, DMA_WRITE_ONLY, DMA_READ_WRITE)
8166 8174 * The mapped physical address is returned buf_info->phys
8167 8175 *
8168 8176 * FC_MBUF_PHYSONLY cleared requests memory be allocated for driver use and
8169 8177 * if FC_MBUF_DMA is set the memory is also mapped for DMA
8170 8178 * The byte alignment of the memory request is supplied in buf_info->align
8171 8179 * The byte size of the memory request is supplied in buf_info->size
8172 8180 * The virtual address is returned buf_info->virt
8173 8181 * The mapped physical address is returned buf_info->phys (for FC_MBUF_DMA)
8174 8182 */
8175 8183 extern uint8_t *
8176 8184 emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info)
8177 8185 {
8178 8186 emlxs_port_t *port = &PPORT;
8179 8187 ddi_dma_attr_t dma_attr;
8180 8188 ddi_device_acc_attr_t dev_attr;
8181 8189 uint_t cookie_count;
8182 8190 size_t dma_reallen;
8183 8191 ddi_dma_cookie_t dma_cookie;
8184 8192 uint_t dma_flag;
8185 8193 int status;
8186 8194
8187 8195 dma_attr = hba->dma_attr_1sg;
8188 8196 dev_attr = emlxs_data_acc_attr;
8189 8197
8190 8198 if (buf_info->flags & FC_MBUF_SNGLSG) {
8191 8199 dma_attr.dma_attr_sgllen = 1;
8192 8200 }
8193 8201
8194 8202 if (buf_info->flags & FC_MBUF_DMA32) {
8195 8203 dma_attr.dma_attr_addr_hi = (uint64_t)0xffffffff;
8196 8204 }
8197 8205
8198 8206 if (buf_info->flags & FC_MBUF_PHYSONLY) {
8199 8207
8200 8208 if (buf_info->virt == NULL) {
8201 8209 goto done;
8202 8210 }
8203 8211
8204 8212 /*
8205 8213 * Allocate the DMA handle for this DMA object
8206 8214 */
8207 8215 status = ddi_dma_alloc_handle((void *)hba->dip,
8208 8216 &dma_attr, DDI_DMA_DONTWAIT,
8209 8217 NULL, (ddi_dma_handle_t *)&buf_info->dma_handle);
8210 8218 if (status != DDI_SUCCESS) {
8211 8219 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
8212 8220 "ddi_dma_alloc_handle failed: size=%x align=%x "
8213 8221 "flags=%x", buf_info->size, buf_info->align,
8214 8222 buf_info->flags);
8215 8223
8216 8224 buf_info->phys = 0;
8217 8225 buf_info->dma_handle = 0;
8218 8226 goto done;
8219 8227 }
8220 8228
8221 8229 switch (buf_info->align) {
8222 8230 case DMA_READ_WRITE:
8223 8231 dma_flag = (DDI_DMA_RDWR | DDI_DMA_CONSISTENT);
8224 8232 break;
8225 8233 case DMA_READ_ONLY:
8226 8234 dma_flag = (DDI_DMA_READ | DDI_DMA_CONSISTENT);
8227 8235 break;
8228 8236 case DMA_WRITE_ONLY:
8229 8237 dma_flag = (DDI_DMA_WRITE | DDI_DMA_CONSISTENT);
8230 8238 break;
8231 8239 default:
8232 8240 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
8233 8241 "Invalid DMA flag");
8234 8242 (void) ddi_dma_free_handle(
8235 8243 (ddi_dma_handle_t *)&buf_info->dma_handle);
8236 8244 buf_info->phys = 0;
8237 8245 buf_info->dma_handle = 0;
8238 8246 return ((uint8_t *)buf_info->virt);
8239 8247 }
8240 8248
8241 8249 /* Map this page of memory */
8242 8250 status = ddi_dma_addr_bind_handle(
8243 8251 (ddi_dma_handle_t)buf_info->dma_handle, NULL,
8244 8252 (caddr_t)buf_info->virt, (size_t)buf_info->size,
8245 8253 dma_flag, DDI_DMA_DONTWAIT, NULL, &dma_cookie,
8246 8254 &cookie_count);
8247 8255
8248 8256 if (status != DDI_DMA_MAPPED || (cookie_count > 1)) {
8249 8257 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
8250 8258 "ddi_dma_addr_bind_handle failed: status=%x "
8251 8259 "count=%x flags=%x", status, cookie_count,
8252 8260 buf_info->flags);
8253 8261
8254 8262 (void) ddi_dma_free_handle(
8255 8263 (ddi_dma_handle_t *)&buf_info->dma_handle);
8256 8264 buf_info->phys = 0;
8257 8265 buf_info->dma_handle = 0;
8258 8266 goto done;
8259 8267 }
8260 8268
8261 8269 if (hba->bus_type == SBUS_FC) {
8262 8270
8263 8271 int32_t burstsizes_limit = 0xff;
8264 8272 int32_t ret_burst;
8265 8273
8266 8274 ret_burst = ddi_dma_burstsizes(
8267 8275 buf_info->dma_handle) & burstsizes_limit;
8268 8276 if (ddi_dma_set_sbus64(buf_info->dma_handle,
8269 8277 ret_burst) == DDI_FAILURE) {
8270 8278 EMLXS_MSGF(EMLXS_CONTEXT,
8271 8279 &emlxs_mem_alloc_failed_msg,
8272 8280 "ddi_dma_set_sbus64 failed.");
8273 8281 }
8274 8282 }
8275 8283
8276 8284 /* Save Physical address */
8277 8285 buf_info->phys = dma_cookie.dmac_laddress;
8278 8286
8279 8287 /*
8280 8288 * Just to be sure, let's add this
8281 8289 */
8282 8290 EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle,
8283 8291 (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV);
8284 8292
8285 8293 } else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) {
8286 8294
8287 8295 dma_attr.dma_attr_align = buf_info->align;
8288 8296
8289 8297 /*
8290 8298 * Allocate the DMA handle for this DMA object
8291 8299 */
8292 8300 status = ddi_dma_alloc_handle((void *)hba->dip, &dma_attr,
8293 8301 DDI_DMA_DONTWAIT, NULL,
8294 8302 (ddi_dma_handle_t *)&buf_info->dma_handle);
8295 8303 if (status != DDI_SUCCESS) {
8296 8304 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
8297 8305 "ddi_dma_alloc_handle failed: size=%x align=%x "
8298 8306 "flags=%x", buf_info->size, buf_info->align,
8299 8307 buf_info->flags);
8300 8308
8301 8309 buf_info->virt = NULL;
8302 8310 buf_info->phys = 0;
8303 8311 buf_info->data_handle = 0;
8304 8312 buf_info->dma_handle = 0;
8305 8313 goto done;
8306 8314 }
8307 8315
8308 8316 status = ddi_dma_mem_alloc(
8309 8317 (ddi_dma_handle_t)buf_info->dma_handle,
8310 8318 (size_t)buf_info->size, &dev_attr, DDI_DMA_CONSISTENT,
8311 8319 DDI_DMA_DONTWAIT, NULL, (caddr_t *)&buf_info->virt,
8312 8320 &dma_reallen, (ddi_acc_handle_t *)&buf_info->data_handle);
8313 8321
8314 8322 if ((status != DDI_SUCCESS) || (buf_info->size > dma_reallen)) {
8315 8323 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
8316 8324 "ddi_dma_mem_alloc failed: size=%x align=%x "
8317 8325 "flags=%x", buf_info->size, buf_info->align,
8318 8326 buf_info->flags);
8319 8327
8320 8328 (void) ddi_dma_free_handle(
8321 8329 (ddi_dma_handle_t *)&buf_info->dma_handle);
8322 8330
8323 8331 buf_info->virt = NULL;
8324 8332 buf_info->phys = 0;
8325 8333 buf_info->data_handle = 0;
8326 8334 buf_info->dma_handle = 0;
8327 8335 goto done;
8328 8336 }
8329 8337
8330 8338 /* Map this page of memory */
8331 8339 status = ddi_dma_addr_bind_handle(
8332 8340 (ddi_dma_handle_t)buf_info->dma_handle, NULL,
8333 8341 (caddr_t)buf_info->virt, (size_t)buf_info->size,
8334 8342 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
8335 8343 &dma_cookie, &cookie_count);
8336 8344
8337 8345 if (status != DDI_DMA_MAPPED || (cookie_count > 1)) {
8338 8346 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
8339 8347 "ddi_dma_addr_bind_handle failed: status=%x "
8340 8348 "count=%d size=%x align=%x flags=%x", status,
8341 8349 cookie_count, buf_info->size, buf_info->align,
8342 8350 buf_info->flags);
8343 8351
8344 8352 (void) ddi_dma_mem_free(
8345 8353 (ddi_acc_handle_t *)&buf_info->data_handle);
8346 8354 (void) ddi_dma_free_handle(
8347 8355 (ddi_dma_handle_t *)&buf_info->dma_handle);
8348 8356
8349 8357 buf_info->virt = NULL;
8350 8358 buf_info->phys = 0;
8351 8359 buf_info->dma_handle = 0;
8352 8360 buf_info->data_handle = 0;
8353 8361 goto done;
8354 8362 }
8355 8363
8356 8364 if (hba->bus_type == SBUS_FC) {
8357 8365 int32_t burstsizes_limit = 0xff;
8358 8366 int32_t ret_burst;
8359 8367
8360 8368 ret_burst =
8361 8369 ddi_dma_burstsizes(buf_info->
8362 8370 dma_handle) & burstsizes_limit;
8363 8371 if (ddi_dma_set_sbus64(buf_info->dma_handle,
8364 8372 ret_burst) == DDI_FAILURE) {
8365 8373 EMLXS_MSGF(EMLXS_CONTEXT,
8366 8374 &emlxs_mem_alloc_failed_msg,
8367 8375 "ddi_dma_set_sbus64 failed.");
8368 8376 }
8369 8377 }
8370 8378
8371 8379 /* Save Physical address */
8372 8380 buf_info->phys = dma_cookie.dmac_laddress;
8373 8381
8374 8382 /* Just to be sure, let's add this */
8375 8383 EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle,
8376 8384 (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV);
8377 8385
8378 8386 } else { /* allocate virtual memory */
8379 8387
8380 8388 buf_info->virt =
8381 8389 kmem_zalloc((size_t)buf_info->size, KM_NOSLEEP);
8382 8390 buf_info->phys = 0;
8383 8391 buf_info->data_handle = 0;
8384 8392 buf_info->dma_handle = 0;
8385 8393
8386 8394 if (buf_info->virt == (uint32_t *)0) {
8387 8395 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
8388 8396 "size=%x flags=%x", buf_info->size,
8389 8397 buf_info->flags);
8390 8398 }
8391 8399
8392 8400 }
8393 8401
8394 8402 done:
8395 8403
8396 8404 return ((uint8_t *)buf_info->virt);
8397 8405
8398 8406 } /* emlxs_mem_alloc() */
8399 8407
8400 8408
8401 8409
8402 8410 /*
8403 8411 * emlxs_mem_free:
8404 8412 *
8405 8413 * OS specific routine for memory de-allocation / unmapping
8406 8414 *
8407 8415 * The buf_info->flags field describes the memory operation requested.
8408 8416 *
8409 8417 * FC_MBUF_PHYSONLY set requests a supplied virtual address be unmapped
8410 8418 * for DMA, but not freed. The mapped physical address to be unmapped is in
8411 8419 * buf_info->phys
8412 8420 *
8413 8421 * FC_MBUF_PHYSONLY cleared requests memory be freed and unmapped for DMA only
8414 8422 * if FC_MBUF_DMA is set. The mapped physical address to be unmapped is in
8415 8423 * buf_info->phys. The virtual address to be freed is in buf_info->virt
8416 8424 */
8417 8425 /*ARGSUSED*/
8418 8426 extern void
8419 8427 emlxs_mem_free(emlxs_hba_t *hba, MBUF_INFO *buf_info)
8420 8428 {
8421 8429 if (buf_info->flags & FC_MBUF_PHYSONLY) {
8422 8430
8423 8431 if (buf_info->dma_handle) {
8424 8432 (void) ddi_dma_unbind_handle(buf_info->dma_handle);
8425 8433 (void) ddi_dma_free_handle(
8426 8434 (ddi_dma_handle_t *)&buf_info->dma_handle);
8427 8435 buf_info->dma_handle = NULL;
8428 8436 }
8429 8437
8430 8438 } else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) {
8431 8439
8432 8440 if (buf_info->dma_handle) {
8433 8441 (void) ddi_dma_unbind_handle(buf_info->dma_handle);
8434 8442 (void) ddi_dma_mem_free(
8435 8443 (ddi_acc_handle_t *)&buf_info->data_handle);
8436 8444 (void) ddi_dma_free_handle(
8437 8445 (ddi_dma_handle_t *)&buf_info->dma_handle);
8438 8446 buf_info->dma_handle = NULL;
8439 8447 buf_info->data_handle = NULL;
8440 8448 }
8441 8449
8442 8450 } else { /* allocate virtual memory */
8443 8451
8444 8452 if (buf_info->virt) {
8445 8453 kmem_free(buf_info->virt, (size_t)buf_info->size);
8446 8454 buf_info->virt = NULL;
8447 8455 }
8448 8456 }
8449 8457
8450 8458 } /* emlxs_mem_free() */
8451 8459
8452 8460
8453 8461 static int
8454 8462 emlxs_select_fcp_channel(emlxs_hba_t *hba, NODELIST *ndlp, int reset)
8455 8463 {
8456 8464 int channel;
8457 8465 int msi_id;
8458 8466
8459 8467
8460 8468 /* IO to FCP2 device or a device reset always use fcp channel */
8461 8469 if ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) || reset) {
8462 8470 return (hba->channel_fcp);
8463 8471 }
8464 8472
8465 8473
8466 8474 msi_id = emlxs_select_msiid(hba);
8467 8475 channel = emlxs_msiid_to_chan(hba, msi_id);
8468 8476
8469 8477
8470 8478
8471 8479 /* If channel is closed, then try fcp channel */
8472 8480 if (ndlp->nlp_flag[channel] & NLP_CLOSED) {
8473 8481 channel = hba->channel_fcp;
8474 8482 }
8475 8483 return (channel);
8476 8484
8477 8485 } /* emlxs_select_fcp_channel() */
8478 8486
8479 8487
8480 8488 static int32_t
8481 8489 emlxs_fast_target_reset(emlxs_port_t *port, emlxs_buf_t *sbp, NODELIST *ndlp)
8482 8490 {
8483 8491 emlxs_hba_t *hba = HBA;
8484 8492 fc_packet_t *pkt;
8485 8493 emlxs_config_t *cfg;
8486 8494 MAILBOXQ *mbq;
8487 8495 MAILBOX *mb;
8488 8496 uint32_t rc;
8489 8497
8490 8498 /*
8491 8499 * This routine provides a alternative target reset provessing
8492 8500 * method. Instead of sending an actual target reset to the
8493 8501 * NPort, we will first unreg the login to that NPort. This
8494 8502 * will cause all the outstanding IOs the quickly complete with
8495 8503 * a NO RPI local error. Next we will force the ULP to relogin
8496 8504 * to the NPort by sending an RSCN (for that NPort) to the
8497 8505 * upper layer. This method should result in a fast target
8498 8506 * reset, as far as IOs completing; however, since an actual
8499 8507 * target reset is not sent to the NPort, it is not 100%
8500 8508 * compatable. Things like reservations will not be broken.
8501 8509 * By default this option is DISABLED, and its only enabled thru
8502 8510 * a hidden configuration parameter (fast-tgt-reset).
8503 8511 */
8504 8512 rc = FC_TRAN_BUSY;
8505 8513 pkt = PRIV2PKT(sbp);
8506 8514 cfg = &CFG;
8507 8515
8508 8516 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
8509 8517 /* issue the mbox cmd to the sli */
8510 8518 mb = (MAILBOX *) mbq->mbox;
8511 8519 bzero((void *) mb, MAILBOX_CMD_BSIZE);
8512 8520 mb->un.varUnregLogin.rpi = (uint16_t)ndlp->nlp_Rpi;
8513 8521 #ifdef SLI3_SUPPORT
8514 8522 mb->un.varUnregLogin.vpi = port->vpi;
8515 8523 #endif /* SLI3_SUPPORT */
8516 8524 mb->mbxCommand = MBX_UNREG_LOGIN;
8517 8525 mb->mbxOwner = OWN_HOST;
8518 8526
8519 8527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
8520 8528 "Fast Target Reset: unreg rpi=%d tmr=%d", ndlp->nlp_Rpi,
8521 8529 cfg[CFG_FAST_TGT_RESET_TMR].current);
8522 8530
8523 8531 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
8524 8532 == MBX_SUCCESS) {
8525 8533
8526 8534 ndlp->nlp_Rpi = 0;
8527 8535
8528 8536 mutex_enter(&sbp->mtx);
8529 8537 sbp->node = (void *)ndlp;
8530 8538 sbp->did = ndlp->nlp_DID;
8531 8539 mutex_exit(&sbp->mtx);
8532 8540
8533 8541 if (pkt->pkt_rsplen) {
8534 8542 bzero((uint8_t *)pkt->pkt_resp,
8535 8543 pkt->pkt_rsplen);
8536 8544 }
8537 8545 if (cfg[CFG_FAST_TGT_RESET_TMR].current) {
8538 8546 ndlp->nlp_force_rscn = hba->timer_tics +
8539 8547 cfg[CFG_FAST_TGT_RESET_TMR].current;
8540 8548 }
8541 8549
8542 8550 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 0);
8543 8551 }
8544 8552
8545 8553 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
8546 8554 rc = FC_SUCCESS;
8547 8555 }
8548 8556 return (rc);
8549 8557 } /* emlxs_fast_target_reset() */
8550 8558
8551 8559 static int32_t
8552 8560 emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp, uint32_t *pkt_flags)
8553 8561 {
8554 8562 emlxs_hba_t *hba = HBA;
8555 8563 fc_packet_t *pkt;
8556 8564 emlxs_config_t *cfg;
8557 8565 IOCBQ *iocbq;
8558 8566 IOCB *iocb;
8559 8567 CHANNEL *cp;
8560 8568 NODELIST *ndlp;
8561 8569 char *cmd;
8562 8570 uint16_t lun;
8563 8571 FCP_CMND *fcp_cmd;
8564 8572 uint32_t did;
8565 8573 uint32_t reset = 0;
8566 8574 int channel;
8567 8575 int32_t rval;
8568 8576
8569 8577 pkt = PRIV2PKT(sbp);
8570 8578 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
8571 8579
8572 8580 /* Find target node object */
8573 8581 ndlp = emlxs_node_find_did(port, did, 1);
8574 8582
8575 8583 if (!ndlp || !ndlp->nlp_active) {
8576 8584 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
8577 8585 "Node not found. did=%x", did);
8578 8586
8579 8587 return (FC_BADPACKET);
8580 8588 }
8581 8589
8582 8590 /* When the fcp channel is closed we stop accepting any FCP cmd */
8583 8591 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) {
8584 8592 return (FC_TRAN_BUSY);
8585 8593 }
8586 8594
8587 8595 /* Snoop for target or lun reset first */
8588 8596 /* We always use FCP channel to send out target/lun reset fcp cmds */
8589 8597 /* interrupt affinity only applies to non tgt lun reset fcp cmd */
8590 8598
8591 8599 cmd = (char *)pkt->pkt_cmd;
8592 8600 lun = *((uint16_t *)cmd);
8593 8601 lun = LE_SWAP16(lun);
8594 8602
8595 8603 iocbq = &sbp->iocbq;
8596 8604 iocb = &iocbq->iocb;
8597 8605 iocbq->node = (void *) ndlp;
8598 8606
8599 8607 /* Check for target reset */
8600 8608 if (cmd[10] & 0x20) {
8601 8609 /* prepare iocb */
8602 8610 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
8603 8611 hba->channel_fcp)) != FC_SUCCESS) {
8604 8612
8605 8613 if (rval == 0xff) {
8606 8614 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
8607 8615 0, 1);
8608 8616 rval = FC_SUCCESS;
8609 8617 }
8610 8618
8611 8619 return (rval);
8612 8620 }
8613 8621
8614 8622 mutex_enter(&sbp->mtx);
8615 8623 sbp->pkt_flags |= PACKET_FCP_TGT_RESET;
8616 8624 sbp->pkt_flags |= PACKET_POLLED;
8617 8625 *pkt_flags = sbp->pkt_flags;
8618 8626 mutex_exit(&sbp->mtx);
8619 8627
8620 8628 #ifdef SAN_DIAG_SUPPORT
8621 8629 emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_TGTRESET,
8622 8630 (HBA_WWN *)&ndlp->nlp_portname, -1);
8623 8631 #endif /* SAN_DIAG_SUPPORT */
8624 8632
8625 8633 iocbq->flag |= IOCB_PRIORITY;
8626 8634
8627 8635 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
8628 8636 "Target Reset: did=%x", did);
8629 8637
8630 8638 cfg = &CFG;
8631 8639 if (cfg[CFG_FAST_TGT_RESET].current) {
8632 8640 if (emlxs_fast_target_reset(port, sbp, ndlp) ==
8633 8641 FC_SUCCESS) {
8634 8642 return (FC_SUCCESS);
8635 8643 }
8636 8644 }
8637 8645
8638 8646 /* Close the node for any further normal IO */
8639 8647 emlxs_node_close(port, ndlp, hba->channel_fcp,
8640 8648 pkt->pkt_timeout);
8641 8649
8642 8650 /* Flush the IO's on the tx queues */
8643 8651 (void) emlxs_tx_node_flush(port, ndlp,
8644 8652 &hba->chan[hba->channel_fcp], 0, sbp);
8645 8653
8646 8654 /* This is the target reset fcp cmd */
8647 8655 reset = 1;
8648 8656 }
8649 8657
8650 8658 /* Check for lun reset */
8651 8659 else if (cmd[10] & 0x10) {
8652 8660 /* prepare iocb */
8653 8661 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
8654 8662 hba->channel_fcp)) != FC_SUCCESS) {
8655 8663
8656 8664 if (rval == 0xff) {
8657 8665 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
8658 8666 0, 1);
8659 8667 rval = FC_SUCCESS;
8660 8668 }
8661 8669
8662 8670 return (rval);
8663 8671 }
8664 8672
8665 8673 mutex_enter(&sbp->mtx);
8666 8674 sbp->pkt_flags |= PACKET_FCP_LUN_RESET;
8667 8675 sbp->pkt_flags |= PACKET_POLLED;
8668 8676 *pkt_flags = sbp->pkt_flags;
8669 8677 mutex_exit(&sbp->mtx);
8670 8678
8671 8679 #ifdef SAN_DIAG_SUPPORT
8672 8680 emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_LUNRESET,
8673 8681 (HBA_WWN *)&ndlp->nlp_portname, lun);
8674 8682 #endif /* SAN_DIAG_SUPPORT */
8675 8683
8676 8684 iocbq->flag |= IOCB_PRIORITY;
8677 8685
8678 8686 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
8679 8687 "LUN Reset: did=%x lun=%02x LUN=%02x02x", did, lun,
8680 8688 cmd[0], cmd[1]);
8681 8689
8682 8690 /* Flush the IO's on the tx queues for this lun */
8683 8691 (void) emlxs_tx_lun_flush(port, ndlp, lun, sbp);
8684 8692
8685 8693 /* This is the lun reset fcp cmd */
8686 8694 reset = 1;
8687 8695 }
8688 8696
8689 8697 channel = emlxs_select_fcp_channel(hba, ndlp, reset);
8690 8698
8691 8699 #ifdef SAN_DIAG_SUPPORT
8692 8700 sbp->sd_start_time = gethrtime();
8693 8701 #endif /* SAN_DIAG_SUPPORT */
8694 8702
8695 8703 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
8696 8704 emlxs_swap_fcp_pkt(sbp);
8697 8705 #endif /* EMLXS_MODREV2X */
8698 8706
8699 8707 fcp_cmd = (FCP_CMND *) pkt->pkt_cmd;
8700 8708
8701 8709 if (fcp_cmd->fcpCntl1 == FCP_QTYPE_UNTAGGED) {
8702 8710 fcp_cmd->fcpCntl1 = FCP_QTYPE_SIMPLE;
8703 8711 }
8704 8712
8705 8713 if (reset == 0) {
8706 8714 /*
8707 8715 * tgt lun reset fcp cmd has been prepared
8708 8716 * separately in the beginning
8709 8717 */
8710 8718 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp,
8711 8719 channel)) != FC_SUCCESS) {
8712 8720
8713 8721 if (rval == 0xff) {
8714 8722 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
8715 8723 0, 1);
8716 8724 rval = FC_SUCCESS;
8717 8725 }
8718 8726
8719 8727 return (rval);
8720 8728 }
8721 8729 }
8722 8730
8723 8731 cp = &hba->chan[channel];
8724 8732 cp->ulpSendCmd++;
8725 8733
8726 8734 /* Initalize sbp */
8727 8735 mutex_enter(&sbp->mtx);
8728 8736 sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
8729 8737 ((pkt->pkt_timeout > 0xff) ? 0 : 10);
8730 8738 sbp->node = (void *)ndlp;
8731 8739 sbp->lun = lun;
8732 8740 sbp->class = iocb->ULPCLASS;
8733 8741 sbp->did = ndlp->nlp_DID;
8734 8742 mutex_exit(&sbp->mtx);
8735 8743
8736 8744 if (pkt->pkt_cmdlen) {
8737 8745 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
8738 8746 DDI_DMA_SYNC_FORDEV);
8739 8747 }
8740 8748
8741 8749 if (pkt->pkt_datalen && pkt->pkt_tran_type == FC_PKT_FCP_WRITE) {
8742 8750 EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen,
8743 8751 DDI_DMA_SYNC_FORDEV);
8744 8752 }
8745 8753
8746 8754 HBASTATS.FcpIssued++;
8747 8755
8748 8756 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
8749 8757 return (FC_SUCCESS);
8750 8758
8751 8759 } /* emlxs_send_fcp_cmd() */
8752 8760
8753 8761
8754 8762
8755 8763
8756 8764 /*
8757 8765 * We have to consider this setup works for INTX, MSI, and MSIX
8758 8766 * For INTX, intr_count is always 1
8759 8767 * For MSI, intr_count is always 2 by default
8760 8768 * For MSIX, intr_count is configurable (1, 2, 4, 8) for now.
8761 8769 */
8762 8770 extern int
8763 8771 emlxs_select_msiid(emlxs_hba_t *hba)
8764 8772 {
8765 8773 int msiid = 0;
8766 8774
8767 8775 /* We use round-robin */
8768 8776 mutex_enter(&EMLXS_MSIID_LOCK);
8769 8777 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
8770 8778 msiid = hba->last_msiid;
8771 8779 hba->last_msiid ++;
8772 8780 if (hba->last_msiid >= hba->intr_count) {
8773 8781 hba->last_msiid = 0;
8774 8782 }
8775 8783 } else {
8776 8784 /* This should work for INTX and MSI also */
8777 8785 /* For SLI3 the chan_count is always 4 */
8778 8786 /* For SLI3 the msiid is limited to chan_count */
8779 8787 msiid = hba->last_msiid;
8780 8788 hba->last_msiid ++;
8781 8789 if (hba->intr_count > hba->chan_count) {
8782 8790 if (hba->last_msiid >= hba->chan_count) {
8783 8791 hba->last_msiid = 0;
8784 8792 }
8785 8793 } else {
8786 8794 if (hba->last_msiid >= hba->intr_count) {
8787 8795 hba->last_msiid = 0;
8788 8796 }
8789 8797 }
8790 8798 }
8791 8799 mutex_exit(&EMLXS_MSIID_LOCK);
8792 8800
8793 8801 return (msiid);
8794 8802 } /* emlxs_select_msiid */
8795 8803
8796 8804
8797 8805 /*
8798 8806 * A channel has a association with a msi id.
8799 8807 * One msi id could be associated with multiple channels.
8800 8808 */
8801 8809 extern int
8802 8810 emlxs_msiid_to_chan(emlxs_hba_t *hba, int msi_id)
8803 8811 {
8804 8812 emlxs_config_t *cfg = &CFG;
8805 8813 EQ_DESC_t *eqp;
8806 8814 int chan;
8807 8815 int num_wq;
8808 8816
8809 8817 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
8810 8818 /* For SLI4 round robin all WQs associated with the msi_id */
8811 8819 eqp = &hba->sli.sli4.eq[msi_id];
8812 8820
8813 8821 mutex_enter(&eqp->lastwq_lock);
8814 8822 chan = eqp->lastwq;
8815 8823 eqp->lastwq++;
8816 8824 num_wq = cfg[CFG_NUM_WQ].current;
8817 8825 if (eqp->lastwq >= ((msi_id + 1) * num_wq)) {
8818 8826 eqp->lastwq -= num_wq;
8819 8827 }
8820 8828 mutex_exit(&eqp->lastwq_lock);
8821 8829
8822 8830 return (chan);
8823 8831 } else {
8824 8832 /* This is for SLI3 mode */
8825 8833 return (hba->msi2chan[msi_id]);
8826 8834 }
8827 8835
8828 8836 } /* emlxs_msiid_to_chan */
8829 8837
8830 8838
8831 8839 #ifdef SFCT_SUPPORT
8832 8840 static int32_t
8833 8841 emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp)
8834 8842 {
8835 8843 emlxs_hba_t *hba = HBA;
8836 8844 IOCBQ *iocbq;
8837 8845 IOCB *iocb;
8838 8846 NODELIST *ndlp;
8839 8847 CHANNEL *cp;
8840 8848 uint32_t did;
8841 8849
8842 8850 did = sbp->did;
8843 8851 ndlp = sbp->node;
8844 8852 cp = (CHANNEL *)sbp->channel;
8845 8853
8846 8854 iocbq = &sbp->iocbq;
8847 8855 iocb = &iocbq->iocb;
8848 8856
8849 8857 /* Make sure node is still active */
8850 8858 if (!ndlp->nlp_active) {
8851 8859 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
8852 8860 "*Node not found. did=%x", did);
8853 8861
8854 8862 return (FC_BADPACKET);
8855 8863 }
8856 8864
8857 8865 /* If gate is closed */
8858 8866 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) {
8859 8867 return (FC_TRAN_BUSY);
8860 8868 }
8861 8869
8862 8870 iocb->ULPCOMMAND = CMD_FCP_TRSP64_CX;
8863 8871 if (EMLXS_SLI_PREP_FCT_IOCB(port, sbp, cp->channelno) !=
8864 8872 IOERR_SUCCESS) {
8865 8873 return (FC_TRAN_BUSY);
8866 8874 }
8867 8875
8868 8876 HBASTATS.FcpIssued++;
8869 8877
8870 8878 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
8871 8879
8872 8880 return (FC_SUCCESS);
8873 8881
8874 8882 } /* emlxs_send_fct_status() */
8875 8883
8876 8884
8877 8885 static int32_t
8878 8886 emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp)
8879 8887 {
8880 8888 emlxs_hba_t *hba = HBA;
8881 8889 IOCBQ *iocbq;
8882 8890 IOCB *iocb;
8883 8891 NODELIST *ndlp;
8884 8892 CHANNEL *cp;
8885 8893 uint32_t did;
8886 8894
8887 8895 did = sbp->did;
8888 8896 ndlp = sbp->node;
8889 8897 cp = (CHANNEL *)sbp->channel;
8890 8898
8891 8899 iocbq = &sbp->iocbq;
8892 8900 iocb = &iocbq->iocb;
8893 8901
8894 8902 /* Make sure node is still active */
8895 8903 if ((ndlp == NULL) || (!ndlp->nlp_active)) {
8896 8904 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
8897 8905 "*Node not found. did=%x", did);
8898 8906
8899 8907 return (FC_BADPACKET);
8900 8908 }
8901 8909
8902 8910 /* If gate is closed */
8903 8911 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) {
8904 8912 return (FC_TRAN_BUSY);
8905 8913 }
8906 8914
8907 8915 iocb->ULPCOMMAND = CMD_ABORT_XRI_CX;
8908 8916 if (EMLXS_SLI_PREP_FCT_IOCB(port, sbp, cp->channelno) !=
8909 8917 IOERR_SUCCESS) {
8910 8918 return (FC_TRAN_BUSY);
8911 8919 }
8912 8920
8913 8921 EMLXS_SLI_ISSUE_IOCB_CMD(hba, sbp->channel, iocbq);
8914 8922
8915 8923 return (FC_SUCCESS);
8916 8924
8917 8925 } /* emlxs_send_fct_abort() */
8918 8926
8919 8927 #endif /* SFCT_SUPPORT */
8920 8928
8921 8929
8922 8930 static int32_t
|
↓ open down ↓ |
4585 lines elided |
↑ open up ↑ |
8923 8931 emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp)
8924 8932 {
8925 8933 emlxs_hba_t *hba = HBA;
8926 8934 fc_packet_t *pkt;
8927 8935 IOCBQ *iocbq;
8928 8936 IOCB *iocb;
8929 8937 CHANNEL *cp;
8930 8938 uint32_t i;
8931 8939 NODELIST *ndlp;
8932 8940 uint32_t did;
8933 - int32_t rval;
8941 + int32_t rval;
8934 8942
8935 8943 pkt = PRIV2PKT(sbp);
8936 8944 cp = &hba->chan[hba->channel_ip];
8937 8945 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
8938 8946
8939 8947 /* Check if node exists */
8940 8948 /* Broadcast did is always a success */
8941 8949 ndlp = emlxs_node_find_did(port, did, 1);
8942 8950
8943 8951 if (!ndlp || !ndlp->nlp_active) {
8944 8952 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
8945 8953 "Node not found. did=0x%x", did);
8946 8954
8947 8955 return (FC_BADPACKET);
8948 8956 }
8949 8957
8950 8958 /* Check if gate is temporarily closed */
8951 8959 if (ndlp->nlp_flag[hba->channel_ip] & NLP_CLOSED) {
8952 8960 return (FC_TRAN_BUSY);
8953 8961 }
8954 8962
8955 8963 /* Check if an exchange has been created */
8956 8964 if ((ndlp->nlp_Xri == 0) && (did != BCAST_DID)) {
8957 8965 /* No exchange. Try creating one */
8958 8966 (void) emlxs_create_xri(port, cp, ndlp);
8959 8967
8960 8968 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
8961 8969 "Adapter Busy. Exchange not found. did=0x%x", did);
8962 8970
8963 8971 return (FC_TRAN_BUSY);
8964 8972 }
8965 8973
8966 8974 /* ULP PATCH: pkt_cmdlen was found to be set to zero */
8967 8975 /* on BROADCAST commands */
8968 8976 if (pkt->pkt_cmdlen == 0) {
8969 8977 /* Set the pkt_cmdlen to the cookie size */
8970 8978 #if (EMLXS_MODREV >= EMLXS_MODREV3)
8971 8979 for (i = 0; i < pkt->pkt_cmd_cookie_cnt; i++) {
8972 8980 pkt->pkt_cmdlen += pkt->pkt_cmd_cookie[i].dmac_size;
8973 8981 }
8974 8982 #else
8975 8983 pkt->pkt_cmdlen = pkt->pkt_cmd_cookie.dmac_size;
8976 8984 #endif /* >= EMLXS_MODREV3 */
8977 8985
8978 8986 }
8979 8987
8980 8988 iocbq = &sbp->iocbq;
8981 8989 iocb = &iocbq->iocb;
8982 8990
8983 8991 iocbq->node = (void *)ndlp;
8984 8992 if ((rval = EMLXS_SLI_PREP_IP_IOCB(port, sbp)) != FC_SUCCESS) {
8985 8993
8986 8994 if (rval == 0xff) {
8987 8995 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
8988 8996 rval = FC_SUCCESS;
8989 8997 }
8990 8998
8991 8999 return (rval);
8992 9000 }
8993 9001
8994 9002 cp->ulpSendCmd++;
8995 9003
8996 9004 /* Initalize sbp */
8997 9005 mutex_enter(&sbp->mtx);
8998 9006 sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
8999 9007 ((pkt->pkt_timeout > 0xff) ? 0 : 10);
9000 9008 sbp->node = (void *)ndlp;
9001 9009 sbp->lun = EMLXS_LUN_NONE;
9002 9010 sbp->class = iocb->ULPCLASS;
9003 9011 sbp->did = did;
9004 9012 mutex_exit(&sbp->mtx);
9005 9013
9006 9014 if (pkt->pkt_cmdlen) {
9007 9015 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
9008 9016 DDI_DMA_SYNC_FORDEV);
9009 9017 }
9010 9018
9011 9019 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
9012 9020
9013 9021 return (FC_SUCCESS);
9014 9022
9015 9023 } /* emlxs_send_ip() */
9016 9024
9017 9025
9018 9026 static int32_t
9019 9027 emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp)
9020 9028 {
9021 9029 emlxs_hba_t *hba = HBA;
9022 9030 emlxs_port_t *vport;
9023 9031 fc_packet_t *pkt;
|
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
9024 9032 IOCBQ *iocbq;
9025 9033 CHANNEL *cp;
9026 9034 SERV_PARM *sp;
9027 9035 uint32_t cmd;
9028 9036 int i;
9029 9037 ELS_PKT *els_pkt;
9030 9038 NODELIST *ndlp;
9031 9039 uint32_t did;
9032 9040 char fcsp_msg[32];
9033 9041 int rc;
9034 - int32_t rval;
9042 + int32_t rval;
9035 9043 emlxs_config_t *cfg = &CFG;
9036 9044
9037 9045 fcsp_msg[0] = 0;
9038 9046 pkt = PRIV2PKT(sbp);
9039 9047 els_pkt = (ELS_PKT *)pkt->pkt_cmd;
9040 9048 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
9041 9049
9042 9050 iocbq = &sbp->iocbq;
9043 9051
9044 9052 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9045 9053 emlxs_swap_els_pkt(sbp);
9046 9054 #endif /* EMLXS_MODREV2X */
9047 9055
9048 9056 cmd = *((uint32_t *)pkt->pkt_cmd);
9049 9057 cmd &= ELS_CMD_MASK;
9050 9058
9051 9059 /* Point of no return, except for ADISC & PLOGI */
9052 9060
9053 9061 /* Check node */
9054 9062 switch (cmd) {
9055 9063 case ELS_CMD_FLOGI:
9056 9064 case ELS_CMD_FDISC:
9057 9065 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
9058 9066
9059 9067 if (emlxs_vpi_logi_notify(port, sbp)) {
9060 9068 pkt->pkt_state = FC_PKT_LOCAL_RJT;
9061 9069 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9062 9070 emlxs_unswap_pkt(sbp);
9063 9071 #endif /* EMLXS_MODREV2X */
9064 9072 return (FC_FAILURE);
9065 9073 }
9066 9074 } else {
9067 9075 /*
9068 9076 * If FLOGI is already complete, then we
9069 9077 * should not be receiving another FLOGI.
9070 9078 * Reset the link to recover.
9071 9079 */
9072 9080 if (port->flag & EMLXS_PORT_FLOGI_CMPL) {
9073 9081 pkt->pkt_state = FC_PKT_LOCAL_RJT;
9074 9082 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9075 9083 emlxs_unswap_pkt(sbp);
9076 9084 #endif /* EMLXS_MODREV2X */
9077 9085
9078 9086 (void) emlxs_reset(port, FC_FCA_LINK_RESET);
9079 9087 return (FC_FAILURE);
9080 9088 }
9081 9089
9082 9090 if (port->vpi > 0) {
9083 9091 *((uint32_t *)pkt->pkt_cmd) = ELS_CMD_FDISC;
9084 9092 }
9085 9093 }
9086 9094
9087 9095 /* Command may have been changed */
9088 9096 cmd = *((uint32_t *)pkt->pkt_cmd);
9089 9097 cmd &= ELS_CMD_MASK;
9090 9098
9091 9099 if (hba->flag & FC_NPIV_DELAY_REQUIRED) {
9092 9100 sbp->pkt_flags |= PACKET_DELAY_REQUIRED;
9093 9101 }
9094 9102
9095 9103 ndlp = NULL;
9096 9104
9097 9105 /* We will process these cmds at the bottom of this routine */
9098 9106 break;
9099 9107
9100 9108 case ELS_CMD_PLOGI:
9101 9109 /* Make sure we don't log into ourself */
9102 9110 for (i = 0; i < MAX_VPORTS; i++) {
9103 9111 vport = &VPORT(i);
9104 9112
9105 9113 if (!(vport->flag & EMLXS_INI_BOUND)) {
9106 9114 continue;
9107 9115 }
9108 9116
9109 9117 if (did == vport->did) {
9110 9118 pkt->pkt_state = FC_PKT_NPORT_RJT;
9111 9119
9112 9120 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9113 9121 emlxs_unswap_pkt(sbp);
9114 9122 #endif /* EMLXS_MODREV2X */
9115 9123
9116 9124 return (FC_FAILURE);
9117 9125 }
9118 9126 }
9119 9127
9120 9128 ndlp = NULL;
9121 9129
9122 9130 if (hba->flag & FC_PT_TO_PT) {
9123 9131 MAILBOXQ *mbox;
9124 9132
9125 9133 /* ULP bug fix */
9126 9134 if (pkt->pkt_cmd_fhdr.s_id == 0) {
9127 9135 pkt->pkt_cmd_fhdr.s_id = FP_DEFAULT_SID;
9128 9136 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_send_msg,
9129 9137 "PLOGI: P2P Fix. sid=0-->%x did=%x",
9130 9138 pkt->pkt_cmd_fhdr.s_id,
9131 9139 pkt->pkt_cmd_fhdr.d_id);
9132 9140 }
9133 9141
9134 9142 mutex_enter(&EMLXS_PORT_LOCK);
9135 9143 port->did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.s_id);
9136 9144 port->rdid = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
9137 9145 mutex_exit(&EMLXS_PORT_LOCK);
9138 9146
9139 9147 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
9140 9148 /* Update our service parms */
9141 9149 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
9142 9150 MEM_MBOX))) {
9143 9151 emlxs_mb_config_link(hba, mbox);
9144 9152
9145 9153 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba,
9146 9154 mbox, MBX_NOWAIT, 0);
9147 9155 if ((rc != MBX_BUSY) &&
9148 9156 (rc != MBX_SUCCESS)) {
9149 9157 emlxs_mem_put(hba, MEM_MBOX,
9150 9158 (void *)mbox);
9151 9159 }
9152 9160 }
9153 9161 }
9154 9162 }
9155 9163
9156 9164 /* We will process these cmds at the bottom of this routine */
9157 9165 break;
9158 9166
9159 9167 default:
9160 9168 ndlp = emlxs_node_find_did(port, did, 1);
9161 9169
9162 9170 /* If an ADISC is being sent and we have no node, */
9163 9171 /* then we must fail the ADISC now */
9164 9172 if (!ndlp && (cmd == ELS_CMD_ADISC) &&
9165 9173 (port->mode == MODE_INITIATOR)) {
9166 9174
9167 9175 /* Build the LS_RJT response */
9168 9176 els_pkt = (ELS_PKT *)pkt->pkt_resp;
9169 9177 els_pkt->elsCode = 0x01;
9170 9178 els_pkt->un.lsRjt.un.b.lsRjtRsvd0 = 0;
9171 9179 els_pkt->un.lsRjt.un.b.lsRjtRsnCode =
9172 9180 LSRJT_LOGICAL_ERR;
9173 9181 els_pkt->un.lsRjt.un.b.lsRjtRsnCodeExp =
9174 9182 LSEXP_NOTHING_MORE;
9175 9183 els_pkt->un.lsRjt.un.b.vendorUnique = 0x03;
9176 9184
9177 9185 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
9178 9186 "ADISC Rejected. Node not found. did=0x%x", did);
9179 9187
9180 9188 if (sbp->channel == NULL) {
9181 9189 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
9182 9190 sbp->channel =
9183 9191 &hba->chan[hba->channel_els];
9184 9192 } else {
9185 9193 sbp->channel =
9186 9194 &hba->chan[FC_ELS_RING];
9187 9195 }
9188 9196 }
9189 9197
9190 9198 /* Return this as rejected by the target */
9191 9199 emlxs_pkt_complete(sbp, IOSTAT_LS_RJT, 0, 1);
9192 9200
9193 9201 return (FC_SUCCESS);
9194 9202 }
9195 9203 }
9196 9204
9197 9205 /* DID == BCAST_DID is special case to indicate that */
9198 9206 /* RPI is being passed in seq_id field */
9199 9207 /* This is used by emlxs_send_logo() for target mode */
9200 9208
9201 9209 /* Initalize iocbq */
9202 9210 iocbq->node = (void *)ndlp;
9203 9211 if ((rval = EMLXS_SLI_PREP_ELS_IOCB(port, sbp)) != FC_SUCCESS) {
9204 9212
9205 9213 if (rval == 0xff) {
9206 9214 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
9207 9215 rval = FC_SUCCESS;
9208 9216 }
9209 9217
9210 9218 return (rval);
9211 9219 }
9212 9220
9213 9221 cp = &hba->chan[hba->channel_els];
9214 9222 cp->ulpSendCmd++;
9215 9223 sp = (SERV_PARM *)&els_pkt->un.logi;
9216 9224
9217 9225 /* Check cmd */
9218 9226 switch (cmd) {
9219 9227 case ELS_CMD_PRLI:
9220 9228 /*
9221 9229 * if our firmware version is 3.20 or later,
9222 9230 * set the following bits for FC-TAPE support.
9223 9231 */
9224 9232 if ((port->mode == MODE_INITIATOR) &&
9225 9233 (hba->vpd.feaLevelHigh >= 0x02) &&
9226 9234 (cfg[CFG_ADISC_SUPPORT].current != 0)) {
9227 9235 els_pkt->un.prli.ConfmComplAllowed = 1;
9228 9236 els_pkt->un.prli.Retry = 1;
9229 9237 els_pkt->un.prli.TaskRetryIdReq = 1;
9230 9238 } else {
9231 9239 els_pkt->un.prli.ConfmComplAllowed = 0;
9232 9240 els_pkt->un.prli.Retry = 0;
9233 9241 els_pkt->un.prli.TaskRetryIdReq = 0;
9234 9242 }
9235 9243
9236 9244 break;
9237 9245
9238 9246 /* This is a patch for the ULP stack. */
9239 9247
9240 9248 /*
9241 9249 * ULP only reads our service parameters once during bind_port,
9242 9250 * but the service parameters change due to topology.
9243 9251 */
9244 9252 case ELS_CMD_FLOGI:
9245 9253 case ELS_CMD_FDISC:
9246 9254 case ELS_CMD_PLOGI:
9247 9255 case ELS_CMD_PDISC:
9248 9256 /* Copy latest service parameters to payload */
9249 9257 bcopy((void *) &port->sparam, (void *)sp, sizeof (SERV_PARM));
9250 9258
9251 9259 if ((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) {
9252 9260
9253 9261 /* Clear support for virtual fabrics */
9254 9262 /* randomOffset bit controls this for FLOGI */
9255 9263 sp->cmn.randomOffset = 0;
9256 9264
9257 9265 /* Set R_A_TOV to current value */
9258 9266 sp->cmn.w2.r_a_tov =
9259 9267 LE_SWAP32((hba->fc_ratov * 1000));
9260 9268 }
9261 9269
9262 9270 if ((hba->flag & FC_NPIV_ENABLED) &&
9263 9271 (hba->flag & FC_NPIV_SUPPORTED) &&
9264 9272 (cmd == ELS_CMD_PLOGI)) {
9265 9273 emlxs_vvl_fmt_t *vvl;
9266 9274
9267 9275 sp->VALID_VENDOR_VERSION = 1;
9268 9276 vvl = (emlxs_vvl_fmt_t *)&sp->vendorVersion[0];
9269 9277 vvl->un0.w0.oui = 0x0000C9;
9270 9278 vvl->un0.word0 = LE_SWAP32(vvl->un0.word0);
9271 9279 vvl->un1.w1.vport = (port->vpi > 0) ? 1 : 0;
9272 9280 vvl->un1.word1 = LE_SWAP32(vvl->un1.word1);
9273 9281 }
9274 9282
9275 9283 #ifdef DHCHAP_SUPPORT
9276 9284 emlxs_dhc_init_sp(port, did, sp, (char **)&fcsp_msg);
9277 9285 #endif /* DHCHAP_SUPPORT */
9278 9286
9279 9287 break;
9280 9288 }
9281 9289
9282 9290 /* Initialize the sbp */
9283 9291 mutex_enter(&sbp->mtx);
9284 9292 sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
9285 9293 ((pkt->pkt_timeout > 0xff) ? 0 : 10);
9286 9294 sbp->node = (void *)ndlp;
9287 9295 sbp->lun = EMLXS_LUN_NONE;
9288 9296 sbp->did = did;
9289 9297 mutex_exit(&sbp->mtx);
9290 9298
9291 9299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_send_msg, "%s: sid=%x did=%x %s",
9292 9300 emlxs_elscmd_xlate(cmd), port->did, did, fcsp_msg);
9293 9301
9294 9302 if (pkt->pkt_cmdlen) {
9295 9303 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
9296 9304 DDI_DMA_SYNC_FORDEV);
9297 9305 }
9298 9306
9299 9307 /* Check node */
9300 9308 switch (cmd) {
9301 9309 case ELS_CMD_FLOGI:
9302 9310 case ELS_CMD_FDISC:
9303 9311 if (port->mode == MODE_INITIATOR) {
9304 9312 /* Make sure fabric node is destroyed */
9305 9313 /* It should already have been destroyed at link down */
9306 9314 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
9307 9315 ndlp = emlxs_node_find_did(port, FABRIC_DID, 1);
9308 9316 if (ndlp) {
9309 9317 if (EMLXS_SLI_UNREG_NODE(port, ndlp,
9310 9318 NULL, NULL, iocbq) == 0) {
9311 9319 /* Deferring iocb tx until */
9312 9320 /* completion of unreg */
9313 9321 return (FC_SUCCESS);
9314 9322 }
9315 9323 }
9316 9324 }
9317 9325 }
9318 9326 break;
9319 9327
9320 9328 case ELS_CMD_PLOGI:
9321 9329
9322 9330 ndlp = emlxs_node_find_did(port, did, 1);
9323 9331
9324 9332 if (ndlp && ndlp->nlp_active) {
9325 9333 /* Close the node for any further normal IO */
9326 9334 emlxs_node_close(port, ndlp, hba->channel_fcp,
9327 9335 pkt->pkt_timeout + 10);
9328 9336 emlxs_node_close(port, ndlp, hba->channel_ip,
9329 9337 pkt->pkt_timeout + 10);
9330 9338
9331 9339 /* Flush tx queues */
9332 9340 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
9333 9341
9334 9342 /* Flush chip queues */
9335 9343 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0);
9336 9344 }
9337 9345
9338 9346 break;
9339 9347
9340 9348 case ELS_CMD_PRLI:
9341 9349
9342 9350 ndlp = emlxs_node_find_did(port, did, 1);
9343 9351
9344 9352 if (ndlp && ndlp->nlp_active) {
9345 9353 /*
9346 9354 * Close the node for any further FCP IO;
9347 9355 * Flush all outstanding I/O only if
9348 9356 * "Establish Image Pair" bit is set.
9349 9357 */
9350 9358 emlxs_node_close(port, ndlp, hba->channel_fcp,
9351 9359 pkt->pkt_timeout + 10);
9352 9360
9353 9361 if (els_pkt->un.prli.estabImagePair) {
9354 9362 /* Flush tx queues */
9355 9363 (void) emlxs_tx_node_flush(port, ndlp,
9356 9364 &hba->chan[hba->channel_fcp], 0, 0);
9357 9365
9358 9366 /* Flush chip queues */
9359 9367 (void) emlxs_chipq_node_flush(port,
9360 9368 &hba->chan[hba->channel_fcp], ndlp, 0);
9361 9369 }
9362 9370 }
9363 9371
9364 9372 break;
9365 9373
9366 9374 }
9367 9375
9368 9376 HBASTATS.ElsCmdIssued++;
9369 9377
9370 9378 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
9371 9379
9372 9380 return (FC_SUCCESS);
9373 9381
9374 9382 } /* emlxs_send_els() */
9375 9383
9376 9384
9377 9385
9378 9386
9379 9387 static int32_t
9380 9388 emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp)
9381 9389 {
9382 9390 emlxs_hba_t *hba = HBA;
9383 9391 emlxs_config_t *cfg = &CFG;
9384 9392 fc_packet_t *pkt;
9385 9393 IOCBQ *iocbq;
9386 9394 IOCB *iocb;
9387 9395 NODELIST *ndlp;
9388 9396 CHANNEL *cp;
9389 9397 int i;
9390 9398 uint32_t cmd;
9391 9399 uint32_t ucmd;
9392 9400 ELS_PKT *els_pkt;
9393 9401 fc_unsol_buf_t *ubp;
9394 9402 emlxs_ub_priv_t *ub_priv;
9395 9403 uint32_t did;
9396 9404 char fcsp_msg[32];
9397 9405 uint8_t *ub_buffer;
9398 9406 int32_t rval;
9399 9407
9400 9408 fcsp_msg[0] = 0;
9401 9409 pkt = PRIV2PKT(sbp);
9402 9410 els_pkt = (ELS_PKT *)pkt->pkt_cmd;
9403 9411 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
9404 9412
9405 9413 iocbq = &sbp->iocbq;
9406 9414 iocb = &iocbq->iocb;
9407 9415
9408 9416 /* Acquire the unsolicited command this pkt is replying to */
9409 9417 if (pkt->pkt_cmd_fhdr.ox_id < EMLXS_UB_TOKEN_OFFSET) {
9410 9418 /* This is for auto replies when no ub's are used */
9411 9419 ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT;
9412 9420 ubp = NULL;
9413 9421 ub_priv = NULL;
9414 9422 ub_buffer = NULL;
9415 9423
9416 9424 #ifdef SFCT_SUPPORT
9417 9425 if (sbp->fct_cmd) {
9418 9426 fct_els_t *els =
9419 9427 (fct_els_t *)sbp->fct_cmd->cmd_specific;
9420 9428 ub_buffer = (uint8_t *)els->els_req_payload;
9421 9429 }
9422 9430 #endif /* SFCT_SUPPORT */
9423 9431
9424 9432 } else {
9425 9433 /* Find the ub buffer that goes with this reply */
9426 9434 if (!(ubp = emlxs_ub_find(port, pkt->pkt_cmd_fhdr.ox_id))) {
9427 9435 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg,
9428 9436 "ELS reply: Invalid oxid=%x",
9429 9437 pkt->pkt_cmd_fhdr.ox_id);
9430 9438 return (FC_BADPACKET);
9431 9439 }
9432 9440
9433 9441 ub_buffer = (uint8_t *)ubp->ub_buffer;
9434 9442 ub_priv = ubp->ub_fca_private;
9435 9443 ucmd = ub_priv->cmd;
9436 9444
9437 9445 ub_priv->flags |= EMLXS_UB_REPLY;
9438 9446
9439 9447 /* Reset oxid to ELS command */
9440 9448 /* We do this because the ub is only valid */
9441 9449 /* until we return from this thread */
9442 9450 pkt->pkt_cmd_fhdr.ox_id = (ucmd >> ELS_CMD_SHIFT) & 0xff;
9443 9451 }
9444 9452
9445 9453 /* Save the result */
9446 9454 sbp->ucmd = ucmd;
9447 9455
9448 9456 if (sbp->channel == NULL) {
9449 9457 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
9450 9458 sbp->channel = &hba->chan[hba->channel_els];
9451 9459 } else {
9452 9460 sbp->channel = &hba->chan[FC_ELS_RING];
9453 9461 }
9454 9462 }
9455 9463
9456 9464 /* Check for interceptions */
9457 9465 switch (ucmd) {
9458 9466
9459 9467 #ifdef ULP_PATCH2
9460 9468 case ELS_CMD_LOGO:
9461 9469 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH2)) {
9462 9470 break;
9463 9471 }
9464 9472
9465 9473 /* Check if this was generated by ULP and not us */
9466 9474 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
9467 9475
9468 9476 /*
9469 9477 * Since we replied to this already,
9470 9478 * we won't need to send this now
9471 9479 */
9472 9480 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
9473 9481
9474 9482 return (FC_SUCCESS);
9475 9483 }
9476 9484
9477 9485 break;
9478 9486 #endif /* ULP_PATCH2 */
9479 9487
9480 9488 #ifdef ULP_PATCH3
9481 9489 case ELS_CMD_PRLI:
9482 9490 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH3)) {
9483 9491 break;
9484 9492 }
9485 9493
9486 9494 /* Check if this was generated by ULP and not us */
9487 9495 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
9488 9496
9489 9497 /*
9490 9498 * Since we replied to this already,
9491 9499 * we won't need to send this now
9492 9500 */
9493 9501 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
9494 9502
9495 9503 return (FC_SUCCESS);
9496 9504 }
9497 9505
9498 9506 break;
9499 9507 #endif /* ULP_PATCH3 */
9500 9508
9501 9509
9502 9510 #ifdef ULP_PATCH4
9503 9511 case ELS_CMD_PRLO:
9504 9512 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH4)) {
9505 9513 break;
9506 9514 }
9507 9515
9508 9516 /* Check if this was generated by ULP and not us */
9509 9517 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) {
9510 9518 /*
9511 9519 * Since we replied to this already,
9512 9520 * we won't need to send this now
9513 9521 */
9514 9522 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
9515 9523
9516 9524 return (FC_SUCCESS);
9517 9525 }
9518 9526
9519 9527 break;
9520 9528 #endif /* ULP_PATCH4 */
9521 9529
9522 9530 #ifdef ULP_PATCH6
9523 9531 case ELS_CMD_RSCN:
9524 9532 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH6)) {
9525 9533 break;
9526 9534 }
9527 9535
9528 9536 /* Check if this RSCN was generated by us */
9529 9537 if (ub_priv && (ub_priv->flags & EMLXS_UB_INTERCEPT)) {
9530 9538 cmd = *((uint32_t *)pkt->pkt_cmd);
9531 9539 cmd = LE_SWAP32(cmd);
9532 9540 cmd &= ELS_CMD_MASK;
9533 9541
9534 9542 /*
9535 9543 * If ULP is accepting this,
9536 9544 * then close affected node
9537 9545 */
9538 9546 if ((port->mode == MODE_INITIATOR) && ub_buffer &&
9539 9547 cmd == ELS_CMD_ACC) {
9540 9548 fc_rscn_t *rscn;
9541 9549 uint32_t count;
9542 9550 uint32_t *lp;
9543 9551
9544 9552 /*
9545 9553 * Only the Leadville code path will
9546 9554 * come thru here. The RSCN data is NOT
9547 9555 * swapped properly for the Comstar code
9548 9556 * path.
9549 9557 */
9550 9558 lp = (uint32_t *)ub_buffer;
9551 9559 rscn = (fc_rscn_t *)lp++;
9552 9560 count =
9553 9561 ((rscn->rscn_payload_len - 4) / 4);
9554 9562
9555 9563 /* Close affected ports */
9556 9564 for (i = 0; i < count; i++, lp++) {
9557 9565 (void) emlxs_port_offline(port,
9558 9566 *lp);
9559 9567 }
9560 9568 }
9561 9569
9562 9570 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg,
9563 9571 "RSCN %s: did=%x oxid=%x rxid=%x. "
9564 9572 "Intercepted.", emlxs_elscmd_xlate(cmd),
9565 9573 did, pkt->pkt_cmd_fhdr.ox_id,
9566 9574 pkt->pkt_cmd_fhdr.rx_id);
9567 9575
9568 9576 /*
9569 9577 * Since we generated this RSCN,
9570 9578 * we won't need to send this reply
9571 9579 */
9572 9580 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
9573 9581
9574 9582 return (FC_SUCCESS);
9575 9583 }
9576 9584
9577 9585 break;
9578 9586 #endif /* ULP_PATCH6 */
9579 9587
9580 9588 case ELS_CMD_PLOGI:
9581 9589 /* Check if this PLOGI was generated by us */
9582 9590 if (ub_priv && (ub_priv->flags & EMLXS_UB_INTERCEPT)) {
9583 9591 cmd = *((uint32_t *)pkt->pkt_cmd);
9584 9592 cmd = LE_SWAP32(cmd);
9585 9593 cmd &= ELS_CMD_MASK;
9586 9594
9587 9595 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg,
9588 9596 "PLOGI %s: did=%x oxid=%x rxid=%x. "
9589 9597 "Intercepted.", emlxs_elscmd_xlate(cmd),
9590 9598 did, pkt->pkt_cmd_fhdr.ox_id,
9591 9599 pkt->pkt_cmd_fhdr.rx_id);
9592 9600
9593 9601 /*
9594 9602 * Since we generated this PLOGI,
9595 9603 * we won't need to send this reply
9596 9604 */
9597 9605 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1);
9598 9606
9599 9607 return (FC_SUCCESS);
9600 9608 }
9601 9609
9602 9610 break;
9603 9611 }
9604 9612
9605 9613 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9606 9614 emlxs_swap_els_pkt(sbp);
9607 9615 #endif /* EMLXS_MODREV2X */
9608 9616
9609 9617
9610 9618 cmd = *((uint32_t *)pkt->pkt_cmd);
9611 9619 cmd &= ELS_CMD_MASK;
9612 9620
9613 9621 /* Check if modifications are needed */
9614 9622 switch (ucmd) {
9615 9623 case (ELS_CMD_PRLI):
9616 9624
9617 9625 if (cmd == ELS_CMD_ACC) {
9618 9626 /* This is a patch for the ULP stack. */
9619 9627 /* ULP does not keep track of FCP2 support */
9620 9628 if ((port->mode == MODE_INITIATOR) &&
9621 9629 (hba->vpd.feaLevelHigh >= 0x02) &&
9622 9630 (cfg[CFG_ADISC_SUPPORT].current != 0)) {
9623 9631 els_pkt->un.prli.ConfmComplAllowed = 1;
9624 9632 els_pkt->un.prli.Retry = 1;
9625 9633 els_pkt->un.prli.TaskRetryIdReq = 1;
9626 9634 } else {
9627 9635 els_pkt->un.prli.ConfmComplAllowed = 0;
9628 9636 els_pkt->un.prli.Retry = 0;
9629 9637 els_pkt->un.prli.TaskRetryIdReq = 0;
9630 9638 }
9631 9639 }
9632 9640
9633 9641 break;
9634 9642
9635 9643 case ELS_CMD_FLOGI:
9636 9644 case ELS_CMD_FDISC:
9637 9645 if (cmd == ELS_CMD_ACC) {
9638 9646 SERV_PARM *sp = (SERV_PARM *)&els_pkt->un.logi;
9639 9647
9640 9648 /* This is a patch for the ULP stack. */
9641 9649
9642 9650 /*
9643 9651 * ULP only reads our service parameters
9644 9652 * once during bind_port, but the service
9645 9653 * parameters change due to topology.
9646 9654 */
9647 9655
9648 9656 /* Copy latest service parameters to payload */
9649 9657 bcopy((void *)&port->sparam,
9650 9658 (void *)sp, sizeof (SERV_PARM));
9651 9659
9652 9660 /* We are in pt-to-pt mode. Set R_A_TOV to default */
9653 9661 sp->cmn.w2.r_a_tov =
9654 9662 LE_SWAP32((FF_DEF_RATOV * 1000));
9655 9663
9656 9664 /* Clear support for virtual fabrics */
9657 9665 /* randomOffset bit controls this for FLOGI */
9658 9666 sp->cmn.randomOffset = 0;
9659 9667 #ifdef DHCHAP_SUPPORT
9660 9668 emlxs_dhc_init_sp(port, did, sp, (char **)&fcsp_msg);
9661 9669 #endif /* DHCHAP_SUPPORT */
9662 9670 }
9663 9671 break;
9664 9672
9665 9673 case ELS_CMD_PLOGI:
9666 9674 case ELS_CMD_PDISC:
9667 9675 if (cmd == ELS_CMD_ACC) {
9668 9676 SERV_PARM *sp = (SERV_PARM *)&els_pkt->un.logi;
9669 9677
9670 9678 /* This is a patch for the ULP stack. */
9671 9679
9672 9680 /*
9673 9681 * ULP only reads our service parameters
9674 9682 * once during bind_port, but the service
9675 9683 * parameters change due to topology.
9676 9684 */
9677 9685
9678 9686 /* Copy latest service parameters to payload */
9679 9687 bcopy((void *)&port->sparam,
9680 9688 (void *)sp, sizeof (SERV_PARM));
9681 9689
9682 9690 #ifdef DHCHAP_SUPPORT
9683 9691 emlxs_dhc_init_sp(port, did, sp, (char **)&fcsp_msg);
9684 9692 #endif /* DHCHAP_SUPPORT */
9685 9693 }
9686 9694 break;
9687 9695
9688 9696 }
9689 9697
9690 9698 /* Initalize iocbq */
9691 9699 iocbq->node = (void *)NULL;
9692 9700 if ((rval = EMLXS_SLI_PREP_ELS_IOCB(port, sbp)) != FC_SUCCESS) {
9693 9701
9694 9702 if (rval == 0xff) {
9695 9703 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
9696 9704 rval = FC_SUCCESS;
9697 9705 }
9698 9706
9699 9707 return (rval);
9700 9708 }
9701 9709
9702 9710 cp = &hba->chan[hba->channel_els];
9703 9711 cp->ulpSendCmd++;
9704 9712
9705 9713 /* Initalize sbp */
9706 9714 mutex_enter(&sbp->mtx);
9707 9715 sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
9708 9716 ((pkt->pkt_timeout > 0xff) ? 0 : 10);
9709 9717 sbp->node = (void *) NULL;
9710 9718 sbp->lun = EMLXS_LUN_NONE;
9711 9719 sbp->class = iocb->ULPCLASS;
9712 9720 sbp->did = did;
9713 9721 mutex_exit(&sbp->mtx);
9714 9722
9715 9723 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg,
9716 9724 "%s %s: did=%x oxid=%x rxid=%x %s", emlxs_elscmd_xlate(ucmd),
9717 9725 emlxs_elscmd_xlate(cmd), did, pkt->pkt_cmd_fhdr.ox_id,
9718 9726 pkt->pkt_cmd_fhdr.rx_id, fcsp_msg);
9719 9727
9720 9728 /* Process nodes */
9721 9729 switch (ucmd) {
9722 9730 case ELS_CMD_RSCN:
9723 9731 if ((port->mode == MODE_INITIATOR) && ub_buffer &&
9724 9732 cmd == ELS_CMD_ACC) {
9725 9733 fc_rscn_t *rscn;
9726 9734 uint32_t count;
9727 9735 uint32_t *lp = NULL;
9728 9736
9729 9737 /*
9730 9738 * Only the Leadville code path will come thru
9731 9739 * here. The RSCN data is NOT swapped properly
9732 9740 * for the Comstar code path.
9733 9741 */
9734 9742 lp = (uint32_t *)ub_buffer;
9735 9743 rscn = (fc_rscn_t *)lp++;
9736 9744 count = ((rscn->rscn_payload_len - 4) / 4);
9737 9745
9738 9746 /* Close affected ports */
9739 9747 for (i = 0; i < count; i++, lp++) {
9740 9748 (void) emlxs_port_offline(port, *lp);
9741 9749 }
9742 9750 }
9743 9751 break;
9744 9752
9745 9753 case ELS_CMD_PLOGI:
9746 9754 if (cmd == ELS_CMD_ACC) {
9747 9755 ndlp = emlxs_node_find_did(port, did, 1);
9748 9756
9749 9757 if (ndlp && ndlp->nlp_active) {
9750 9758 /* Close the node for any further normal IO */
9751 9759 emlxs_node_close(port, ndlp, hba->channel_fcp,
9752 9760 pkt->pkt_timeout + 10);
9753 9761 emlxs_node_close(port, ndlp, hba->channel_ip,
9754 9762 pkt->pkt_timeout + 10);
9755 9763
9756 9764 /* Flush tx queue */
9757 9765 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
9758 9766
9759 9767 /* Flush chip queue */
9760 9768 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0);
9761 9769 }
9762 9770 }
9763 9771 break;
9764 9772
9765 9773 case ELS_CMD_PRLI:
9766 9774 if (cmd == ELS_CMD_ACC) {
9767 9775 ndlp = emlxs_node_find_did(port, did, 1);
9768 9776
9769 9777 if (ndlp && ndlp->nlp_active) {
9770 9778 /* Close the node for any further normal IO */
9771 9779 emlxs_node_close(port, ndlp, hba->channel_fcp,
9772 9780 pkt->pkt_timeout + 10);
9773 9781
9774 9782 /* Flush tx queues */
9775 9783 (void) emlxs_tx_node_flush(port, ndlp,
9776 9784 &hba->chan[hba->channel_fcp], 0, 0);
9777 9785
9778 9786 /* Flush chip queues */
9779 9787 (void) emlxs_chipq_node_flush(port,
9780 9788 &hba->chan[hba->channel_fcp], ndlp, 0);
9781 9789 }
9782 9790 }
9783 9791 break;
9784 9792
9785 9793 case ELS_CMD_PRLO:
9786 9794 if (cmd == ELS_CMD_ACC) {
9787 9795 ndlp = emlxs_node_find_did(port, did, 1);
9788 9796
9789 9797 if (ndlp && ndlp->nlp_active) {
9790 9798 /* Close the node for any further normal IO */
9791 9799 emlxs_node_close(port, ndlp,
9792 9800 hba->channel_fcp, 60);
9793 9801
9794 9802 /* Flush tx queues */
9795 9803 (void) emlxs_tx_node_flush(port, ndlp,
9796 9804 &hba->chan[hba->channel_fcp], 0, 0);
9797 9805
9798 9806 /* Flush chip queues */
9799 9807 (void) emlxs_chipq_node_flush(port,
9800 9808 &hba->chan[hba->channel_fcp], ndlp, 0);
9801 9809 }
9802 9810 }
9803 9811
9804 9812 break;
9805 9813
9806 9814 case ELS_CMD_LOGO:
9807 9815 if (cmd == ELS_CMD_ACC) {
9808 9816 ndlp = emlxs_node_find_did(port, did, 1);
9809 9817
9810 9818 if (ndlp && ndlp->nlp_active) {
9811 9819 /* Close the node for any further normal IO */
9812 9820 emlxs_node_close(port, ndlp,
9813 9821 hba->channel_fcp, 60);
9814 9822 emlxs_node_close(port, ndlp,
9815 9823 hba->channel_ip, 60);
9816 9824
9817 9825 /* Flush tx queues */
9818 9826 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
9819 9827
9820 9828 /* Flush chip queues */
9821 9829 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0);
9822 9830 }
9823 9831 }
9824 9832
9825 9833 break;
9826 9834 }
9827 9835
9828 9836 if (pkt->pkt_cmdlen) {
9829 9837 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
9830 9838 DDI_DMA_SYNC_FORDEV);
9831 9839 }
9832 9840
9833 9841 HBASTATS.ElsRspIssued++;
9834 9842
9835 9843 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
9836 9844
9837 9845 return (FC_SUCCESS);
9838 9846
9839 9847 } /* emlxs_send_els_rsp() */
9840 9848
9841 9849
9842 9850 #ifdef MENLO_SUPPORT
9843 9851 static int32_t
9844 9852 emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp)
9845 9853 {
9846 9854 emlxs_hba_t *hba = HBA;
9847 9855 fc_packet_t *pkt;
9848 9856 IOCBQ *iocbq;
9849 9857 IOCB *iocb;
9850 9858 CHANNEL *cp;
9851 9859 NODELIST *ndlp;
9852 9860 uint32_t did;
9853 9861 uint32_t *lp;
9854 9862 int32_t rval;
9855 9863
9856 9864 pkt = PRIV2PKT(sbp);
9857 9865 did = EMLXS_MENLO_DID;
9858 9866 lp = (uint32_t *)pkt->pkt_cmd;
9859 9867
9860 9868 iocbq = &sbp->iocbq;
9861 9869 iocb = &iocbq->iocb;
9862 9870
9863 9871 ndlp = emlxs_node_find_did(port, did, 1);
9864 9872
9865 9873 if (!ndlp || !ndlp->nlp_active) {
9866 9874 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
9867 9875 "Node not found. did=0x%x", did);
9868 9876
9869 9877 return (FC_BADPACKET);
9870 9878 }
9871 9879
9872 9880 iocbq->node = (void *) ndlp;
9873 9881 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) {
9874 9882
9875 9883 if (rval == 0xff) {
9876 9884 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
9877 9885 rval = FC_SUCCESS;
9878 9886 }
9879 9887
9880 9888 return (rval);
9881 9889 }
9882 9890
9883 9891 cp = &hba->chan[hba->channel_ct];
9884 9892 cp->ulpSendCmd++;
9885 9893
9886 9894 if (pkt->pkt_tran_type == FC_PKT_EXCHANGE) {
9887 9895 /* Cmd phase */
9888 9896
9889 9897 /* Initalize iocb */
9890 9898 iocb->un.genreq64.param = pkt->pkt_cmd_fhdr.d_id;
9891 9899 iocb->ULPCONTEXT = 0;
9892 9900 iocb->ULPPU = 3;
9893 9901
9894 9902 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
9895 9903 "%s: [%08x,%08x,%08x,%08x]",
9896 9904 emlxs_menlo_cmd_xlate(BE_SWAP32(lp[0])), BE_SWAP32(lp[1]),
9897 9905 BE_SWAP32(lp[2]), BE_SWAP32(lp[3]), BE_SWAP32(lp[4]));
9898 9906
9899 9907 } else { /* FC_PKT_OUTBOUND */
9900 9908
9901 9909 /* MENLO_CMD_FW_DOWNLOAD Data Phase */
9902 9910 iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX;
9903 9911
9904 9912 /* Initalize iocb */
9905 9913 iocb->un.genreq64.param = 0;
9906 9914 iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id;
9907 9915 iocb->ULPPU = 1;
9908 9916
9909 9917 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
9910 9918 "%s: Data: rxid=0x%x size=%d",
9911 9919 emlxs_menlo_cmd_xlate(MENLO_CMD_FW_DOWNLOAD),
9912 9920 pkt->pkt_cmd_fhdr.rx_id, pkt->pkt_cmdlen);
9913 9921 }
9914 9922
9915 9923 /* Initalize sbp */
9916 9924 mutex_enter(&sbp->mtx);
9917 9925 sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
9918 9926 ((pkt->pkt_timeout > 0xff) ? 0 : 10);
9919 9927 sbp->node = (void *) ndlp;
9920 9928 sbp->lun = EMLXS_LUN_NONE;
9921 9929 sbp->class = iocb->ULPCLASS;
9922 9930 sbp->did = did;
9923 9931 mutex_exit(&sbp->mtx);
9924 9932
9925 9933 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
9926 9934 DDI_DMA_SYNC_FORDEV);
9927 9935
9928 9936 HBASTATS.CtCmdIssued++;
9929 9937
9930 9938 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
9931 9939
9932 9940 return (FC_SUCCESS);
9933 9941
9934 9942 } /* emlxs_send_menlo() */
9935 9943 #endif /* MENLO_SUPPORT */
9936 9944
9937 9945
|
↓ open down ↓ |
893 lines elided |
↑ open up ↑ |
9938 9946 static int32_t
9939 9947 emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp)
9940 9948 {
9941 9949 emlxs_hba_t *hba = HBA;
9942 9950 fc_packet_t *pkt;
9943 9951 IOCBQ *iocbq;
9944 9952 IOCB *iocb;
9945 9953 NODELIST *ndlp;
9946 9954 uint32_t did;
9947 9955 CHANNEL *cp;
9948 - int32_t rval;
9956 + int32_t rval;
9949 9957
9950 9958 pkt = PRIV2PKT(sbp);
9951 9959 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
9952 9960
9953 9961 iocbq = &sbp->iocbq;
9954 9962 iocb = &iocbq->iocb;
9955 9963
9956 9964 ndlp = emlxs_node_find_did(port, did, 1);
9957 9965
9958 9966 if (!ndlp || !ndlp->nlp_active) {
9959 9967 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
9960 9968 "Node not found. did=0x%x", did);
9961 9969
9962 9970 return (FC_BADPACKET);
9963 9971 }
9964 9972
9965 9973 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
9966 9974 emlxs_swap_ct_pkt(sbp);
9967 9975 #endif /* EMLXS_MODREV2X */
9968 9976
9969 9977 iocbq->node = (void *)ndlp;
9970 9978 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) {
9971 9979
9972 9980 if (rval == 0xff) {
9973 9981 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
9974 9982 rval = FC_SUCCESS;
9975 9983 }
9976 9984
9977 9985 return (rval);
9978 9986 }
9979 9987
9980 9988 cp = &hba->chan[hba->channel_ct];
9981 9989 cp->ulpSendCmd++;
9982 9990
9983 9991 /* Initalize sbp */
9984 9992 mutex_enter(&sbp->mtx);
9985 9993 sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
9986 9994 ((pkt->pkt_timeout > 0xff) ? 0 : 10);
9987 9995 sbp->node = (void *)ndlp;
9988 9996 sbp->lun = EMLXS_LUN_NONE;
9989 9997 sbp->class = iocb->ULPCLASS;
9990 9998 sbp->did = did;
9991 9999 mutex_exit(&sbp->mtx);
9992 10000
9993 10001 if (did == NAMESERVER_DID) {
9994 10002 SLI_CT_REQUEST *CtCmd;
9995 10003 uint32_t *lp0;
9996 10004
9997 10005 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
9998 10006 lp0 = (uint32_t *)pkt->pkt_cmd;
9999 10007
10000 10008 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
10001 10009 "%s: did=%x [%08x,%08x]",
10002 10010 emlxs_ctcmd_xlate(
10003 10011 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)),
10004 10012 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5]));
10005 10013
10006 10014 if (hba->flag & FC_NPIV_DELAY_REQUIRED) {
10007 10015 sbp->pkt_flags |= PACKET_DELAY_REQUIRED;
10008 10016 }
10009 10017
10010 10018 } else if (did == FDMI_DID) {
10011 10019 SLI_CT_REQUEST *CtCmd;
10012 10020 uint32_t *lp0;
10013 10021
10014 10022 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
10015 10023 lp0 = (uint32_t *)pkt->pkt_cmd;
10016 10024
10017 10025 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
10018 10026 "%s: did=%x [%08x,%08x]",
10019 10027 emlxs_mscmd_xlate(
10020 10028 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)),
10021 10029 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5]));
10022 10030 } else {
10023 10031 SLI_CT_REQUEST *CtCmd;
10024 10032 uint32_t *lp0;
10025 10033
10026 10034 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
10027 10035 lp0 = (uint32_t *)pkt->pkt_cmd;
10028 10036
10029 10037 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg,
10030 10038 "%s: did=%x [%08x,%08x]",
10031 10039 emlxs_rmcmd_xlate(
10032 10040 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)),
10033 10041 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5]));
10034 10042 }
10035 10043
10036 10044 if (pkt->pkt_cmdlen) {
10037 10045 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
10038 10046 DDI_DMA_SYNC_FORDEV);
10039 10047 }
10040 10048
10041 10049 HBASTATS.CtCmdIssued++;
10042 10050
10043 10051 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
10044 10052
10045 10053 return (FC_SUCCESS);
10046 10054
10047 10055 } /* emlxs_send_ct() */
10048 10056
10049 10057
|
↓ open down ↓ |
91 lines elided |
↑ open up ↑ |
10050 10058 static int32_t
10051 10059 emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp)
10052 10060 {
10053 10061 emlxs_hba_t *hba = HBA;
10054 10062 fc_packet_t *pkt;
10055 10063 CHANNEL *cp;
10056 10064 IOCBQ *iocbq;
10057 10065 IOCB *iocb;
10058 10066 uint32_t *cmd;
10059 10067 SLI_CT_REQUEST *CtCmd;
10060 - int32_t rval;
10068 + int32_t rval;
10061 10069
10062 10070 pkt = PRIV2PKT(sbp);
10063 10071 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
10064 10072 cmd = (uint32_t *)pkt->pkt_cmd;
10065 10073
10066 10074 iocbq = &sbp->iocbq;
10067 10075 iocb = &iocbq->iocb;
10068 10076
10069 10077 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
10070 10078 emlxs_swap_ct_pkt(sbp);
10071 10079 #endif /* EMLXS_MODREV2X */
10072 10080
10073 10081 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) {
10074 10082
10075 10083 if (rval == 0xff) {
10076 10084 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
10077 10085 rval = FC_SUCCESS;
10078 10086 }
10079 10087
10080 10088 return (rval);
10081 10089 }
10082 10090
10083 10091 cp = &hba->chan[hba->channel_ct];
10084 10092 cp->ulpSendCmd++;
10085 10093
10086 10094 /* Initalize sbp */
10087 10095 mutex_enter(&sbp->mtx);
10088 10096 sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
10089 10097 ((pkt->pkt_timeout > 0xff) ? 0 : 10);
10090 10098 sbp->node = NULL;
10091 10099 sbp->lun = EMLXS_LUN_NONE;
10092 10100 sbp->class = iocb->ULPCLASS;
10093 10101 mutex_exit(&sbp->mtx);
10094 10102
10095 10103 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_reply_msg,
10096 10104 "%s: Rsn=%x Exp=%x [%08x,%08x] rxid=%x ",
10097 10105 emlxs_rmcmd_xlate(LE_SWAP16(
10098 10106 CtCmd->CommandResponse.bits.CmdRsp)),
10099 10107 CtCmd->ReasonCode, CtCmd->Explanation,
10100 10108 LE_SWAP32(cmd[4]), LE_SWAP32(cmd[5]),
10101 10109 pkt->pkt_cmd_fhdr.rx_id);
10102 10110
10103 10111 if (pkt->pkt_cmdlen) {
10104 10112 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
10105 10113 DDI_DMA_SYNC_FORDEV);
10106 10114 }
10107 10115
10108 10116 HBASTATS.CtRspIssued++;
10109 10117
10110 10118 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
10111 10119
10112 10120 return (FC_SUCCESS);
10113 10121
10114 10122 } /* emlxs_send_ct_rsp() */
10115 10123
10116 10124
10117 10125 /*
10118 10126 * emlxs_get_instance()
10119 10127 * Given a ddi ddiinst, return a Fibre Channel (emlx) ddiinst.
10120 10128 */
10121 10129 extern uint32_t
10122 10130 emlxs_get_instance(int32_t ddiinst)
10123 10131 {
10124 10132 uint32_t i;
10125 10133 uint32_t inst;
10126 10134
10127 10135 mutex_enter(&emlxs_device.lock);
10128 10136
10129 10137 inst = MAX_FC_BRDS;
10130 10138 for (i = 0; i < emlxs_instance_count; i++) {
10131 10139 if (emlxs_instance[i] == ddiinst) {
10132 10140 inst = i;
10133 10141 break;
10134 10142 }
10135 10143 }
10136 10144
10137 10145 mutex_exit(&emlxs_device.lock);
10138 10146
10139 10147 return (inst);
10140 10148
10141 10149 } /* emlxs_get_instance() */
10142 10150
10143 10151
10144 10152 /*
10145 10153 * emlxs_add_instance()
10146 10154 * Given a ddi ddiinst, create a Fibre Channel (emlx) ddiinst.
10147 10155 * emlx ddiinsts are the order that emlxs_attach gets called, starting at 0.
10148 10156 */
10149 10157 static uint32_t
10150 10158 emlxs_add_instance(int32_t ddiinst)
10151 10159 {
10152 10160 uint32_t i;
10153 10161
10154 10162 mutex_enter(&emlxs_device.lock);
10155 10163
10156 10164 /* First see if the ddiinst already exists */
10157 10165 for (i = 0; i < emlxs_instance_count; i++) {
10158 10166 if (emlxs_instance[i] == ddiinst) {
10159 10167 break;
10160 10168 }
10161 10169 }
10162 10170
10163 10171 /* If it doesn't already exist, add it */
10164 10172 if (i >= emlxs_instance_count) {
10165 10173 if ((i = emlxs_instance_count) < MAX_FC_BRDS) {
10166 10174 emlxs_instance[i] = ddiinst;
10167 10175 emlxs_instance_count++;
10168 10176 emlxs_device.hba_count = emlxs_instance_count;
10169 10177 }
10170 10178 }
10171 10179
10172 10180 mutex_exit(&emlxs_device.lock);
10173 10181
10174 10182 return (i);
10175 10183
10176 10184 } /* emlxs_add_instance() */
10177 10185
10178 10186
10179 10187 /*ARGSUSED*/
10180 10188 extern void
10181 10189 emlxs_pkt_complete(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat,
10182 10190 uint32_t doneq)
10183 10191 {
10184 10192 emlxs_hba_t *hba;
10185 10193 emlxs_port_t *port;
10186 10194 emlxs_buf_t *fpkt;
10187 10195
10188 10196 port = sbp->port;
10189 10197
10190 10198 if (!port) {
10191 10199 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_completion_error_msg,
10192 10200 "NULL port found. sbp=%p flags=%x", sbp, sbp->pkt_flags);
10193 10201
10194 10202 return;
10195 10203 }
10196 10204
10197 10205 hba = HBA;
10198 10206
10199 10207 if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
10200 10208 (sbp->iotag)) {
10201 10209 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
10202 10210 "WARNING: Completing IO with iotag. sbp=%p iotag=%d "
10203 10211 "xri_flags=%x",
10204 10212 sbp, sbp->iotag, ((sbp->xrip)? sbp->xrip->flag:0));
10205 10213
10206 10214 emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1);
10207 10215 }
10208 10216
10209 10217 mutex_enter(&sbp->mtx);
10210 10218
10211 10219 /* Check for error conditions */
10212 10220 if (sbp->pkt_flags & (PACKET_ULP_OWNED | PACKET_COMPLETED |
10213 10221 PACKET_IN_DONEQ | PACKET_IN_COMPLETION |
10214 10222 PACKET_IN_TXQ | PACKET_IN_CHIPQ)) {
10215 10223 if (sbp->pkt_flags & PACKET_ULP_OWNED) {
10216 10224 EMLXS_MSGF(EMLXS_CONTEXT,
10217 10225 &emlxs_pkt_completion_error_msg,
10218 10226 "Packet already returned. sbp=%p flags=%x", sbp,
10219 10227 sbp->pkt_flags);
10220 10228 }
10221 10229
10222 10230 else if (sbp->pkt_flags & PACKET_COMPLETED) {
10223 10231 EMLXS_MSGF(EMLXS_CONTEXT,
10224 10232 &emlxs_pkt_completion_error_msg,
10225 10233 "Packet already completed. sbp=%p flags=%x", sbp,
10226 10234 sbp->pkt_flags);
10227 10235 }
10228 10236
10229 10237 else if (sbp->pkt_flags & PACKET_IN_DONEQ) {
10230 10238 EMLXS_MSGF(EMLXS_CONTEXT,
10231 10239 &emlxs_pkt_completion_error_msg,
10232 10240 "Pkt already on done queue. sbp=%p flags=%x", sbp,
10233 10241 sbp->pkt_flags);
10234 10242 }
10235 10243
10236 10244 else if (sbp->pkt_flags & PACKET_IN_COMPLETION) {
10237 10245 EMLXS_MSGF(EMLXS_CONTEXT,
10238 10246 &emlxs_pkt_completion_error_msg,
10239 10247 "Packet already in completion. sbp=%p flags=%x",
10240 10248 sbp, sbp->pkt_flags);
10241 10249 }
10242 10250
10243 10251 else if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
10244 10252 EMLXS_MSGF(EMLXS_CONTEXT,
10245 10253 &emlxs_pkt_completion_error_msg,
10246 10254 "Packet still on chip queue. sbp=%p flags=%x",
10247 10255 sbp, sbp->pkt_flags);
10248 10256 }
10249 10257
10250 10258 else if (sbp->pkt_flags & PACKET_IN_TXQ) {
10251 10259 EMLXS_MSGF(EMLXS_CONTEXT,
10252 10260 &emlxs_pkt_completion_error_msg,
10253 10261 "Packet still on tx queue. sbp=%p flags=%x", sbp,
10254 10262 sbp->pkt_flags);
10255 10263 }
10256 10264
10257 10265 mutex_exit(&sbp->mtx);
10258 10266 return;
10259 10267 }
10260 10268
10261 10269 /* Packet is now in completion */
10262 10270 sbp->pkt_flags |= PACKET_IN_COMPLETION;
10263 10271
10264 10272 /* Set the state if not already set */
10265 10273 if (!(sbp->pkt_flags & PACKET_STATE_VALID)) {
10266 10274 emlxs_set_pkt_state(sbp, iostat, localstat, 0);
10267 10275 }
10268 10276
10269 10277 /* Check for parent flush packet */
10270 10278 /* If pkt has a parent flush packet then adjust its count now */
10271 10279 fpkt = sbp->fpkt;
10272 10280 if (fpkt) {
10273 10281 /*
10274 10282 * We will try to NULL sbp->fpkt inside the
10275 10283 * fpkt's mutex if possible
10276 10284 */
10277 10285
10278 10286 if (!(fpkt->pkt_flags & PACKET_ULP_OWNED)) {
10279 10287 mutex_enter(&fpkt->mtx);
10280 10288 if (fpkt->flush_count) {
10281 10289 fpkt->flush_count--;
10282 10290 }
10283 10291 sbp->fpkt = NULL;
10284 10292 mutex_exit(&fpkt->mtx);
10285 10293 } else { /* fpkt has been returned already */
10286 10294
10287 10295 sbp->fpkt = NULL;
10288 10296 }
10289 10297 }
10290 10298
10291 10299 /* If pkt is polled, then wake up sleeping thread */
10292 10300 if (sbp->pkt_flags & PACKET_POLLED) {
10293 10301 /* Don't set the PACKET_ULP_OWNED flag here */
10294 10302 /* because the polling thread will do it */
10295 10303 sbp->pkt_flags |= PACKET_COMPLETED;
10296 10304 mutex_exit(&sbp->mtx);
10297 10305
10298 10306 /* Wake up sleeping thread */
10299 10307 mutex_enter(&EMLXS_PKT_LOCK);
10300 10308 cv_broadcast(&EMLXS_PKT_CV);
10301 10309 mutex_exit(&EMLXS_PKT_LOCK);
10302 10310 }
10303 10311
10304 10312 /* If packet was generated by our driver, */
10305 10313 /* then complete it immediately */
10306 10314 else if (sbp->pkt_flags & PACKET_ALLOCATED) {
10307 10315 mutex_exit(&sbp->mtx);
10308 10316
10309 10317 emlxs_iodone(sbp);
10310 10318 }
10311 10319
10312 10320 /* Put the pkt on the done queue for callback */
10313 10321 /* completion in another thread */
10314 10322 else {
10315 10323 sbp->pkt_flags |= PACKET_IN_DONEQ;
10316 10324 sbp->next = NULL;
10317 10325 mutex_exit(&sbp->mtx);
10318 10326
10319 10327 /* Put pkt on doneq, so I/O's will be completed in order */
10320 10328 mutex_enter(&EMLXS_PORT_LOCK);
10321 10329 if (hba->iodone_tail == NULL) {
10322 10330 hba->iodone_list = sbp;
10323 10331 hba->iodone_count = 1;
10324 10332 } else {
10325 10333 hba->iodone_tail->next = sbp;
10326 10334 hba->iodone_count++;
10327 10335 }
10328 10336 hba->iodone_tail = sbp;
10329 10337 mutex_exit(&EMLXS_PORT_LOCK);
10330 10338
10331 10339 /* Trigger a thread to service the doneq */
10332 10340 emlxs_thread_trigger1(&hba->iodone_thread,
10333 10341 emlxs_iodone_server);
10334 10342 }
10335 10343
10336 10344 return;
10337 10345
10338 10346 } /* emlxs_pkt_complete() */
10339 10347
10340 10348
10341 10349 #ifdef SAN_DIAG_SUPPORT
10342 10350 /*
10343 10351 * This routine is called with EMLXS_PORT_LOCK held so we can just increment
10344 10352 * normally. Don't have to use atomic operations.
10345 10353 */
10346 10354 extern void
10347 10355 emlxs_update_sd_bucket(emlxs_buf_t *sbp)
10348 10356 {
10349 10357 emlxs_port_t *vport;
10350 10358 fc_packet_t *pkt;
10351 10359 uint32_t did;
10352 10360 hrtime_t t;
10353 10361 hrtime_t delta_time;
10354 10362 int i;
10355 10363 NODELIST *ndlp;
10356 10364
10357 10365 vport = sbp->port;
10358 10366
10359 10367 if ((emlxs_sd_bucket.search_type == 0) ||
10360 10368 (vport->sd_io_latency_state != SD_COLLECTING)) {
10361 10369 return;
10362 10370 }
10363 10371
10364 10372 /* Compute the iolatency time in microseconds */
10365 10373 t = gethrtime();
10366 10374 delta_time = t - sbp->sd_start_time;
10367 10375 pkt = PRIV2PKT(sbp);
10368 10376 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
10369 10377 ndlp = emlxs_node_find_did(vport, did, 1);
10370 10378
10371 10379 if (!ndlp) {
10372 10380 return;
10373 10381 }
10374 10382
10375 10383 if (delta_time >=
10376 10384 emlxs_sd_bucket.values[SD_IO_LATENCY_MAX_BUCKETS - 1]) {
10377 10385 ndlp->sd_dev_bucket[SD_IO_LATENCY_MAX_BUCKETS - 1].
10378 10386 count++;
10379 10387 } else if (delta_time <= emlxs_sd_bucket.values[0]) {
10380 10388 ndlp->sd_dev_bucket[0].count++;
10381 10389 } else {
10382 10390 for (i = 1; i < SD_IO_LATENCY_MAX_BUCKETS; i++) {
10383 10391 if ((delta_time > emlxs_sd_bucket.values[i-1]) &&
10384 10392 (delta_time <= emlxs_sd_bucket.values[i])) {
10385 10393 ndlp->sd_dev_bucket[i].count++;
10386 10394 break;
10387 10395 }
10388 10396 }
10389 10397 }
10390 10398
10391 10399 return;
10392 10400
10393 10401 } /* emlxs_update_sd_bucket() */
10394 10402 #endif /* SAN_DIAG_SUPPORT */
10395 10403
10396 10404 /*ARGSUSED*/
10397 10405 static void
10398 10406 emlxs_iodone_server(void *arg1, void *arg2, void *arg3)
10399 10407 {
10400 10408 emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
10401 10409 emlxs_buf_t *sbp;
10402 10410
10403 10411 mutex_enter(&EMLXS_PORT_LOCK);
10404 10412
10405 10413 /* Remove one pkt from the doneq head and complete it */
10406 10414 while ((sbp = hba->iodone_list) != NULL) {
10407 10415 if ((hba->iodone_list = sbp->next) == NULL) {
10408 10416 hba->iodone_tail = NULL;
10409 10417 hba->iodone_count = 0;
10410 10418 } else {
10411 10419 hba->iodone_count--;
10412 10420 }
10413 10421
10414 10422 mutex_exit(&EMLXS_PORT_LOCK);
10415 10423
10416 10424 /* Prepare the pkt for completion */
10417 10425 mutex_enter(&sbp->mtx);
10418 10426 sbp->next = NULL;
10419 10427 sbp->pkt_flags &= ~PACKET_IN_DONEQ;
10420 10428 mutex_exit(&sbp->mtx);
10421 10429
10422 10430 /* Complete the IO now */
10423 10431 emlxs_iodone(sbp);
10424 10432
10425 10433 /* Reacquire lock and check if more work is to be done */
10426 10434 mutex_enter(&EMLXS_PORT_LOCK);
10427 10435 }
10428 10436
10429 10437 mutex_exit(&EMLXS_PORT_LOCK);
10430 10438
10431 10439 #ifdef FMA_SUPPORT
10432 10440 if (hba->flag & FC_DMA_CHECK_ERROR) {
10433 10441 emlxs_thread_spawn(hba, emlxs_restart_thread,
10434 10442 NULL, NULL);
10435 10443 }
10436 10444 #endif /* FMA_SUPPORT */
10437 10445
10438 10446 return;
10439 10447
10440 10448 } /* End emlxs_iodone_server */
10441 10449
10442 10450
10443 10451 static void
10444 10452 emlxs_iodone(emlxs_buf_t *sbp)
10445 10453 {
10446 10454 #ifdef FMA_SUPPORT
10447 10455 emlxs_port_t *port = sbp->port;
10448 10456 emlxs_hba_t *hba = port->hba;
10449 10457 #endif /* FMA_SUPPORT */
10450 10458
10451 10459 fc_packet_t *pkt;
10452 10460 CHANNEL *cp;
10453 10461
10454 10462 pkt = PRIV2PKT(sbp);
10455 10463
10456 10464 /* Check one more time that the pkt has not already been returned */
10457 10465 if (sbp->pkt_flags & PACKET_ULP_OWNED) {
10458 10466 return;
10459 10467 }
10460 10468
10461 10469 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
10462 10470 emlxs_unswap_pkt(sbp);
10463 10471 #endif /* EMLXS_MODREV2X */
10464 10472
10465 10473 mutex_enter(&sbp->mtx);
10466 10474 sbp->pkt_flags |= (PACKET_COMPLETED | PACKET_ULP_OWNED);
10467 10475 mutex_exit(&sbp->mtx);
10468 10476
10469 10477 if (pkt->pkt_comp) {
10470 10478 #ifdef FMA_SUPPORT
10471 10479 emlxs_check_dma(hba, sbp);
10472 10480 #endif /* FMA_SUPPORT */
10473 10481
10474 10482 if (sbp->channel) {
10475 10483 cp = (CHANNEL *)sbp->channel;
10476 10484 cp->ulpCmplCmd++;
10477 10485 }
10478 10486
10479 10487 (*pkt->pkt_comp) (pkt);
10480 10488 }
10481 10489
10482 10490 return;
10483 10491
10484 10492 } /* emlxs_iodone() */
10485 10493
10486 10494
10487 10495
10488 10496 extern fc_unsol_buf_t *
10489 10497 emlxs_ub_find(emlxs_port_t *port, uint32_t token)
10490 10498 {
10491 10499 emlxs_unsol_buf_t *pool;
10492 10500 fc_unsol_buf_t *ubp;
10493 10501 emlxs_ub_priv_t *ub_priv;
10494 10502
10495 10503 /* Check if this is a valid ub token */
10496 10504 if (token < EMLXS_UB_TOKEN_OFFSET) {
10497 10505 return (NULL);
10498 10506 }
10499 10507
10500 10508 mutex_enter(&EMLXS_UB_LOCK);
10501 10509
10502 10510 pool = port->ub_pool;
10503 10511 while (pool) {
10504 10512 /* Find a pool with the proper token range */
10505 10513 if (token >= pool->pool_first_token &&
10506 10514 token <= pool->pool_last_token) {
10507 10515 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[(token -
10508 10516 pool->pool_first_token)];
10509 10517 ub_priv = ubp->ub_fca_private;
10510 10518
10511 10519 if (ub_priv->token != token) {
10512 10520 EMLXS_MSGF(EMLXS_CONTEXT,
10513 10521 &emlxs_sfs_debug_msg,
10514 10522 "ub_find: Invalid token=%x", ubp, token,
10515 10523 ub_priv->token);
10516 10524
10517 10525 ubp = NULL;
10518 10526 }
10519 10527
10520 10528 else if (!(ub_priv->flags & EMLXS_UB_IN_USE)) {
10521 10529 EMLXS_MSGF(EMLXS_CONTEXT,
10522 10530 &emlxs_sfs_debug_msg,
10523 10531 "ub_find: Buffer not in use. buffer=%p "
10524 10532 "token=%x", ubp, token);
10525 10533
10526 10534 ubp = NULL;
10527 10535 }
10528 10536
10529 10537 mutex_exit(&EMLXS_UB_LOCK);
10530 10538
10531 10539 return (ubp);
10532 10540 }
10533 10541
10534 10542 pool = pool->pool_next;
10535 10543 }
10536 10544
10537 10545 mutex_exit(&EMLXS_UB_LOCK);
10538 10546
10539 10547 return (NULL);
10540 10548
10541 10549 } /* emlxs_ub_find() */
10542 10550
10543 10551
10544 10552
10545 10553 extern fc_unsol_buf_t *
10546 10554 emlxs_ub_get(emlxs_port_t *port, uint32_t size, uint32_t type,
10547 10555 uint32_t reserve)
10548 10556 {
10549 10557 emlxs_hba_t *hba = HBA;
10550 10558 emlxs_unsol_buf_t *pool;
10551 10559 fc_unsol_buf_t *ubp;
10552 10560 emlxs_ub_priv_t *ub_priv;
10553 10561 uint32_t i;
10554 10562 uint32_t resv_flag;
10555 10563 uint32_t pool_free;
10556 10564 uint32_t pool_free_resv;
10557 10565
10558 10566 mutex_enter(&EMLXS_UB_LOCK);
10559 10567
10560 10568 pool = port->ub_pool;
10561 10569 while (pool) {
10562 10570 /* Find a pool of the appropriate type and size */
10563 10571 if ((pool->pool_available == 0) ||
10564 10572 (pool->pool_type != type) ||
10565 10573 (pool->pool_buf_size < size)) {
10566 10574 goto next_pool;
10567 10575 }
10568 10576
10569 10577
10570 10578 /* Adjust free counts based on availablity */
10571 10579 /* The free reserve count gets first priority */
10572 10580 pool_free_resv =
10573 10581 min(pool->pool_free_resv, pool->pool_available);
10574 10582 pool_free =
10575 10583 min(pool->pool_free,
10576 10584 (pool->pool_available - pool_free_resv));
10577 10585
10578 10586 /* Initialize reserve flag */
10579 10587 resv_flag = reserve;
10580 10588
10581 10589 if (resv_flag) {
10582 10590 if (pool_free_resv == 0) {
10583 10591 if (pool_free == 0) {
10584 10592 goto next_pool;
10585 10593 }
10586 10594 resv_flag = 0;
10587 10595 }
10588 10596 } else if (pool_free == 0) {
10589 10597 goto next_pool;
10590 10598 }
10591 10599
10592 10600 /* Find next available free buffer in this pool */
10593 10601 for (i = 0; i < pool->pool_nentries; i++) {
10594 10602 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i];
10595 10603 ub_priv = ubp->ub_fca_private;
10596 10604
10597 10605 if (!ub_priv->available ||
10598 10606 ub_priv->flags != EMLXS_UB_FREE) {
10599 10607 continue;
10600 10608 }
10601 10609
10602 10610 ub_priv->time = hba->timer_tics;
10603 10611
10604 10612 /* Timeout in 5 minutes */
10605 10613 ub_priv->timeout = (5 * 60);
10606 10614
10607 10615 ub_priv->flags = EMLXS_UB_IN_USE;
10608 10616
10609 10617 /* Alloc the buffer from the pool */
10610 10618 if (resv_flag) {
10611 10619 ub_priv->flags |= EMLXS_UB_RESV;
10612 10620 pool->pool_free_resv--;
10613 10621 } else {
10614 10622 pool->pool_free--;
10615 10623 }
10616 10624
10617 10625 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg,
10618 10626 "ub_get: ubp=%p token=%x (%d,%d,%d,%d)", ubp,
10619 10627 ub_priv->token, pool->pool_nentries,
10620 10628 pool->pool_available, pool->pool_free,
10621 10629 pool->pool_free_resv);
10622 10630
10623 10631 mutex_exit(&EMLXS_UB_LOCK);
10624 10632
10625 10633 return (ubp);
10626 10634 }
10627 10635 next_pool:
10628 10636
10629 10637 pool = pool->pool_next;
10630 10638 }
10631 10639
10632 10640 mutex_exit(&EMLXS_UB_LOCK);
10633 10641
10634 10642 return (NULL);
10635 10643
10636 10644 } /* emlxs_ub_get() */
10637 10645
10638 10646
10639 10647
10640 10648 extern void
10641 10649 emlxs_set_pkt_state(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat,
10642 10650 uint32_t lock)
10643 10651 {
10644 10652 fc_packet_t *pkt;
10645 10653 fcp_rsp_t *fcp_rsp;
10646 10654 uint32_t i;
10647 10655 emlxs_xlat_err_t *tptr;
10648 10656 emlxs_xlat_err_t *entry;
10649 10657
10650 10658
10651 10659 pkt = PRIV2PKT(sbp);
10652 10660
10653 10661 /* Warning: Some FCT sbp's don't have */
10654 10662 /* fc_packet objects, so just return */
10655 10663 if (!pkt) {
10656 10664 return;
10657 10665 }
10658 10666
10659 10667 if (lock) {
10660 10668 mutex_enter(&sbp->mtx);
10661 10669 }
10662 10670
10663 10671 if (!(sbp->pkt_flags & PACKET_STATE_VALID)) {
10664 10672 sbp->pkt_flags |= PACKET_STATE_VALID;
10665 10673
10666 10674 /* Perform table lookup */
10667 10675 entry = NULL;
10668 10676 if (iostat != IOSTAT_LOCAL_REJECT) {
10669 10677 tptr = emlxs_iostat_tbl;
10670 10678 for (i = 0; i < IOSTAT_MAX; i++, tptr++) {
10671 10679 if (iostat == tptr->emlxs_status) {
10672 10680 entry = tptr;
10673 10681 break;
10674 10682 }
10675 10683 }
10676 10684 } else { /* iostate == IOSTAT_LOCAL_REJECT */
10677 10685
10678 10686 tptr = emlxs_ioerr_tbl;
10679 10687 for (i = 0; i < IOERR_MAX; i++, tptr++) {
10680 10688 if (localstat == tptr->emlxs_status) {
10681 10689 entry = tptr;
10682 10690 break;
10683 10691 }
10684 10692 }
10685 10693 }
10686 10694
10687 10695 if (entry) {
10688 10696 pkt->pkt_state = entry->pkt_state;
10689 10697 pkt->pkt_reason = entry->pkt_reason;
10690 10698 pkt->pkt_expln = entry->pkt_expln;
10691 10699 pkt->pkt_action = entry->pkt_action;
10692 10700 } else {
10693 10701 /* Set defaults */
10694 10702 pkt->pkt_state = FC_PKT_TRAN_ERROR;
10695 10703 pkt->pkt_reason = FC_REASON_ABORTED;
10696 10704 pkt->pkt_expln = FC_EXPLN_NONE;
10697 10705 pkt->pkt_action = FC_ACTION_RETRYABLE;
10698 10706 }
10699 10707
10700 10708
10701 10709 /* Set the residual counts and response frame */
10702 10710 /* Check if response frame was received from the chip */
10703 10711 /* If so, then the residual counts will already be set */
10704 10712 if (!(sbp->pkt_flags & (PACKET_FCP_RSP_VALID |
10705 10713 PACKET_CT_RSP_VALID | PACKET_ELS_RSP_VALID))) {
10706 10714 /* We have to create the response frame */
10707 10715 if (iostat == IOSTAT_SUCCESS) {
10708 10716 pkt->pkt_resp_resid = 0;
10709 10717 pkt->pkt_data_resid = 0;
10710 10718
10711 10719 if ((pkt->pkt_cmd_fhdr.type ==
10712 10720 FC_TYPE_SCSI_FCP) && pkt->pkt_rsplen &&
10713 10721 pkt->pkt_resp) {
10714 10722 fcp_rsp = (fcp_rsp_t *)pkt->pkt_resp;
10715 10723
10716 10724 fcp_rsp->fcp_u.fcp_status.
10717 10725 rsp_len_set = 1;
10718 10726 fcp_rsp->fcp_response_len = 8;
10719 10727 }
10720 10728 } else {
10721 10729 /* Otherwise assume no data */
10722 10730 /* and no response received */
10723 10731 pkt->pkt_data_resid = pkt->pkt_datalen;
10724 10732 pkt->pkt_resp_resid = pkt->pkt_rsplen;
10725 10733 }
10726 10734 }
10727 10735 }
10728 10736
10729 10737 if (lock) {
10730 10738 mutex_exit(&sbp->mtx);
10731 10739 }
10732 10740
10733 10741 return;
10734 10742
10735 10743 } /* emlxs_set_pkt_state() */
10736 10744
10737 10745
10738 10746 #if (EMLXS_MODREVX == EMLXS_MODREV2X)
10739 10747
10740 10748 extern void
10741 10749 emlxs_swap_service_params(SERV_PARM *sp)
10742 10750 {
10743 10751 uint16_t *p;
10744 10752 int size;
10745 10753 int i;
10746 10754
10747 10755 size = (sizeof (CSP) - 4) / 2;
10748 10756 p = (uint16_t *)&sp->cmn;
10749 10757 for (i = 0; i < size; i++) {
10750 10758 p[i] = LE_SWAP16(p[i]);
10751 10759 }
10752 10760 sp->cmn.e_d_tov = LE_SWAP32(sp->cmn.e_d_tov);
10753 10761
10754 10762 size = sizeof (CLASS_PARMS) / 2;
10755 10763 p = (uint16_t *)&sp->cls1;
10756 10764 for (i = 0; i < size; i++, p++) {
10757 10765 *p = LE_SWAP16(*p);
10758 10766 }
10759 10767
10760 10768 size = sizeof (CLASS_PARMS) / 2;
10761 10769 p = (uint16_t *)&sp->cls2;
10762 10770 for (i = 0; i < size; i++, p++) {
10763 10771 *p = LE_SWAP16(*p);
10764 10772 }
10765 10773
10766 10774 size = sizeof (CLASS_PARMS) / 2;
10767 10775 p = (uint16_t *)&sp->cls3;
10768 10776 for (i = 0; i < size; i++, p++) {
10769 10777 *p = LE_SWAP16(*p);
10770 10778 }
10771 10779
10772 10780 size = sizeof (CLASS_PARMS) / 2;
10773 10781 p = (uint16_t *)&sp->cls4;
10774 10782 for (i = 0; i < size; i++, p++) {
10775 10783 *p = LE_SWAP16(*p);
10776 10784 }
10777 10785
10778 10786 return;
10779 10787
10780 10788 } /* emlxs_swap_service_params() */
10781 10789
10782 10790 extern void
10783 10791 emlxs_unswap_pkt(emlxs_buf_t *sbp)
10784 10792 {
10785 10793 if (sbp->pkt_flags & PACKET_FCP_SWAPPED) {
10786 10794 emlxs_swap_fcp_pkt(sbp);
10787 10795 }
10788 10796
10789 10797 else if (sbp->pkt_flags & PACKET_ELS_SWAPPED) {
10790 10798 emlxs_swap_els_pkt(sbp);
10791 10799 }
10792 10800
10793 10801 else if (sbp->pkt_flags & PACKET_CT_SWAPPED) {
10794 10802 emlxs_swap_ct_pkt(sbp);
10795 10803 }
10796 10804
10797 10805 } /* emlxs_unswap_pkt() */
10798 10806
10799 10807
10800 10808 extern void
10801 10809 emlxs_swap_fcp_pkt(emlxs_buf_t *sbp)
10802 10810 {
10803 10811 fc_packet_t *pkt;
10804 10812 FCP_CMND *cmd;
10805 10813 fcp_rsp_t *rsp;
10806 10814 uint16_t *lunp;
10807 10815 uint32_t i;
10808 10816
10809 10817 mutex_enter(&sbp->mtx);
10810 10818
10811 10819 if (sbp->pkt_flags & PACKET_ALLOCATED) {
10812 10820 mutex_exit(&sbp->mtx);
10813 10821 return;
10814 10822 }
10815 10823
10816 10824 if (sbp->pkt_flags & PACKET_FCP_SWAPPED) {
10817 10825 sbp->pkt_flags &= ~PACKET_FCP_SWAPPED;
10818 10826 } else {
10819 10827 sbp->pkt_flags |= PACKET_FCP_SWAPPED;
10820 10828 }
10821 10829
10822 10830 mutex_exit(&sbp->mtx);
10823 10831
10824 10832 pkt = PRIV2PKT(sbp);
10825 10833
10826 10834 cmd = (FCP_CMND *)pkt->pkt_cmd;
10827 10835 rsp = (pkt->pkt_rsplen &&
10828 10836 (sbp->pkt_flags & PACKET_FCP_RSP_VALID)) ?
10829 10837 (fcp_rsp_t *)pkt->pkt_resp : NULL;
10830 10838
10831 10839 /* The size of data buffer needs to be swapped. */
10832 10840 cmd->fcpDl = LE_SWAP32(cmd->fcpDl);
10833 10841
10834 10842 /*
10835 10843 * Swap first 2 words of FCP CMND payload.
10836 10844 */
10837 10845 lunp = (uint16_t *)&cmd->fcpLunMsl;
10838 10846 for (i = 0; i < 4; i++) {
10839 10847 lunp[i] = LE_SWAP16(lunp[i]);
10840 10848 }
10841 10849
10842 10850 if (rsp) {
10843 10851 rsp->fcp_resid = LE_SWAP32(rsp->fcp_resid);
10844 10852 rsp->fcp_sense_len = LE_SWAP32(rsp->fcp_sense_len);
10845 10853 rsp->fcp_response_len = LE_SWAP32(rsp->fcp_response_len);
10846 10854 }
10847 10855
10848 10856 return;
10849 10857
10850 10858 } /* emlxs_swap_fcp_pkt() */
10851 10859
10852 10860
10853 10861 extern void
10854 10862 emlxs_swap_els_pkt(emlxs_buf_t *sbp)
10855 10863 {
10856 10864 fc_packet_t *pkt;
10857 10865 uint32_t *cmd;
10858 10866 uint32_t *rsp;
10859 10867 uint32_t command;
10860 10868 uint16_t *c;
10861 10869 uint32_t i;
10862 10870 uint32_t swapped;
10863 10871
10864 10872 mutex_enter(&sbp->mtx);
10865 10873
10866 10874 if (sbp->pkt_flags & PACKET_ALLOCATED) {
10867 10875 mutex_exit(&sbp->mtx);
10868 10876 return;
10869 10877 }
10870 10878
10871 10879 if (sbp->pkt_flags & PACKET_ELS_SWAPPED) {
10872 10880 sbp->pkt_flags &= ~PACKET_ELS_SWAPPED;
10873 10881 swapped = 1;
10874 10882 } else {
10875 10883 sbp->pkt_flags |= PACKET_ELS_SWAPPED;
10876 10884 swapped = 0;
10877 10885 }
10878 10886
10879 10887 mutex_exit(&sbp->mtx);
10880 10888
10881 10889 pkt = PRIV2PKT(sbp);
10882 10890
10883 10891 cmd = (uint32_t *)pkt->pkt_cmd;
10884 10892 rsp = (pkt->pkt_rsplen &&
10885 10893 (sbp->pkt_flags & PACKET_ELS_RSP_VALID)) ?
10886 10894 (uint32_t *)pkt->pkt_resp : NULL;
10887 10895
10888 10896 if (!swapped) {
10889 10897 cmd[0] = LE_SWAP32(cmd[0]);
10890 10898 command = cmd[0] & ELS_CMD_MASK;
10891 10899 } else {
10892 10900 command = cmd[0] & ELS_CMD_MASK;
10893 10901 cmd[0] = LE_SWAP32(cmd[0]);
10894 10902 }
10895 10903
10896 10904 if (rsp) {
10897 10905 rsp[0] = LE_SWAP32(rsp[0]);
10898 10906 }
10899 10907
10900 10908 switch (command) {
10901 10909 case ELS_CMD_ACC:
10902 10910 if (sbp->ucmd == ELS_CMD_ADISC) {
10903 10911 /* Hard address of originator */
10904 10912 cmd[1] = LE_SWAP32(cmd[1]);
10905 10913
10906 10914 /* N_Port ID of originator */
10907 10915 cmd[6] = LE_SWAP32(cmd[6]);
10908 10916 }
10909 10917 break;
10910 10918
10911 10919 case ELS_CMD_PLOGI:
10912 10920 case ELS_CMD_FLOGI:
10913 10921 case ELS_CMD_FDISC:
10914 10922 if (rsp) {
10915 10923 emlxs_swap_service_params((SERV_PARM *) & rsp[1]);
10916 10924 }
10917 10925 break;
10918 10926
10919 10927 case ELS_CMD_LOGO:
10920 10928 cmd[1] = LE_SWAP32(cmd[1]); /* N_Port ID */
10921 10929 break;
10922 10930
10923 10931 case ELS_CMD_RLS:
10924 10932 cmd[1] = LE_SWAP32(cmd[1]);
10925 10933
10926 10934 if (rsp) {
10927 10935 for (i = 0; i < 6; i++) {
10928 10936 rsp[1 + i] = LE_SWAP32(rsp[1 + i]);
10929 10937 }
10930 10938 }
10931 10939 break;
10932 10940
10933 10941 case ELS_CMD_ADISC:
10934 10942 cmd[1] = LE_SWAP32(cmd[1]); /* Hard address of originator */
10935 10943 cmd[6] = LE_SWAP32(cmd[6]); /* N_Port ID of originator */
10936 10944 break;
10937 10945
10938 10946 case ELS_CMD_PRLI:
10939 10947 c = (uint16_t *)&cmd[1];
10940 10948 c[1] = LE_SWAP16(c[1]);
10941 10949
10942 10950 cmd[4] = LE_SWAP32(cmd[4]);
10943 10951
10944 10952 if (rsp) {
10945 10953 rsp[4] = LE_SWAP32(rsp[4]);
10946 10954 }
10947 10955 break;
10948 10956
10949 10957 case ELS_CMD_SCR:
10950 10958 cmd[1] = LE_SWAP32(cmd[1]);
10951 10959 break;
10952 10960
10953 10961 case ELS_CMD_LINIT:
10954 10962 if (rsp) {
10955 10963 rsp[1] = LE_SWAP32(rsp[1]);
10956 10964 }
10957 10965 break;
10958 10966
10959 10967 default:
10960 10968 break;
10961 10969 }
10962 10970
10963 10971 return;
10964 10972
10965 10973 } /* emlxs_swap_els_pkt() */
10966 10974
10967 10975
10968 10976 extern void
10969 10977 emlxs_swap_ct_pkt(emlxs_buf_t *sbp)
10970 10978 {
10971 10979 fc_packet_t *pkt;
10972 10980 uint32_t *cmd;
10973 10981 uint32_t *rsp;
10974 10982 uint32_t command;
10975 10983 uint32_t i;
10976 10984 uint32_t swapped;
10977 10985
10978 10986 mutex_enter(&sbp->mtx);
10979 10987
10980 10988 if (sbp->pkt_flags & PACKET_ALLOCATED) {
10981 10989 mutex_exit(&sbp->mtx);
10982 10990 return;
10983 10991 }
10984 10992
10985 10993 if (sbp->pkt_flags & PACKET_CT_SWAPPED) {
10986 10994 sbp->pkt_flags &= ~PACKET_CT_SWAPPED;
10987 10995 swapped = 1;
10988 10996 } else {
10989 10997 sbp->pkt_flags |= PACKET_CT_SWAPPED;
10990 10998 swapped = 0;
10991 10999 }
10992 11000
10993 11001 mutex_exit(&sbp->mtx);
10994 11002
10995 11003 pkt = PRIV2PKT(sbp);
10996 11004
10997 11005 cmd = (uint32_t *)pkt->pkt_cmd;
10998 11006 rsp = (pkt->pkt_rsplen &&
10999 11007 (sbp->pkt_flags & PACKET_CT_RSP_VALID)) ?
11000 11008 (uint32_t *)pkt->pkt_resp : NULL;
11001 11009
11002 11010 if (!swapped) {
11003 11011 cmd[0] = 0x01000000;
11004 11012 command = cmd[2];
11005 11013 }
11006 11014
11007 11015 cmd[0] = LE_SWAP32(cmd[0]);
11008 11016 cmd[1] = LE_SWAP32(cmd[1]);
11009 11017 cmd[2] = LE_SWAP32(cmd[2]);
11010 11018 cmd[3] = LE_SWAP32(cmd[3]);
11011 11019
11012 11020 if (swapped) {
11013 11021 command = cmd[2];
11014 11022 }
11015 11023
11016 11024 switch ((command >> 16)) {
11017 11025 case SLI_CTNS_GA_NXT:
11018 11026 cmd[4] = LE_SWAP32(cmd[4]);
11019 11027 break;
11020 11028
11021 11029 case SLI_CTNS_GPN_ID:
11022 11030 case SLI_CTNS_GNN_ID:
11023 11031 case SLI_CTNS_RPN_ID:
11024 11032 case SLI_CTNS_RNN_ID:
11025 11033 case SLI_CTNS_RSPN_ID:
11026 11034 cmd[4] = LE_SWAP32(cmd[4]);
11027 11035 break;
11028 11036
11029 11037 case SLI_CTNS_RCS_ID:
11030 11038 case SLI_CTNS_RPT_ID:
11031 11039 cmd[4] = LE_SWAP32(cmd[4]);
11032 11040 cmd[5] = LE_SWAP32(cmd[5]);
11033 11041 break;
11034 11042
11035 11043 case SLI_CTNS_RFT_ID:
11036 11044 cmd[4] = LE_SWAP32(cmd[4]);
11037 11045
11038 11046 /* Swap FC4 types */
11039 11047 for (i = 0; i < 8; i++) {
11040 11048 cmd[5 + i] = LE_SWAP32(cmd[5 + i]);
11041 11049 }
11042 11050 break;
11043 11051
11044 11052 case SLI_CTNS_GFT_ID:
11045 11053 if (rsp) {
11046 11054 /* Swap FC4 types */
11047 11055 for (i = 0; i < 8; i++) {
11048 11056 rsp[4 + i] = LE_SWAP32(rsp[4 + i]);
11049 11057 }
11050 11058 }
11051 11059 break;
11052 11060
11053 11061 case SLI_CTNS_GCS_ID:
11054 11062 case SLI_CTNS_GSPN_ID:
11055 11063 case SLI_CTNS_GSNN_NN:
11056 11064 case SLI_CTNS_GIP_NN:
11057 11065 case SLI_CTNS_GIPA_NN:
11058 11066
11059 11067 case SLI_CTNS_GPT_ID:
11060 11068 case SLI_CTNS_GID_NN:
11061 11069 case SLI_CTNS_GNN_IP:
11062 11070 case SLI_CTNS_GIPA_IP:
11063 11071 case SLI_CTNS_GID_FT:
11064 11072 case SLI_CTNS_GID_PT:
11065 11073 case SLI_CTNS_GID_PN:
11066 11074 case SLI_CTNS_RIP_NN:
11067 11075 case SLI_CTNS_RIPA_NN:
11068 11076 case SLI_CTNS_RSNN_NN:
11069 11077 case SLI_CTNS_DA_ID:
11070 11078 case SLI_CT_RESPONSE_FS_RJT:
11071 11079 case SLI_CT_RESPONSE_FS_ACC:
11072 11080
11073 11081 default:
11074 11082 break;
11075 11083 }
11076 11084 return;
11077 11085
11078 11086 } /* emlxs_swap_ct_pkt() */
11079 11087
11080 11088
11081 11089 extern void
11082 11090 emlxs_swap_els_ub(fc_unsol_buf_t *ubp)
11083 11091 {
11084 11092 emlxs_ub_priv_t *ub_priv;
11085 11093 fc_rscn_t *rscn;
11086 11094 uint32_t count;
11087 11095 uint32_t i;
11088 11096 uint32_t *lp;
11089 11097 la_els_logi_t *logi;
11090 11098
11091 11099 ub_priv = ubp->ub_fca_private;
11092 11100
11093 11101 switch (ub_priv->cmd) {
11094 11102 case ELS_CMD_RSCN:
11095 11103 rscn = (fc_rscn_t *)ubp->ub_buffer;
11096 11104
11097 11105 rscn->rscn_payload_len = LE_SWAP16(rscn->rscn_payload_len);
11098 11106
11099 11107 count = ((rscn->rscn_payload_len - 4) / 4);
11100 11108 lp = (uint32_t *)ubp->ub_buffer + 1;
11101 11109 for (i = 0; i < count; i++, lp++) {
11102 11110 *lp = LE_SWAP32(*lp);
11103 11111 }
11104 11112
11105 11113 break;
11106 11114
11107 11115 case ELS_CMD_FLOGI:
11108 11116 case ELS_CMD_PLOGI:
11109 11117 case ELS_CMD_FDISC:
11110 11118 case ELS_CMD_PDISC:
11111 11119 logi = (la_els_logi_t *)ubp->ub_buffer;
11112 11120 emlxs_swap_service_params(
11113 11121 (SERV_PARM *)&logi->common_service);
11114 11122 break;
11115 11123
11116 11124 /* ULP handles this */
11117 11125 case ELS_CMD_LOGO:
11118 11126 case ELS_CMD_PRLI:
11119 11127 case ELS_CMD_PRLO:
11120 11128 case ELS_CMD_ADISC:
11121 11129 default:
11122 11130 break;
11123 11131 }
11124 11132
11125 11133 return;
11126 11134
11127 11135 } /* emlxs_swap_els_ub() */
11128 11136
11129 11137
11130 11138 #endif /* EMLXS_MODREV2X */
11131 11139
11132 11140
11133 11141 extern char *
11134 11142 emlxs_mode_xlate(uint32_t mode)
11135 11143 {
11136 11144 static char buffer[32];
11137 11145 uint32_t i;
11138 11146 uint32_t count;
11139 11147
11140 11148 count = sizeof (emlxs_mode_table) / sizeof (emlxs_table_t);
11141 11149 for (i = 0; i < count; i++) {
11142 11150 if (mode == emlxs_mode_table[i].code) {
11143 11151 return (emlxs_mode_table[i].string);
11144 11152 }
11145 11153 }
11146 11154
11147 11155 (void) snprintf(buffer, sizeof (buffer), "Unknown (%x)", mode);
11148 11156 return (buffer);
11149 11157
11150 11158 } /* emlxs_mode_xlate() */
11151 11159
11152 11160
11153 11161 extern char *
11154 11162 emlxs_elscmd_xlate(uint32_t elscmd)
11155 11163 {
11156 11164 static char buffer[32];
11157 11165 uint32_t i;
11158 11166 uint32_t count;
11159 11167
11160 11168 count = sizeof (emlxs_elscmd_table) / sizeof (emlxs_table_t);
11161 11169 for (i = 0; i < count; i++) {
11162 11170 if (elscmd == emlxs_elscmd_table[i].code) {
11163 11171 return (emlxs_elscmd_table[i].string);
11164 11172 }
11165 11173 }
11166 11174
11167 11175 (void) snprintf(buffer, sizeof (buffer), "ELS=0x%x", elscmd);
11168 11176 return (buffer);
11169 11177
11170 11178 } /* emlxs_elscmd_xlate() */
11171 11179
11172 11180
11173 11181 extern char *
11174 11182 emlxs_ctcmd_xlate(uint32_t ctcmd)
11175 11183 {
11176 11184 static char buffer[32];
11177 11185 uint32_t i;
11178 11186 uint32_t count;
11179 11187
11180 11188 count = sizeof (emlxs_ctcmd_table) / sizeof (emlxs_table_t);
11181 11189 for (i = 0; i < count; i++) {
11182 11190 if (ctcmd == emlxs_ctcmd_table[i].code) {
11183 11191 return (emlxs_ctcmd_table[i].string);
11184 11192 }
11185 11193 }
11186 11194
11187 11195 (void) snprintf(buffer, sizeof (buffer), "cmd=0x%x", ctcmd);
11188 11196 return (buffer);
11189 11197
11190 11198 } /* emlxs_ctcmd_xlate() */
11191 11199
11192 11200
11193 11201 #ifdef MENLO_SUPPORT
11194 11202 extern char *
11195 11203 emlxs_menlo_cmd_xlate(uint32_t cmd)
11196 11204 {
11197 11205 static char buffer[32];
11198 11206 uint32_t i;
11199 11207 uint32_t count;
11200 11208
11201 11209 count = sizeof (emlxs_menlo_cmd_table) / sizeof (emlxs_table_t);
11202 11210 for (i = 0; i < count; i++) {
11203 11211 if (cmd == emlxs_menlo_cmd_table[i].code) {
11204 11212 return (emlxs_menlo_cmd_table[i].string);
11205 11213 }
11206 11214 }
11207 11215
11208 11216 (void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", cmd);
11209 11217 return (buffer);
11210 11218
11211 11219 } /* emlxs_menlo_cmd_xlate() */
11212 11220
11213 11221 extern char *
11214 11222 emlxs_menlo_rsp_xlate(uint32_t rsp)
11215 11223 {
11216 11224 static char buffer[32];
11217 11225 uint32_t i;
11218 11226 uint32_t count;
11219 11227
11220 11228 count = sizeof (emlxs_menlo_rsp_table) / sizeof (emlxs_table_t);
11221 11229 for (i = 0; i < count; i++) {
11222 11230 if (rsp == emlxs_menlo_rsp_table[i].code) {
11223 11231 return (emlxs_menlo_rsp_table[i].string);
11224 11232 }
11225 11233 }
11226 11234
11227 11235 (void) snprintf(buffer, sizeof (buffer), "Rsp=0x%x", rsp);
11228 11236 return (buffer);
11229 11237
11230 11238 } /* emlxs_menlo_rsp_xlate() */
11231 11239
11232 11240 #endif /* MENLO_SUPPORT */
11233 11241
11234 11242
11235 11243 extern char *
11236 11244 emlxs_rmcmd_xlate(uint32_t rmcmd)
11237 11245 {
11238 11246 static char buffer[32];
11239 11247 uint32_t i;
11240 11248 uint32_t count;
11241 11249
11242 11250 count = sizeof (emlxs_rmcmd_table) / sizeof (emlxs_table_t);
11243 11251 for (i = 0; i < count; i++) {
11244 11252 if (rmcmd == emlxs_rmcmd_table[i].code) {
11245 11253 return (emlxs_rmcmd_table[i].string);
11246 11254 }
11247 11255 }
11248 11256
11249 11257 (void) snprintf(buffer, sizeof (buffer), "RM=0x%x", rmcmd);
11250 11258 return (buffer);
11251 11259
11252 11260 } /* emlxs_rmcmd_xlate() */
11253 11261
11254 11262
11255 11263
11256 11264 extern char *
11257 11265 emlxs_mscmd_xlate(uint16_t mscmd)
11258 11266 {
11259 11267 static char buffer[32];
11260 11268 uint32_t i;
11261 11269 uint32_t count;
11262 11270
11263 11271 count = sizeof (emlxs_mscmd_table) / sizeof (emlxs_table_t);
11264 11272 for (i = 0; i < count; i++) {
11265 11273 if (mscmd == emlxs_mscmd_table[i].code) {
11266 11274 return (emlxs_mscmd_table[i].string);
11267 11275 }
11268 11276 }
11269 11277
11270 11278 (void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", mscmd);
11271 11279 return (buffer);
11272 11280
11273 11281 } /* emlxs_mscmd_xlate() */
11274 11282
11275 11283
11276 11284 extern char *
11277 11285 emlxs_state_xlate(uint8_t state)
11278 11286 {
11279 11287 static char buffer[32];
11280 11288 uint32_t i;
11281 11289 uint32_t count;
11282 11290
11283 11291 count = sizeof (emlxs_state_table) / sizeof (emlxs_table_t);
11284 11292 for (i = 0; i < count; i++) {
11285 11293 if (state == emlxs_state_table[i].code) {
11286 11294 return (emlxs_state_table[i].string);
11287 11295 }
11288 11296 }
11289 11297
11290 11298 (void) snprintf(buffer, sizeof (buffer), "State=0x%x", state);
11291 11299 return (buffer);
11292 11300
11293 11301 } /* emlxs_state_xlate() */
11294 11302
11295 11303
11296 11304 extern char *
11297 11305 emlxs_error_xlate(uint8_t errno)
11298 11306 {
11299 11307 static char buffer[32];
11300 11308 uint32_t i;
11301 11309 uint32_t count;
11302 11310
11303 11311 count = sizeof (emlxs_error_table) / sizeof (emlxs_table_t);
11304 11312 for (i = 0; i < count; i++) {
11305 11313 if (errno == emlxs_error_table[i].code) {
11306 11314 return (emlxs_error_table[i].string);
11307 11315 }
11308 11316 }
11309 11317
11310 11318 (void) snprintf(buffer, sizeof (buffer), "Errno=0x%x", errno);
11311 11319 return (buffer);
11312 11320
11313 11321 } /* emlxs_error_xlate() */
11314 11322
11315 11323
11316 11324 static int
11317 11325 emlxs_pm_lower_power(dev_info_t *dip)
11318 11326 {
11319 11327 int ddiinst;
11320 11328 int emlxinst;
11321 11329 emlxs_config_t *cfg;
11322 11330 int32_t rval;
11323 11331 emlxs_hba_t *hba;
11324 11332
11325 11333 ddiinst = ddi_get_instance(dip);
11326 11334 emlxinst = emlxs_get_instance(ddiinst);
11327 11335 hba = emlxs_device.hba[emlxinst];
11328 11336 cfg = &CFG;
11329 11337
11330 11338 rval = DDI_SUCCESS;
11331 11339
11332 11340 /* Lower the power level */
11333 11341 if (cfg[CFG_PM_SUPPORT].current) {
11334 11342 rval =
11335 11343 pm_lower_power(dip, EMLXS_PM_ADAPTER,
11336 11344 EMLXS_PM_ADAPTER_DOWN);
11337 11345 } else {
11338 11346 /* We do not have kernel support of power management enabled */
11339 11347 /* therefore, call our power management routine directly */
11340 11348 rval =
11341 11349 emlxs_power(dip, EMLXS_PM_ADAPTER, EMLXS_PM_ADAPTER_DOWN);
11342 11350 }
11343 11351
11344 11352 return (rval);
11345 11353
11346 11354 } /* emlxs_pm_lower_power() */
11347 11355
11348 11356
11349 11357 static int
11350 11358 emlxs_pm_raise_power(dev_info_t *dip)
11351 11359 {
11352 11360 int ddiinst;
11353 11361 int emlxinst;
11354 11362 emlxs_config_t *cfg;
11355 11363 int32_t rval;
11356 11364 emlxs_hba_t *hba;
11357 11365
11358 11366 ddiinst = ddi_get_instance(dip);
11359 11367 emlxinst = emlxs_get_instance(ddiinst);
11360 11368 hba = emlxs_device.hba[emlxinst];
11361 11369 cfg = &CFG;
11362 11370
11363 11371 /* Raise the power level */
11364 11372 if (cfg[CFG_PM_SUPPORT].current) {
11365 11373 rval =
11366 11374 pm_raise_power(dip, EMLXS_PM_ADAPTER,
11367 11375 EMLXS_PM_ADAPTER_UP);
11368 11376 } else {
11369 11377 /* We do not have kernel support of power management enabled */
11370 11378 /* therefore, call our power management routine directly */
11371 11379 rval =
11372 11380 emlxs_power(dip, EMLXS_PM_ADAPTER, EMLXS_PM_ADAPTER_UP);
11373 11381 }
11374 11382
11375 11383 return (rval);
11376 11384
11377 11385 } /* emlxs_pm_raise_power() */
11378 11386
11379 11387
11380 11388 #ifdef IDLE_TIMER
11381 11389
11382 11390 extern int
11383 11391 emlxs_pm_busy_component(emlxs_hba_t *hba)
11384 11392 {
11385 11393 emlxs_config_t *cfg = &CFG;
11386 11394 int rval;
11387 11395
11388 11396 hba->pm_active = 1;
11389 11397
11390 11398 if (hba->pm_busy) {
11391 11399 return (DDI_SUCCESS);
11392 11400 }
11393 11401
11394 11402 mutex_enter(&EMLXS_PM_LOCK);
11395 11403
11396 11404 if (hba->pm_busy) {
11397 11405 mutex_exit(&EMLXS_PM_LOCK);
11398 11406 return (DDI_SUCCESS);
11399 11407 }
11400 11408 hba->pm_busy = 1;
11401 11409
11402 11410 mutex_exit(&EMLXS_PM_LOCK);
11403 11411
11404 11412 /* Attempt to notify system that we are busy */
11405 11413 if (cfg[CFG_PM_SUPPORT].current) {
11406 11414 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
11407 11415 "pm_busy_component.");
11408 11416
11409 11417 rval = pm_busy_component(dip, EMLXS_PM_ADAPTER);
11410 11418
11411 11419 if (rval != DDI_SUCCESS) {
11412 11420 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
11413 11421 "pm_busy_component failed. ret=%d", rval);
11414 11422
11415 11423 /* If this attempt failed then clear our flags */
11416 11424 mutex_enter(&EMLXS_PM_LOCK);
11417 11425 hba->pm_busy = 0;
11418 11426 mutex_exit(&EMLXS_PM_LOCK);
11419 11427
11420 11428 return (rval);
11421 11429 }
11422 11430 }
11423 11431
11424 11432 return (DDI_SUCCESS);
11425 11433
11426 11434 } /* emlxs_pm_busy_component() */
11427 11435
11428 11436
11429 11437 extern int
11430 11438 emlxs_pm_idle_component(emlxs_hba_t *hba)
11431 11439 {
11432 11440 emlxs_config_t *cfg = &CFG;
11433 11441 int rval;
11434 11442
11435 11443 if (!hba->pm_busy) {
11436 11444 return (DDI_SUCCESS);
11437 11445 }
11438 11446
11439 11447 mutex_enter(&EMLXS_PM_LOCK);
11440 11448
11441 11449 if (!hba->pm_busy) {
11442 11450 mutex_exit(&EMLXS_PM_LOCK);
11443 11451 return (DDI_SUCCESS);
11444 11452 }
11445 11453 hba->pm_busy = 0;
11446 11454
11447 11455 mutex_exit(&EMLXS_PM_LOCK);
11448 11456
11449 11457 if (cfg[CFG_PM_SUPPORT].current) {
11450 11458 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
11451 11459 "pm_idle_component.");
11452 11460
11453 11461 rval = pm_idle_component(dip, EMLXS_PM_ADAPTER);
11454 11462
11455 11463 if (rval != DDI_SUCCESS) {
11456 11464 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
11457 11465 "pm_idle_component failed. ret=%d", rval);
11458 11466
11459 11467 /* If this attempt failed then */
11460 11468 /* reset our flags for another attempt */
11461 11469 mutex_enter(&EMLXS_PM_LOCK);
11462 11470 hba->pm_busy = 1;
11463 11471 mutex_exit(&EMLXS_PM_LOCK);
11464 11472
11465 11473 return (rval);
11466 11474 }
11467 11475 }
11468 11476
11469 11477 return (DDI_SUCCESS);
11470 11478
11471 11479 } /* emlxs_pm_idle_component() */
11472 11480
11473 11481
11474 11482 extern void
11475 11483 emlxs_pm_idle_timer(emlxs_hba_t *hba)
11476 11484 {
11477 11485 emlxs_config_t *cfg = &CFG;
11478 11486
11479 11487 if (hba->pm_active) {
11480 11488 /* Clear active flag and reset idle timer */
11481 11489 mutex_enter(&EMLXS_PM_LOCK);
11482 11490 hba->pm_active = 0;
11483 11491 hba->pm_idle_timer =
11484 11492 hba->timer_tics + cfg[CFG_PM_IDLE].current;
11485 11493 mutex_exit(&EMLXS_PM_LOCK);
11486 11494 }
11487 11495
11488 11496 /* Check for idle timeout */
11489 11497 else if (hba->timer_tics >= hba->pm_idle_timer) {
11490 11498 if (emlxs_pm_idle_component(hba) == DDI_SUCCESS) {
11491 11499 mutex_enter(&EMLXS_PM_LOCK);
11492 11500 hba->pm_idle_timer =
11493 11501 hba->timer_tics + cfg[CFG_PM_IDLE].current;
11494 11502 mutex_exit(&EMLXS_PM_LOCK);
11495 11503 }
11496 11504 }
11497 11505
11498 11506 return;
11499 11507
11500 11508 } /* emlxs_pm_idle_timer() */
11501 11509
11502 11510 #endif /* IDLE_TIMER */
11503 11511
11504 11512
11505 11513 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4)
11506 11514 static void
11507 11515 emlxs_read_vport_prop(emlxs_hba_t *hba)
11508 11516 {
11509 11517 emlxs_port_t *port = &PPORT;
11510 11518 emlxs_config_t *cfg = &CFG;
11511 11519 char **arrayp;
11512 11520 uint8_t *s;
11513 11521 uint8_t *np;
11514 11522 NAME_TYPE pwwpn;
11515 11523 NAME_TYPE wwnn;
11516 11524 NAME_TYPE wwpn;
11517 11525 uint32_t vpi;
11518 11526 uint32_t cnt;
11519 11527 uint32_t rval;
11520 11528 uint32_t i;
11521 11529 uint32_t j;
11522 11530 uint32_t c1;
11523 11531 uint32_t sum;
11524 11532 uint32_t errors;
11525 11533 char buffer[64];
11526 11534
11527 11535 /* Check for the per adapter vport setting */
11528 11536 (void) snprintf(buffer, sizeof (buffer), "%s%d-vport", DRIVER_NAME,
11529 11537 hba->ddiinst);
11530 11538 cnt = 0;
11531 11539 arrayp = NULL;
11532 11540 rval =
11533 11541 ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
11534 11542 (DDI_PROP_DONTPASS), buffer, &arrayp, &cnt);
11535 11543
11536 11544 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
11537 11545 /* Check for the global vport setting */
11538 11546 cnt = 0;
11539 11547 arrayp = NULL;
11540 11548 rval =
11541 11549 ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
11542 11550 (DDI_PROP_DONTPASS), "vport", &arrayp, &cnt);
11543 11551 }
11544 11552
11545 11553 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
11546 11554 return;
11547 11555 }
11548 11556
11549 11557 for (i = 0; i < cnt; i++) {
11550 11558 errors = 0;
11551 11559 s = (uint8_t *)arrayp[i];
11552 11560
11553 11561 if (!s) {
11554 11562 break;
11555 11563 }
11556 11564
11557 11565 np = (uint8_t *)&pwwpn;
11558 11566 for (j = 0; j < sizeof (NAME_TYPE); j++) {
11559 11567 c1 = *s++;
11560 11568 if ((c1 >= '0') && (c1 <= '9')) {
11561 11569 sum = ((c1 - '0') << 4);
11562 11570 } else if ((c1 >= 'a') && (c1 <= 'f')) {
11563 11571 sum = ((c1 - 'a' + 10) << 4);
11564 11572 } else if ((c1 >= 'A') && (c1 <= 'F')) {
11565 11573 sum = ((c1 - 'A' + 10) << 4);
11566 11574 } else {
11567 11575 EMLXS_MSGF(EMLXS_CONTEXT,
11568 11576 &emlxs_attach_debug_msg,
11569 11577 "Config error: Invalid PWWPN found. "
11570 11578 "entry=%d byte=%d hi_nibble=%c",
11571 11579 i, j, c1);
11572 11580 errors++;
11573 11581 }
11574 11582
11575 11583 c1 = *s++;
11576 11584 if ((c1 >= '0') && (c1 <= '9')) {
11577 11585 sum |= (c1 - '0');
11578 11586 } else if ((c1 >= 'a') && (c1 <= 'f')) {
11579 11587 sum |= (c1 - 'a' + 10);
11580 11588 } else if ((c1 >= 'A') && (c1 <= 'F')) {
11581 11589 sum |= (c1 - 'A' + 10);
11582 11590 } else {
11583 11591 EMLXS_MSGF(EMLXS_CONTEXT,
11584 11592 &emlxs_attach_debug_msg,
11585 11593 "Config error: Invalid PWWPN found. "
11586 11594 "entry=%d byte=%d lo_nibble=%c",
11587 11595 i, j, c1);
11588 11596 errors++;
11589 11597 }
11590 11598
11591 11599 *np++ = (uint8_t)sum;
11592 11600 }
11593 11601
11594 11602 if (*s++ != ':') {
11595 11603 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
11596 11604 "Config error: Invalid delimiter after PWWPN. "
11597 11605 "entry=%d", i);
11598 11606 goto out;
11599 11607 }
11600 11608
11601 11609 np = (uint8_t *)&wwnn;
11602 11610 for (j = 0; j < sizeof (NAME_TYPE); j++) {
11603 11611 c1 = *s++;
11604 11612 if ((c1 >= '0') && (c1 <= '9')) {
11605 11613 sum = ((c1 - '0') << 4);
11606 11614 } else if ((c1 >= 'a') && (c1 <= 'f')) {
11607 11615 sum = ((c1 - 'a' + 10) << 4);
11608 11616 } else if ((c1 >= 'A') && (c1 <= 'F')) {
11609 11617 sum = ((c1 - 'A' + 10) << 4);
11610 11618 } else {
11611 11619 EMLXS_MSGF(EMLXS_CONTEXT,
11612 11620 &emlxs_attach_debug_msg,
11613 11621 "Config error: Invalid WWNN found. "
11614 11622 "entry=%d byte=%d hi_nibble=%c",
11615 11623 i, j, c1);
11616 11624 errors++;
11617 11625 }
11618 11626
11619 11627 c1 = *s++;
11620 11628 if ((c1 >= '0') && (c1 <= '9')) {
11621 11629 sum |= (c1 - '0');
11622 11630 } else if ((c1 >= 'a') && (c1 <= 'f')) {
11623 11631 sum |= (c1 - 'a' + 10);
11624 11632 } else if ((c1 >= 'A') && (c1 <= 'F')) {
11625 11633 sum |= (c1 - 'A' + 10);
11626 11634 } else {
11627 11635 EMLXS_MSGF(EMLXS_CONTEXT,
11628 11636 &emlxs_attach_debug_msg,
11629 11637 "Config error: Invalid WWNN found. "
11630 11638 "entry=%d byte=%d lo_nibble=%c",
11631 11639 i, j, c1);
11632 11640 errors++;
11633 11641 }
11634 11642
11635 11643 *np++ = (uint8_t)sum;
11636 11644 }
11637 11645
11638 11646 if (*s++ != ':') {
11639 11647 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
11640 11648 "Config error: Invalid delimiter after WWNN. "
11641 11649 "entry=%d", i);
11642 11650 goto out;
11643 11651 }
11644 11652
11645 11653 np = (uint8_t *)&wwpn;
11646 11654 for (j = 0; j < sizeof (NAME_TYPE); j++) {
11647 11655 c1 = *s++;
11648 11656 if ((c1 >= '0') && (c1 <= '9')) {
11649 11657 sum = ((c1 - '0') << 4);
11650 11658 } else if ((c1 >= 'a') && (c1 <= 'f')) {
11651 11659 sum = ((c1 - 'a' + 10) << 4);
11652 11660 } else if ((c1 >= 'A') && (c1 <= 'F')) {
11653 11661 sum = ((c1 - 'A' + 10) << 4);
11654 11662 } else {
11655 11663 EMLXS_MSGF(EMLXS_CONTEXT,
11656 11664 &emlxs_attach_debug_msg,
11657 11665 "Config error: Invalid WWPN found. "
11658 11666 "entry=%d byte=%d hi_nibble=%c",
11659 11667 i, j, c1);
11660 11668
11661 11669 errors++;
11662 11670 }
11663 11671
11664 11672 c1 = *s++;
11665 11673 if ((c1 >= '0') && (c1 <= '9')) {
11666 11674 sum |= (c1 - '0');
11667 11675 } else if ((c1 >= 'a') && (c1 <= 'f')) {
11668 11676 sum |= (c1 - 'a' + 10);
11669 11677 } else if ((c1 >= 'A') && (c1 <= 'F')) {
11670 11678 sum |= (c1 - 'A' + 10);
11671 11679 } else {
11672 11680 EMLXS_MSGF(EMLXS_CONTEXT,
11673 11681 &emlxs_attach_debug_msg,
11674 11682 "Config error: Invalid WWPN found. "
11675 11683 "entry=%d byte=%d lo_nibble=%c",
11676 11684 i, j, c1);
11677 11685
11678 11686 errors++;
11679 11687 }
11680 11688
11681 11689 *np++ = (uint8_t)sum;
11682 11690 }
11683 11691
11684 11692 if (*s++ != ':') {
11685 11693 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
11686 11694 "Config error: Invalid delimiter after WWPN. "
11687 11695 "entry=%d", i);
11688 11696
11689 11697 goto out;
11690 11698 }
11691 11699
11692 11700 sum = 0;
11693 11701 do {
11694 11702 c1 = *s++;
11695 11703 if ((c1 < '0') || (c1 > '9')) {
11696 11704 EMLXS_MSGF(EMLXS_CONTEXT,
11697 11705 &emlxs_attach_debug_msg,
11698 11706 "Config error: Invalid VPI found. "
11699 11707 "entry=%d c=%c vpi=%d", i, c1, sum);
11700 11708
11701 11709 goto out;
11702 11710 }
11703 11711
11704 11712 sum = (sum * 10) + (c1 - '0');
11705 11713
11706 11714 } while (*s != 0);
11707 11715
11708 11716 vpi = sum;
11709 11717
11710 11718 if (errors) {
11711 11719 continue;
11712 11720 }
11713 11721
11714 11722 /* Entry has been read */
11715 11723
11716 11724 /* Check if the physical port wwpn */
11717 11725 /* matches our physical port wwpn */
11718 11726 if (bcmp((caddr_t)&hba->wwpn, (caddr_t)&pwwpn, 8)) {
11719 11727 continue;
11720 11728 }
11721 11729
11722 11730 /* Check vpi range */
11723 11731 if ((vpi == 0) || (vpi >= MAX_VPORTS)) {
11724 11732 continue;
11725 11733 }
11726 11734
11727 11735 /* Check if port has already been configured */
11728 11736 if (hba->port[vpi].flag & EMLXS_PORT_CONFIG) {
11729 11737 continue;
11730 11738 }
11731 11739
11732 11740 /* Set the highest configured vpi */
11733 11741 if (vpi > hba->vpi_high) {
11734 11742 hba->vpi_high = vpi;
11735 11743 }
11736 11744
11737 11745 bcopy((caddr_t)&wwnn, (caddr_t)&hba->port[vpi].wwnn,
11738 11746 sizeof (NAME_TYPE));
11739 11747 bcopy((caddr_t)&wwpn, (caddr_t)&hba->port[vpi].wwpn,
11740 11748 sizeof (NAME_TYPE));
11741 11749
11742 11750 if (hba->port[vpi].snn[0] == 0) {
11743 11751 (void) strncpy((caddr_t)hba->port[vpi].snn,
11744 11752 (caddr_t)hba->snn,
11745 11753 (sizeof (hba->port[vpi].snn)-1));
11746 11754 }
11747 11755
11748 11756 if (hba->port[vpi].spn[0] == 0) {
11749 11757 (void) snprintf((caddr_t)hba->port[vpi].spn,
11750 11758 sizeof (hba->port[vpi].spn),
11751 11759 "%s VPort-%d",
11752 11760 (caddr_t)hba->spn, vpi);
11753 11761 }
11754 11762
11755 11763 hba->port[vpi].flag |=
11756 11764 (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED);
11757 11765
11758 11766 if (cfg[CFG_VPORT_RESTRICTED].current) {
11759 11767 hba->port[vpi].flag |= EMLXS_PORT_RESTRICTED;
11760 11768 }
11761 11769 }
11762 11770
11763 11771 out:
11764 11772
11765 11773 (void) ddi_prop_free((void *) arrayp);
11766 11774 return;
11767 11775
11768 11776 } /* emlxs_read_vport_prop() */
11769 11777 #endif /* EMLXS_MODREV3 || EMLXS_MODREV4 */
11770 11778
11771 11779
11772 11780 extern char *
11773 11781 emlxs_wwn_xlate(char *buffer, size_t len, uint8_t *wwn)
11774 11782 {
11775 11783 (void) snprintf(buffer, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
11776 11784 wwn[0] & 0xff, wwn[1] & 0xff, wwn[2] & 0xff, wwn[3] & 0xff,
11777 11785 wwn[4] & 0xff, wwn[5] & 0xff, wwn[6] & 0xff, wwn[7] & 0xff);
11778 11786
11779 11787 return (buffer);
11780 11788
11781 11789 } /* emlxs_wwn_xlate() */
11782 11790
11783 11791
11784 11792 extern int32_t
11785 11793 emlxs_wwn_cmp(uint8_t *wwn1, uint8_t *wwn2)
11786 11794 {
11787 11795 uint32_t i;
11788 11796
11789 11797 for (i = 0; i < 8; i ++, wwn1 ++, wwn2 ++) {
11790 11798 if (*wwn1 > *wwn2) {
11791 11799 return (1);
11792 11800 }
11793 11801 if (*wwn1 < *wwn2) {
11794 11802 return (-1);
11795 11803 }
11796 11804 }
11797 11805
11798 11806 return (0);
11799 11807
11800 11808 } /* emlxs_wwn_cmp() */
11801 11809
11802 11810
11803 11811 /* This is called at port online and offline */
11804 11812 extern void
11805 11813 emlxs_ub_flush(emlxs_port_t *port)
11806 11814 {
11807 11815 emlxs_hba_t *hba = HBA;
11808 11816 fc_unsol_buf_t *ubp;
11809 11817 emlxs_ub_priv_t *ub_priv;
11810 11818 emlxs_ub_priv_t *next;
11811 11819
11812 11820 /* Return if nothing to do */
11813 11821 if (!port->ub_wait_head) {
11814 11822 return;
11815 11823 }
11816 11824
11817 11825 mutex_enter(&EMLXS_PORT_LOCK);
11818 11826 ub_priv = port->ub_wait_head;
11819 11827 port->ub_wait_head = NULL;
11820 11828 port->ub_wait_tail = NULL;
11821 11829 mutex_exit(&EMLXS_PORT_LOCK);
11822 11830
11823 11831 while (ub_priv) {
11824 11832 next = ub_priv->next;
11825 11833 ubp = ub_priv->ubp;
11826 11834
11827 11835 /* Check if ULP is online and we have a callback function */
11828 11836 if (port->ulp_statec != FC_STATE_OFFLINE) {
11829 11837 /* Send ULP the ub buffer */
11830 11838 emlxs_ulp_unsol_cb(port, ubp);
11831 11839 } else { /* Drop the buffer */
11832 11840 (void) emlxs_fca_ub_release(port, 1, &ubp->ub_token);
11833 11841 }
11834 11842
11835 11843 ub_priv = next;
11836 11844
11837 11845 } /* while () */
11838 11846
11839 11847 return;
11840 11848
11841 11849 } /* emlxs_ub_flush() */
11842 11850
11843 11851
11844 11852 extern void
11845 11853 emlxs_ub_callback(emlxs_port_t *port, fc_unsol_buf_t *ubp)
11846 11854 {
11847 11855 emlxs_hba_t *hba = HBA;
11848 11856 emlxs_ub_priv_t *ub_priv;
11849 11857
11850 11858 ub_priv = ubp->ub_fca_private;
11851 11859
11852 11860 /* Check if ULP is online */
11853 11861 if (port->ulp_statec != FC_STATE_OFFLINE) {
11854 11862 emlxs_ulp_unsol_cb(port, ubp);
11855 11863
11856 11864 } else { /* ULP offline */
11857 11865
11858 11866 if (hba->state >= FC_LINK_UP) {
11859 11867 /* Add buffer to queue tail */
11860 11868 mutex_enter(&EMLXS_PORT_LOCK);
11861 11869
11862 11870 if (port->ub_wait_tail) {
11863 11871 port->ub_wait_tail->next = ub_priv;
11864 11872 }
11865 11873 port->ub_wait_tail = ub_priv;
11866 11874
11867 11875 if (!port->ub_wait_head) {
11868 11876 port->ub_wait_head = ub_priv;
11869 11877 }
11870 11878
11871 11879 mutex_exit(&EMLXS_PORT_LOCK);
11872 11880 } else {
11873 11881 (void) emlxs_fca_ub_release(port, 1, &ubp->ub_token);
11874 11882 }
11875 11883 }
11876 11884
11877 11885 return;
11878 11886
11879 11887 } /* emlxs_ub_callback() */
11880 11888
11881 11889
11882 11890 extern void
11883 11891 emlxs_fca_link_up(emlxs_port_t *port)
11884 11892 {
11885 11893 emlxs_ulp_statec_cb(port, port->ulp_statec);
11886 11894 return;
11887 11895
11888 11896 } /* emlxs_fca_link_up() */
11889 11897
11890 11898
11891 11899 extern void
11892 11900 emlxs_fca_link_down(emlxs_port_t *port)
11893 11901 {
11894 11902 emlxs_ulp_statec_cb(port, FC_STATE_OFFLINE);
11895 11903 return;
11896 11904
11897 11905 } /* emlxs_fca_link_down() */
11898 11906
11899 11907
11900 11908 static uint32_t
11901 11909 emlxs_integrity_check(emlxs_hba_t *hba)
11902 11910 {
11903 11911 uint32_t size;
11904 11912 uint32_t errors = 0;
11905 11913 int ddiinst = hba->ddiinst;
11906 11914
11907 11915 size = 16;
11908 11916 if (sizeof (ULP_BDL) != size) {
11909 11917 cmn_err(CE_WARN, "?%s%d: ULP_BDL size incorrect. %d != 16",
11910 11918 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDL));
11911 11919
11912 11920 errors++;
11913 11921 }
11914 11922 size = 8;
11915 11923 if (sizeof (ULP_BDE) != size) {
11916 11924 cmn_err(CE_WARN, "?%s%d: ULP_BDE size incorrect. %d != 8",
11917 11925 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDE));
11918 11926
11919 11927 errors++;
11920 11928 }
11921 11929 size = 12;
11922 11930 if (sizeof (ULP_BDE64) != size) {
11923 11931 cmn_err(CE_WARN, "?%s%d: ULP_BDE64 size incorrect. %d != 12",
11924 11932 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDE64));
11925 11933
11926 11934 errors++;
11927 11935 }
11928 11936 size = 16;
11929 11937 if (sizeof (HBQE_t) != size) {
11930 11938 cmn_err(CE_WARN, "?%s%d: HBQE size incorrect. %d != 16",
11931 11939 DRIVER_NAME, ddiinst, (int)sizeof (HBQE_t));
11932 11940
11933 11941 errors++;
11934 11942 }
11935 11943 size = 8;
11936 11944 if (sizeof (HGP) != size) {
11937 11945 cmn_err(CE_WARN, "?%s%d: HGP size incorrect. %d != 8",
11938 11946 DRIVER_NAME, ddiinst, (int)sizeof (HGP));
11939 11947
11940 11948 errors++;
11941 11949 }
11942 11950 if (sizeof (PGP) != size) {
11943 11951 cmn_err(CE_WARN, "?%s%d: PGP size incorrect. %d != 8",
11944 11952 DRIVER_NAME, ddiinst, (int)sizeof (PGP));
11945 11953
11946 11954 errors++;
11947 11955 }
11948 11956 size = 4;
11949 11957 if (sizeof (WORD5) != size) {
11950 11958 cmn_err(CE_WARN, "?%s%d: WORD5 size incorrect. %d != 4",
11951 11959 DRIVER_NAME, ddiinst, (int)sizeof (WORD5));
11952 11960
11953 11961 errors++;
11954 11962 }
11955 11963 size = 124;
11956 11964 if (sizeof (MAILVARIANTS) != size) {
11957 11965 cmn_err(CE_WARN, "?%s%d: MAILVARIANTS size incorrect. "
11958 11966 "%d != 124", DRIVER_NAME, ddiinst,
11959 11967 (int)sizeof (MAILVARIANTS));
11960 11968
11961 11969 errors++;
11962 11970 }
11963 11971 size = 128;
11964 11972 if (sizeof (SLI1_DESC) != size) {
11965 11973 cmn_err(CE_WARN, "?%s%d: SLI1_DESC size incorrect. %d != 128",
11966 11974 DRIVER_NAME, ddiinst, (int)sizeof (SLI1_DESC));
11967 11975
11968 11976 errors++;
11969 11977 }
11970 11978 if (sizeof (SLI2_DESC) != size) {
11971 11979 cmn_err(CE_WARN, "?%s%d: SLI2_DESC size incorrect. %d != 128",
11972 11980 DRIVER_NAME, ddiinst, (int)sizeof (SLI2_DESC));
11973 11981
11974 11982 errors++;
11975 11983 }
11976 11984 size = MBOX_SIZE;
11977 11985 if (sizeof (MAILBOX) != size) {
11978 11986 cmn_err(CE_WARN, "?%s%d: MAILBOX size incorrect. %d != %d",
11979 11987 DRIVER_NAME, ddiinst, (int)sizeof (MAILBOX), MBOX_SIZE);
11980 11988
11981 11989 errors++;
11982 11990 }
11983 11991 size = PCB_SIZE;
11984 11992 if (sizeof (PCB) != size) {
11985 11993 cmn_err(CE_WARN, "?%s%d: PCB size incorrect. %d != %d",
11986 11994 DRIVER_NAME, ddiinst, (int)sizeof (PCB), PCB_SIZE);
11987 11995
11988 11996 errors++;
11989 11997 }
11990 11998 size = 260;
11991 11999 if (sizeof (ATTRIBUTE_ENTRY) != size) {
11992 12000 cmn_err(CE_WARN, "?%s%d: ATTRIBUTE_ENTRY size incorrect. "
11993 12001 "%d != 260", DRIVER_NAME, ddiinst,
11994 12002 (int)sizeof (ATTRIBUTE_ENTRY));
11995 12003
11996 12004 errors++;
11997 12005 }
11998 12006 size = SLI_SLIM1_SIZE;
11999 12007 if (sizeof (SLIM1) != size) {
12000 12008 cmn_err(CE_WARN, "?%s%d: SLIM1 size incorrect. %d != %d",
12001 12009 DRIVER_NAME, ddiinst, (int)sizeof (SLIM1), SLI_SLIM1_SIZE);
12002 12010
12003 12011 errors++;
12004 12012 }
12005 12013 size = SLI3_IOCB_CMD_SIZE;
12006 12014 if (sizeof (IOCB) != size) {
12007 12015 cmn_err(CE_WARN, "?%s%d: IOCB size incorrect. %d != %d",
12008 12016 DRIVER_NAME, ddiinst, (int)sizeof (IOCB),
12009 12017 SLI3_IOCB_CMD_SIZE);
12010 12018
12011 12019 errors++;
12012 12020 }
12013 12021
12014 12022 size = SLI_SLIM2_SIZE;
12015 12023 if (sizeof (SLIM2) != size) {
12016 12024 cmn_err(CE_WARN, "?%s%d: SLIM2 size incorrect. %d != %d",
12017 12025 DRIVER_NAME, ddiinst, (int)sizeof (SLIM2),
12018 12026 SLI_SLIM2_SIZE);
12019 12027
12020 12028 errors++;
12021 12029 }
12022 12030 return (errors);
12023 12031
12024 12032 } /* emlxs_integrity_check() */
12025 12033
12026 12034
12027 12035 #ifdef FMA_SUPPORT
12028 12036 /*
12029 12037 * FMA support
12030 12038 */
12031 12039
12032 12040 extern void
12033 12041 emlxs_fm_init(emlxs_hba_t *hba)
12034 12042 {
12035 12043 ddi_iblock_cookie_t iblk;
12036 12044
12037 12045 if (hba->fm_caps == DDI_FM_NOT_CAPABLE) {
12038 12046 return;
12039 12047 }
12040 12048
12041 12049 if (DDI_FM_ACC_ERR_CAP(hba->fm_caps)) {
12042 12050 emlxs_dev_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
12043 12051 emlxs_data_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
12044 12052 }
12045 12053
12046 12054 if (DDI_FM_DMA_ERR_CAP(hba->fm_caps)) {
12047 12055 hba->dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
12048 12056 hba->dma_attr_ro.dma_attr_flags |= DDI_DMA_FLAGERR;
12049 12057 hba->dma_attr_1sg.dma_attr_flags |= DDI_DMA_FLAGERR;
12050 12058 hba->dma_attr_fcip_rsp.dma_attr_flags |= DDI_DMA_FLAGERR;
12051 12059 } else {
12052 12060 hba->dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12053 12061 hba->dma_attr_ro.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12054 12062 hba->dma_attr_1sg.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12055 12063 hba->dma_attr_fcip_rsp.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12056 12064 }
12057 12065
12058 12066 ddi_fm_init(hba->dip, &hba->fm_caps, &iblk);
12059 12067
12060 12068 if (DDI_FM_EREPORT_CAP(hba->fm_caps) ||
12061 12069 DDI_FM_ERRCB_CAP(hba->fm_caps)) {
12062 12070 pci_ereport_setup(hba->dip);
12063 12071 }
12064 12072
12065 12073 if (DDI_FM_ERRCB_CAP(hba->fm_caps)) {
12066 12074 ddi_fm_handler_register(hba->dip, emlxs_fm_error_cb,
12067 12075 (void *)hba);
12068 12076 }
12069 12077
12070 12078 } /* emlxs_fm_init() */
12071 12079
12072 12080
12073 12081 extern void
12074 12082 emlxs_fm_fini(emlxs_hba_t *hba)
12075 12083 {
12076 12084 if (hba->fm_caps == DDI_FM_NOT_CAPABLE) {
12077 12085 return;
12078 12086 }
12079 12087
12080 12088 if (DDI_FM_EREPORT_CAP(hba->fm_caps) ||
12081 12089 DDI_FM_ERRCB_CAP(hba->fm_caps)) {
12082 12090 pci_ereport_teardown(hba->dip);
12083 12091 }
12084 12092
12085 12093 if (DDI_FM_ERRCB_CAP(hba->fm_caps)) {
12086 12094 ddi_fm_handler_unregister(hba->dip);
12087 12095 }
12088 12096
12089 12097 (void) ddi_fm_fini(hba->dip);
12090 12098
12091 12099 } /* emlxs_fm_fini() */
12092 12100
12093 12101
12094 12102 extern int
12095 12103 emlxs_fm_check_acc_handle(emlxs_hba_t *hba, ddi_acc_handle_t handle)
12096 12104 {
12097 12105 ddi_fm_error_t err;
12098 12106
12099 12107 if (!DDI_FM_ACC_ERR_CAP(hba->fm_caps)) {
12100 12108 return (DDI_FM_OK);
12101 12109 }
12102 12110
12103 12111 /* Some S10 versions do not define the ahi_err structure */
12104 12112 if (((ddi_acc_impl_t *)handle)->ahi_err == NULL) {
12105 12113 return (DDI_FM_OK);
12106 12114 }
12107 12115
12108 12116 err.fme_status = DDI_FM_OK;
12109 12117 (void) ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION);
12110 12118
12111 12119 /* Some S10 versions do not define the ddi_fm_acc_err_clear function */
12112 12120 if ((void *)&ddi_fm_acc_err_clear != NULL) {
12113 12121 (void) ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
12114 12122 }
12115 12123
12116 12124 return (err.fme_status);
12117 12125
12118 12126 } /* emlxs_fm_check_acc_handle() */
12119 12127
12120 12128
12121 12129 extern int
12122 12130 emlxs_fm_check_dma_handle(emlxs_hba_t *hba, ddi_dma_handle_t handle)
12123 12131 {
12124 12132 ddi_fm_error_t err;
12125 12133
12126 12134 if (!DDI_FM_ACC_ERR_CAP(hba->fm_caps)) {
12127 12135 return (DDI_FM_OK);
12128 12136 }
12129 12137
12130 12138 err.fme_status = DDI_FM_OK;
12131 12139 (void) ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION);
12132 12140
12133 12141 return (err.fme_status);
12134 12142
12135 12143 } /* emlxs_fm_check_dma_handle() */
12136 12144
12137 12145
12138 12146 extern void
12139 12147 emlxs_fm_ereport(emlxs_hba_t *hba, char *detail)
12140 12148 {
12141 12149 uint64_t ena;
12142 12150 char buf[FM_MAX_CLASS];
12143 12151
12144 12152 if (!DDI_FM_EREPORT_CAP(hba->fm_caps)) {
12145 12153 return;
12146 12154 }
12147 12155
12148 12156 if (detail == NULL) {
12149 12157 return;
12150 12158 }
12151 12159
12152 12160 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
12153 12161 ena = fm_ena_generate(0, FM_ENA_FMT1);
12154 12162
12155 12163 ddi_fm_ereport_post(hba->dip, buf, ena, DDI_NOSLEEP,
12156 12164 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
12157 12165
12158 12166 } /* emlxs_fm_ereport() */
12159 12167
12160 12168
12161 12169 extern void
12162 12170 emlxs_fm_service_impact(emlxs_hba_t *hba, int impact)
12163 12171 {
12164 12172 if (!DDI_FM_EREPORT_CAP(hba->fm_caps)) {
12165 12173 return;
12166 12174 }
12167 12175
12168 12176 if (impact == NULL) {
12169 12177 return;
12170 12178 }
12171 12179
12172 12180 if ((hba->pm_state & EMLXS_PM_IN_DETACH) &&
12173 12181 (impact == DDI_SERVICE_DEGRADED)) {
12174 12182 impact = DDI_SERVICE_UNAFFECTED;
12175 12183 }
12176 12184
12177 12185 ddi_fm_service_impact(hba->dip, impact);
12178 12186
12179 12187 return;
12180 12188
12181 12189 } /* emlxs_fm_service_impact() */
12182 12190
12183 12191
12184 12192 /*
12185 12193 * The I/O fault service error handling callback function
12186 12194 */
12187 12195 /*ARGSUSED*/
12188 12196 extern int
12189 12197 emlxs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err,
12190 12198 const void *impl_data)
12191 12199 {
12192 12200 /*
12193 12201 * as the driver can always deal with an error
12194 12202 * in any dma or access handle, we can just return
12195 12203 * the fme_status value.
12196 12204 */
12197 12205 pci_ereport_post(dip, err, NULL);
12198 12206 return (err->fme_status);
12199 12207
12200 12208 } /* emlxs_fm_error_cb() */
12201 12209
12202 12210 extern void
12203 12211 emlxs_check_dma(emlxs_hba_t *hba, emlxs_buf_t *sbp)
12204 12212 {
12205 12213 emlxs_port_t *port = sbp->port;
12206 12214 fc_packet_t *pkt = PRIV2PKT(sbp);
12207 12215
12208 12216 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
12209 12217 if (emlxs_fm_check_dma_handle(hba,
12210 12218 hba->sli.sli4.slim2.dma_handle)
12211 12219 != DDI_FM_OK) {
12212 12220 EMLXS_MSGF(EMLXS_CONTEXT,
12213 12221 &emlxs_invalid_dma_handle_msg,
12214 12222 "slim2: hdl=%p",
12215 12223 hba->sli.sli4.slim2.dma_handle);
12216 12224
12217 12225 mutex_enter(&EMLXS_PORT_LOCK);
12218 12226 hba->flag |= FC_DMA_CHECK_ERROR;
12219 12227 mutex_exit(&EMLXS_PORT_LOCK);
12220 12228 }
12221 12229 } else {
12222 12230 if (emlxs_fm_check_dma_handle(hba,
12223 12231 hba->sli.sli3.slim2.dma_handle)
12224 12232 != DDI_FM_OK) {
12225 12233 EMLXS_MSGF(EMLXS_CONTEXT,
12226 12234 &emlxs_invalid_dma_handle_msg,
12227 12235 "slim2: hdl=%p",
12228 12236 hba->sli.sli3.slim2.dma_handle);
12229 12237
12230 12238 mutex_enter(&EMLXS_PORT_LOCK);
12231 12239 hba->flag |= FC_DMA_CHECK_ERROR;
12232 12240 mutex_exit(&EMLXS_PORT_LOCK);
12233 12241 }
12234 12242 }
12235 12243
12236 12244 if (hba->flag & FC_DMA_CHECK_ERROR) {
12237 12245 pkt->pkt_state = FC_PKT_TRAN_ERROR;
12238 12246 pkt->pkt_reason = FC_REASON_DMA_ERROR;
12239 12247 pkt->pkt_expln = FC_EXPLN_NONE;
12240 12248 pkt->pkt_action = FC_ACTION_RETRYABLE;
12241 12249 return;
12242 12250 }
12243 12251
12244 12252 if (pkt->pkt_cmdlen) {
12245 12253 if (emlxs_fm_check_dma_handle(hba, pkt->pkt_cmd_dma)
12246 12254 != DDI_FM_OK) {
12247 12255 EMLXS_MSGF(EMLXS_CONTEXT,
12248 12256 &emlxs_invalid_dma_handle_msg,
12249 12257 "pkt_cmd_dma: hdl=%p",
12250 12258 pkt->pkt_cmd_dma);
12251 12259
12252 12260 pkt->pkt_state = FC_PKT_TRAN_ERROR;
12253 12261 pkt->pkt_reason = FC_REASON_DMA_ERROR;
12254 12262 pkt->pkt_expln = FC_EXPLN_NONE;
12255 12263 pkt->pkt_action = FC_ACTION_RETRYABLE;
12256 12264
12257 12265 return;
12258 12266 }
12259 12267 }
12260 12268
12261 12269 if (pkt->pkt_rsplen) {
12262 12270 if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
12263 12271 != DDI_FM_OK) {
12264 12272 EMLXS_MSGF(EMLXS_CONTEXT,
12265 12273 &emlxs_invalid_dma_handle_msg,
12266 12274 "pkt_resp_dma: hdl=%p",
12267 12275 pkt->pkt_resp_dma);
12268 12276
12269 12277 pkt->pkt_state = FC_PKT_TRAN_ERROR;
12270 12278 pkt->pkt_reason = FC_REASON_DMA_ERROR;
12271 12279 pkt->pkt_expln = FC_EXPLN_NONE;
12272 12280 pkt->pkt_action = FC_ACTION_RETRYABLE;
12273 12281
12274 12282 return;
12275 12283 }
12276 12284 }
12277 12285
12278 12286 if (pkt->pkt_datalen) {
12279 12287 if (emlxs_fm_check_dma_handle(hba, pkt->pkt_data_dma)
12280 12288 != DDI_FM_OK) {
12281 12289 EMLXS_MSGF(EMLXS_CONTEXT,
12282 12290 &emlxs_invalid_dma_handle_msg,
12283 12291 "pkt_data_dma: hdl=%p",
12284 12292 pkt->pkt_data_dma);
12285 12293
12286 12294 pkt->pkt_state = FC_PKT_TRAN_ERROR;
12287 12295 pkt->pkt_reason = FC_REASON_DMA_ERROR;
12288 12296 pkt->pkt_expln = FC_EXPLN_NONE;
12289 12297 pkt->pkt_action = FC_ACTION_RETRYABLE;
12290 12298
12291 12299 return;
12292 12300 }
12293 12301 }
12294 12302
12295 12303 return;
12296 12304
12297 12305 }
12298 12306 #endif /* FMA_SUPPORT */
12299 12307
12300 12308
12301 12309 extern void
12302 12310 emlxs_swap32_buffer(uint8_t *buffer, uint32_t size)
12303 12311 {
12304 12312 uint32_t word;
12305 12313 uint32_t *wptr;
12306 12314 uint32_t i;
12307 12315
12308 12316 VERIFY((size % 4) == 0);
12309 12317
12310 12318 wptr = (uint32_t *)buffer;
12311 12319
12312 12320 for (i = 0; i < size / 4; i++) {
12313 12321 word = *wptr;
12314 12322 *wptr++ = SWAP32(word);
12315 12323 }
12316 12324
12317 12325 return;
12318 12326
12319 12327 } /* emlxs_swap32_buffer() */
12320 12328
12321 12329
12322 12330 extern void
12323 12331 emlxs_swap32_bcopy(uint8_t *src, uint8_t *dst, uint32_t size)
12324 12332 {
12325 12333 uint32_t word;
12326 12334 uint32_t *sptr;
12327 12335 uint32_t *dptr;
12328 12336 uint32_t i;
12329 12337
12330 12338 VERIFY((size % 4) == 0);
12331 12339
12332 12340 sptr = (uint32_t *)src;
12333 12341 dptr = (uint32_t *)dst;
12334 12342
12335 12343 for (i = 0; i < size / 4; i++) {
12336 12344 word = *sptr++;
12337 12345 *dptr++ = SWAP32(word);
12338 12346 }
12339 12347
12340 12348 return;
12341 12349
12342 12350 } /* emlxs_swap32_buffer() */
12343 12351
12344 12352
12345 12353 extern char *
12346 12354 emlxs_strtoupper(char *str)
12347 12355 {
12348 12356 char *cptr = str;
12349 12357
12350 12358 while (*cptr) {
12351 12359 if ((*cptr >= 'a') && (*cptr <= 'z')) {
12352 12360 *cptr -= ('a' - 'A');
12353 12361 }
12354 12362 cptr++;
12355 12363 }
12356 12364
12357 12365 return (str);
12358 12366
12359 12367 } /* emlxs_strtoupper() */
12360 12368
12361 12369
12362 12370 extern void
12363 12371 emlxs_ulp_statec_cb(emlxs_port_t *port, uint32_t statec)
12364 12372 {
12365 12373 emlxs_hba_t *hba = HBA;
12366 12374
12367 12375 /* This routine coordinates protection with emlxs_fca_unbind_port() */
12368 12376
12369 12377 mutex_enter(&EMLXS_PORT_LOCK);
12370 12378 if (!(port->flag & EMLXS_INI_BOUND)) {
12371 12379 mutex_exit(&EMLXS_PORT_LOCK);
12372 12380 return;
12373 12381 }
12374 12382 port->ulp_busy++;
12375 12383 mutex_exit(&EMLXS_PORT_LOCK);
12376 12384
12377 12385 port->ulp_statec_cb(port->ulp_handle, statec);
12378 12386
12379 12387 mutex_enter(&EMLXS_PORT_LOCK);
12380 12388 port->ulp_busy--;
12381 12389 mutex_exit(&EMLXS_PORT_LOCK);
12382 12390
12383 12391 return;
12384 12392
12385 12393 } /* emlxs_ulp_statec_cb() */
12386 12394
12387 12395
12388 12396 extern void
12389 12397 emlxs_ulp_unsol_cb(emlxs_port_t *port, fc_unsol_buf_t *ubp)
12390 12398 {
12391 12399 emlxs_hba_t *hba = HBA;
12392 12400
12393 12401 /* This routine coordinates protection with emlxs_fca_unbind_port() */
12394 12402
12395 12403 mutex_enter(&EMLXS_PORT_LOCK);
12396 12404 if (!(port->flag & EMLXS_INI_BOUND)) {
12397 12405 mutex_exit(&EMLXS_PORT_LOCK);
12398 12406 return;
12399 12407 }
12400 12408 port->ulp_busy++;
12401 12409 mutex_exit(&EMLXS_PORT_LOCK);
12402 12410
12403 12411 port->ulp_unsol_cb(port->ulp_handle, ubp, ubp->ub_frame.type);
12404 12412
12405 12413 mutex_enter(&EMLXS_PORT_LOCK);
12406 12414 port->ulp_busy--;
12407 12415 mutex_exit(&EMLXS_PORT_LOCK);
12408 12416
12409 12417 return;
12410 12418
12411 12419 } /* emlxs_ulp_unsol_cb() */
|
↓ open down ↓ |
2341 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX