Print this page
8368 remove warlock leftovers from usr/src/uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ib/adapters/tavor/tavor_ioctl.c
+++ new/usr/src/uts/common/io/ib/adapters/tavor/tavor_ioctl.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 usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
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 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * tavor_ioctl.c
29 29 * Tavor IOCTL Routines
30 30 *
31 31 * Implements all ioctl access into the driver. This includes all routines
32 32 * necessary for updating firmware, accessing the tavor flash device, and
33 33 * providing interfaces for VTS.
34 34 */
35 35
36 36 #include <sys/types.h>
37 37 #include <sys/conf.h>
38 38 #include <sys/ddi.h>
39 39 #include <sys/sunddi.h>
40 40 #include <sys/modctl.h>
41 41 #include <sys/file.h>
42 42
43 43 #include <sys/ib/adapters/tavor/tavor.h>
44 44
45 45 /* Tavor HCA state pointer (extern) */
46 46 extern void *tavor_statep;
47 47
48 48 /*
49 49 * The ioctl declarations (for firmware flash burning, register read/write
50 50 * (DEBUG-only), and VTS interfaces)
51 51 */
52 52 static int tavor_ioctl_flash_read(tavor_state_t *state, dev_t dev,
53 53 intptr_t arg, int mode);
54 54 static int tavor_ioctl_flash_write(tavor_state_t *state, dev_t dev,
55 55 intptr_t arg, int mode);
56 56 static int tavor_ioctl_flash_erase(tavor_state_t *state, dev_t dev,
57 57 intptr_t arg, int mode);
58 58 static int tavor_ioctl_flash_init(tavor_state_t *state, dev_t dev,
59 59 intptr_t arg, int mode);
60 60 static int tavor_ioctl_flash_fini(tavor_state_t *state, dev_t dev);
61 61 static void tavor_ioctl_flash_cleanup(tavor_state_t *state);
62 62 static void tavor_ioctl_flash_cleanup_nolock(tavor_state_t *state);
63 63 #ifdef DEBUG
64 64 static int tavor_ioctl_reg_write(tavor_state_t *state, intptr_t arg,
65 65 int mode);
66 66 static int tavor_ioctl_reg_read(tavor_state_t *state, intptr_t arg,
67 67 int mode);
68 68 #endif /* DEBUG */
69 69 static int tavor_ioctl_info(tavor_state_t *state, dev_t dev,
70 70 intptr_t arg, int mode);
71 71 static int tavor_ioctl_ports(tavor_state_t *state, intptr_t arg,
72 72 int mode);
73 73 static int tavor_ioctl_loopback(tavor_state_t *state, intptr_t arg,
74 74 int mode);
75 75 static int tavor_ioctl_ddr_read(tavor_state_t *state, intptr_t arg,
76 76 int mode);
77 77
78 78 /* Tavor Flash Functions */
79 79 static void tavor_flash_read_sector(tavor_state_t *state, uint32_t sector_num);
80 80 static void tavor_flash_read_quadlet(tavor_state_t *state, uint32_t *data,
81 81 uint32_t addr);
82 82 static int tavor_flash_write_sector(tavor_state_t *state, uint32_t sector_num);
83 83 static int tavor_flash_write_byte(tavor_state_t *state, uint32_t addr,
84 84 uchar_t data);
85 85 static int tavor_flash_erase_sector(tavor_state_t *state, uint32_t sector_num);
86 86 static int tavor_flash_erase_chip(tavor_state_t *state);
87 87 static void tavor_flash_bank(tavor_state_t *state, uint32_t addr);
88 88 static uint32_t tavor_flash_read(tavor_state_t *state, uint32_t addr);
89 89 static void tavor_flash_write(tavor_state_t *state, uint32_t addr,
90 90 uchar_t data);
91 91 static void tavor_flash_init(tavor_state_t *state);
92 92 static void tavor_flash_cfi_init(tavor_state_t *state, uint32_t *cfi_info,
93 93 int *intel_xcmd);
94 94 static void tavor_flash_fini(tavor_state_t *state);
95 95 static void tavor_flash_reset(tavor_state_t *state);
96 96 static uint32_t tavor_flash_read_cfg(ddi_acc_handle_t pci_config_hdl,
97 97 uint32_t addr);
98 98 static void tavor_flash_write_cfg(ddi_acc_handle_t pci_config_hdl,
99 99 uint32_t addr, uint32_t data);
100 100 static void tavor_flash_cfi_byte(uint8_t *ch, uint32_t dword, int i);
101 101 static void tavor_flash_cfi_dword(uint32_t *dword, uint8_t *ch, int i);
102 102
103 103 /* Tavor loopback test functions */
104 104 static void tavor_loopback_free_qps(tavor_loopback_state_t *lstate);
105 105 static void tavor_loopback_free_state(tavor_loopback_state_t *lstate);
106 106 static int tavor_loopback_init(tavor_state_t *state,
107 107 tavor_loopback_state_t *lstate);
108 108 static void tavor_loopback_init_qp_info(tavor_loopback_state_t *lstate,
109 109 tavor_loopback_comm_t *comm);
110 110 static int tavor_loopback_alloc_mem(tavor_loopback_state_t *lstate,
111 111 tavor_loopback_comm_t *comm, int sz);
112 112 static int tavor_loopback_alloc_qps(tavor_loopback_state_t *lstate,
113 113 tavor_loopback_comm_t *comm);
114 114 static int tavor_loopback_modify_qp(tavor_loopback_state_t *lstate,
115 115 tavor_loopback_comm_t *comm, uint_t qp_num);
116 116 static int tavor_loopback_copyout(tavor_loopback_ioctl_t *lb,
117 117 intptr_t arg, int mode);
118 118 static int tavor_loopback_post_send(tavor_loopback_state_t *lstate,
119 119 tavor_loopback_comm_t *tx, tavor_loopback_comm_t *rx);
120 120 static int tavor_loopback_poll_cq(tavor_loopback_state_t *lstate,
121 121 tavor_loopback_comm_t *comm);
122 122
123 123 /* Patchable timeout values for flash operations */
124 124 int tavor_hw_flash_timeout_gpio_sema = TAVOR_HW_FLASH_TIMEOUT_GPIO_SEMA;
125 125 int tavor_hw_flash_timeout_config = TAVOR_HW_FLASH_TIMEOUT_CONFIG;
126 126 int tavor_hw_flash_timeout_write = TAVOR_HW_FLASH_TIMEOUT_WRITE;
127 127 int tavor_hw_flash_timeout_erase = TAVOR_HW_FLASH_TIMEOUT_ERASE;
128 128
129 129 /*
130 130 * tavor_ioctl()
131 131 */
132 132 /* ARGSUSED */
133 133 int
134 134 tavor_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
135 135 int *rvalp)
136 136 {
137 137 tavor_state_t *state;
138 138 minor_t instance;
139 139 int status;
140 140
141 141 TAVOR_TNF_ENTER(tavor_ioctl);
142 142
143 143 if (drv_priv(credp) != 0) {
144 144 TNF_PROBE_0(tavor_ioctl_priv_fail, TAVOR_TNF_ERROR, "");
145 145 TAVOR_TNF_EXIT(tavor_ioctl);
146 146 return (EPERM);
147 147 }
148 148
149 149 instance = TAVOR_DEV_INSTANCE(dev);
150 150 if (instance == -1) {
151 151 TNF_PROBE_0(tavor_ioctl_inst_fail, TAVOR_TNF_ERROR, "");
152 152 TAVOR_TNF_EXIT(tavor_ioctl);
153 153 return (EBADF);
154 154 }
155 155
156 156 state = ddi_get_soft_state(tavor_statep, instance);
157 157 if (state == NULL) {
158 158 TNF_PROBE_0(tavor_ioctl_gss_fail, TAVOR_TNF_ERROR, "");
159 159 TAVOR_TNF_EXIT(tavor_ioctl);
160 160 return (EBADF);
161 161 }
162 162
163 163 status = 0;
164 164
165 165 switch (cmd) {
166 166 case TAVOR_IOCTL_FLASH_READ:
167 167 status = tavor_ioctl_flash_read(state, dev, arg, mode);
168 168 break;
169 169
170 170 case TAVOR_IOCTL_FLASH_WRITE:
171 171 status = tavor_ioctl_flash_write(state, dev, arg, mode);
172 172 break;
173 173
174 174 case TAVOR_IOCTL_FLASH_ERASE:
175 175 status = tavor_ioctl_flash_erase(state, dev, arg, mode);
176 176 break;
177 177
178 178 case TAVOR_IOCTL_FLASH_INIT:
179 179 status = tavor_ioctl_flash_init(state, dev, arg, mode);
180 180 break;
181 181
182 182 case TAVOR_IOCTL_FLASH_FINI:
183 183 status = tavor_ioctl_flash_fini(state, dev);
184 184 break;
185 185
186 186 case TAVOR_IOCTL_INFO:
187 187 status = tavor_ioctl_info(state, dev, arg, mode);
188 188 break;
189 189
190 190 case TAVOR_IOCTL_PORTS:
191 191 status = tavor_ioctl_ports(state, arg, mode);
192 192 break;
193 193
194 194 case TAVOR_IOCTL_DDR_READ:
195 195 status = tavor_ioctl_ddr_read(state, arg, mode);
196 196 break;
197 197
198 198 case TAVOR_IOCTL_LOOPBACK:
199 199 status = tavor_ioctl_loopback(state, arg, mode);
200 200 break;
201 201
202 202 #ifdef DEBUG
203 203 case TAVOR_IOCTL_REG_WRITE:
204 204 status = tavor_ioctl_reg_write(state, arg, mode);
205 205 break;
206 206
207 207 case TAVOR_IOCTL_REG_READ:
208 208 status = tavor_ioctl_reg_read(state, arg, mode);
209 209 break;
210 210 #endif /* DEBUG */
211 211
212 212 default:
213 213 status = ENOTTY;
214 214 TNF_PROBE_0(tavor_ioctl_default_fail, TAVOR_TNF_ERROR, "");
215 215 break;
216 216 }
217 217 *rvalp = status;
218 218
219 219 TAVOR_TNF_EXIT(tavor_ioctl);
220 220 return (status);
221 221 }
222 222
223 223 /*
224 224 * tavor_ioctl_flash_read()
225 225 */
226 226 static int
227 227 tavor_ioctl_flash_read(tavor_state_t *state, dev_t dev, intptr_t arg, int mode)
228 228 {
229 229 tavor_flash_ioctl_t ioctl_info;
230 230 int status = 0;
231 231
232 232 TAVOR_TNF_ENTER(tavor_ioctl_flash_read);
233 233
234 234 /*
235 235 * Check that flash init ioctl has been called first. And check
236 236 * that the same dev_t that called init is the one calling read now.
237 237 */
238 238 mutex_enter(&state->ts_fw_flashlock);
239 239 if ((state->ts_fw_flashdev != dev) ||
240 240 (state->ts_fw_flashstarted == 0)) {
241 241 mutex_exit(&state->ts_fw_flashlock);
242 242 TNF_PROBE_0(tavor_flash_bad_state, TAVOR_TNF_ERROR, "");
243 243 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
244 244 return (EIO);
245 245 }
246 246
247 247 /* copy user struct to kernel */
248 248 #ifdef _MULTI_DATAMODEL
249 249 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
250 250 tavor_flash_ioctl32_t info32;
251 251
252 252 if (ddi_copyin((void *)arg, &info32,
253 253 sizeof (tavor_flash_ioctl32_t), mode) != 0) {
254 254 mutex_exit(&state->ts_fw_flashlock);
255 255 TNF_PROBE_0(tavor_ioctl_flash_read_copyin_fail,
256 256 TAVOR_TNF_ERROR, "");
257 257 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
258 258 return (EFAULT);
259 259 }
260 260 ioctl_info.tf_type = info32.tf_type;
261 261 ioctl_info.tf_sector = (caddr_t)(uintptr_t)info32.tf_sector;
262 262 ioctl_info.tf_sector_num = info32.tf_sector_num;
263 263 ioctl_info.tf_addr = info32.tf_addr;
264 264 } else
265 265 #endif /* _MULTI_DATAMODEL */
266 266 if (ddi_copyin((void *)arg, &ioctl_info, sizeof (tavor_flash_ioctl_t),
267 267 mode) != 0) {
268 268 mutex_exit(&state->ts_fw_flashlock);
269 269 TNF_PROBE_0(tavor_ioctl_flash_read_copyin_fail,
270 270 TAVOR_TNF_ERROR, "");
271 271 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
272 272 return (EFAULT);
273 273 }
274 274
275 275 /*
276 276 * Determine type of READ ioctl
277 277 */
278 278 switch (ioctl_info.tf_type) {
279 279 case TAVOR_FLASH_READ_SECTOR:
280 280 /* Check if sector num is too large for flash device */
281 281 if (ioctl_info.tf_sector_num >=
282 282 (state->ts_fw_device_sz >> state->ts_fw_log_sector_sz)) {
283 283 mutex_exit(&state->ts_fw_flashlock);
284 284 TNF_PROBE_0(tavor_flash_read_sector_num_too_large,
285 285 TAVOR_TNF_ERROR, "");
286 286 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
287 287 return (EFAULT);
288 288 }
289 289
290 290 /* Perform the Sector Read */
291 291 tavor_flash_reset(state);
292 292 tavor_flash_read_sector(state, ioctl_info.tf_sector_num);
293 293
294 294 /* copyout the firmware sector image data */
295 295 if (ddi_copyout(&state->ts_fw_sector[0],
296 296 &ioctl_info.tf_sector[0], 1 << state->ts_fw_log_sector_sz,
297 297 mode) != 0) {
298 298 mutex_exit(&state->ts_fw_flashlock);
299 299 TNF_PROBE_0(tavor_flash_read_copyout_fail,
300 300 TAVOR_TNF_ERROR, "");
301 301 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
302 302 return (EFAULT);
303 303 }
304 304 break;
305 305
306 306 case TAVOR_FLASH_READ_QUADLET:
307 307 /* Check if addr is too large for flash device */
308 308 if (ioctl_info.tf_addr >= state->ts_fw_device_sz) {
309 309 mutex_exit(&state->ts_fw_flashlock);
310 310 TNF_PROBE_0(tavor_flash_read_quad_addr_too_large,
311 311 TAVOR_TNF_ERROR, "");
312 312 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
313 313 return (EFAULT);
314 314 }
315 315
316 316 /* Perform the Quadlet Read */
317 317 tavor_flash_reset(state);
318 318 tavor_flash_read_quadlet(state, &ioctl_info.tf_quadlet,
319 319 ioctl_info.tf_addr);
320 320 break;
321 321
322 322 default:
323 323 TNF_PROBE_0(tavor_ioctl_flash_read_invalid_type,
324 324 TAVOR_TNF_ERROR, "");
325 325 status = EIO;
326 326 break;
327 327 }
328 328
329 329 /* copy results back to userland */
330 330 #ifdef _MULTI_DATAMODEL
331 331 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
332 332 tavor_flash_ioctl32_t info32;
333 333
334 334 info32.tf_quadlet = ioctl_info.tf_quadlet;
335 335 info32.tf_type = ioctl_info.tf_type;
336 336 info32.tf_sector_num = ioctl_info.tf_sector_num;
337 337 info32.tf_sector = (caddr32_t)(uintptr_t)ioctl_info.tf_sector;
338 338 info32.tf_addr = ioctl_info.tf_addr;
339 339
340 340 if (ddi_copyout(&info32, (void *)arg,
341 341 sizeof (tavor_flash_ioctl32_t), mode) != 0) {
342 342 mutex_exit(&state->ts_fw_flashlock);
343 343 TNF_PROBE_0(tavor_flash_read_copyout_fail,
344 344 TAVOR_TNF_ERROR, "");
345 345 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
346 346 return (EFAULT);
347 347 }
348 348 } else
349 349 #endif /* _MULTI_DATAMODEL */
350 350 if (ddi_copyout(&ioctl_info, (void *)arg,
351 351 sizeof (tavor_flash_ioctl_t), mode) != 0) {
352 352 mutex_exit(&state->ts_fw_flashlock);
353 353 TNF_PROBE_0(tavor_flash_read_copyout_fail,
354 354 TAVOR_TNF_ERROR, "");
355 355 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
356 356 return (EFAULT);
357 357 }
358 358
359 359 mutex_exit(&state->ts_fw_flashlock);
360 360 TAVOR_TNF_EXIT(tavor_ioctl_flash_read);
361 361 return (status);
362 362 }
363 363
364 364 /*
365 365 * tavor_ioctl_flash_write()
366 366 */
367 367 static int
368 368 tavor_ioctl_flash_write(tavor_state_t *state, dev_t dev, intptr_t arg, int mode)
369 369 {
370 370 tavor_flash_ioctl_t ioctl_info;
371 371 int status = 0;
372 372
373 373 TAVOR_TNF_ENTER(tavor_ioctl_flash_write);
374 374
375 375 /*
376 376 * Check that flash init ioctl has been called first. And check
377 377 * that the same dev_t that called init is the one calling write now.
378 378 */
379 379 mutex_enter(&state->ts_fw_flashlock);
380 380 if ((state->ts_fw_flashdev != dev) ||
381 381 (state->ts_fw_flashstarted == 0)) {
382 382 mutex_exit(&state->ts_fw_flashlock);
383 383 TNF_PROBE_0(tavor_flash_bad_state, TAVOR_TNF_ERROR, "");
384 384 TAVOR_TNF_EXIT(tavor_ioctl_flash_write);
385 385 return (EIO);
386 386 }
387 387
388 388 /* copy user struct to kernel */
389 389 #ifdef _MULTI_DATAMODEL
390 390 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
391 391 tavor_flash_ioctl32_t info32;
392 392
393 393 if (ddi_copyin((void *)arg, &info32,
394 394 sizeof (tavor_flash_ioctl32_t), mode) != 0) {
395 395 mutex_exit(&state->ts_fw_flashlock);
396 396 TNF_PROBE_0(tavor_ioctl_flash_write_copyin_fail,
397 397 TAVOR_TNF_ERROR, "");
398 398 TAVOR_TNF_EXIT(tavor_ioctl_flash_write);
399 399 return (EFAULT);
400 400 }
401 401 ioctl_info.tf_type = info32.tf_type;
402 402 ioctl_info.tf_sector = (caddr_t)(uintptr_t)info32.tf_sector;
403 403 ioctl_info.tf_sector_num = info32.tf_sector_num;
404 404 ioctl_info.tf_addr = info32.tf_addr;
405 405 ioctl_info.tf_byte = info32.tf_byte;
406 406 } else
407 407 #endif /* _MULTI_DATAMODEL */
408 408 if (ddi_copyin((void *)arg, &ioctl_info,
409 409 sizeof (tavor_flash_ioctl_t), mode) != 0) {
410 410 mutex_exit(&state->ts_fw_flashlock);
411 411 TNF_PROBE_0(tavor_ioctl_flash_write_ci_fail,
412 412 TAVOR_TNF_ERROR, "");
413 413 TAVOR_TNF_EXIT(tavor_ioctl_flash_write);
414 414 return (EFAULT);
415 415 }
416 416
417 417 /*
418 418 * Determine type of WRITE ioctl
419 419 */
420 420 switch (ioctl_info.tf_type) {
421 421 case TAVOR_FLASH_WRITE_SECTOR:
422 422 /* Check if sector num is too large for flash device */
423 423 if (ioctl_info.tf_sector_num >=
424 424 (state->ts_fw_device_sz >> state->ts_fw_log_sector_sz)) {
425 425 mutex_exit(&state->ts_fw_flashlock);
426 426 TNF_PROBE_0(tavor_flash_write_sector_num_too_large,
427 427 TAVOR_TNF_ERROR, "");
428 428 TAVOR_TNF_EXIT(tavor_ioctl_flash_write);
429 429 return (EFAULT);
430 430 }
431 431
432 432 /* copy in fw sector image data */
433 433 if (ddi_copyin(&ioctl_info.tf_sector[0],
434 434 &state->ts_fw_sector[0], 1 << state->ts_fw_log_sector_sz,
435 435 mode) != 0) {
436 436 mutex_exit(&state->ts_fw_flashlock);
437 437 TNF_PROBE_0(tavor_ioctl_flash_write_fw_sector_ci_fail,
438 438 TAVOR_TNF_ERROR, "");
439 439 TAVOR_TNF_EXIT(tavor_ioctl_flash_write);
440 440 return (EFAULT);
441 441 }
442 442
443 443 /* Perform Write Sector */
444 444 status = tavor_flash_write_sector(state,
445 445 ioctl_info.tf_sector_num);
446 446 break;
447 447
448 448 case TAVOR_FLASH_WRITE_BYTE:
449 449 /* Check if addr is too large for flash device */
450 450 if (ioctl_info.tf_addr >= state->ts_fw_device_sz) {
451 451 mutex_exit(&state->ts_fw_flashlock);
452 452 TNF_PROBE_0(tavor_flash_write_byte_addr_too_large,
453 453 TAVOR_TNF_ERROR, "");
454 454 TAVOR_TNF_EXIT(tavor_ioctl_flash_write);
455 455 return (EFAULT);
456 456 }
457 457
458 458 /* Perform Write Byte */
459 459 tavor_flash_bank(state, ioctl_info.tf_addr);
460 460 tavor_flash_reset(state);
461 461 status = tavor_flash_write_byte(state, ioctl_info.tf_addr,
462 462 ioctl_info.tf_byte);
463 463 tavor_flash_reset(state);
464 464 break;
465 465
466 466 default:
467 467 TNF_PROBE_0(tavor_ioctl_flash_write_invalid_type,
468 468 TAVOR_TNF_ERROR, "");
469 469 status = EIO;
470 470 break;
471 471 }
472 472
473 473 mutex_exit(&state->ts_fw_flashlock);
474 474 TAVOR_TNF_EXIT(tavor_ioctl_flash_write);
475 475 return (status);
476 476 }
477 477
478 478 /*
479 479 * tavor_ioctl_flash_erase()
480 480 */
481 481 static int
482 482 tavor_ioctl_flash_erase(tavor_state_t *state, dev_t dev, intptr_t arg, int mode)
483 483 {
484 484 tavor_flash_ioctl_t ioctl_info;
485 485 int status = 0;
486 486
487 487 TAVOR_TNF_ENTER(tavor_ioctl_flash_erase);
488 488
489 489 /*
490 490 * Check that flash init ioctl has been called first. And check
491 491 * that the same dev_t that called init is the one calling erase now.
492 492 */
493 493 mutex_enter(&state->ts_fw_flashlock);
494 494 if ((state->ts_fw_flashdev != dev) ||
495 495 (state->ts_fw_flashstarted == 0)) {
496 496 mutex_exit(&state->ts_fw_flashlock);
497 497 TNF_PROBE_0(tavor_flash_bad_state, TAVOR_TNF_ERROR, "");
498 498 TAVOR_TNF_EXIT(tavor_ioctl_flash_erase);
499 499 return (EIO);
500 500 }
501 501
502 502 /* copy user struct to kernel */
503 503 #ifdef _MULTI_DATAMODEL
504 504 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
505 505 tavor_flash_ioctl32_t info32;
506 506
507 507 if (ddi_copyin((void *)arg, &info32,
508 508 sizeof (tavor_flash_ioctl32_t), mode) != 0) {
509 509 mutex_exit(&state->ts_fw_flashlock);
510 510 TNF_PROBE_0(tavor_ioctl_flash_read_copyin_fail,
511 511 TAVOR_TNF_ERROR, "");
512 512 TAVOR_TNF_EXIT(tavor_ioctl_flash_erase);
513 513 return (EFAULT);
514 514 }
515 515 ioctl_info.tf_type = info32.tf_type;
516 516 ioctl_info.tf_sector_num = info32.tf_sector_num;
517 517 } else
518 518 #endif /* _MULTI_DATAMODEL */
519 519 if (ddi_copyin((void *)arg, &ioctl_info, sizeof (tavor_flash_ioctl_t),
520 520 mode) != 0) {
521 521 mutex_exit(&state->ts_fw_flashlock);
522 522 TNF_PROBE_0(tavor_ioctl_flash_erase_ci_fail,
523 523 TAVOR_TNF_ERROR, "");
524 524 TAVOR_TNF_EXIT(tavor_ioctl_flash_erase);
525 525 return (EFAULT);
526 526 }
527 527
528 528 /*
529 529 * Determine type of ERASE ioctl
530 530 */
531 531 switch (ioctl_info.tf_type) {
532 532 case TAVOR_FLASH_ERASE_SECTOR:
533 533 /* Check if sector num is too large for flash device */
534 534 if (ioctl_info.tf_sector_num >=
535 535 (state->ts_fw_device_sz >> state->ts_fw_log_sector_sz)) {
536 536 mutex_exit(&state->ts_fw_flashlock);
537 537 TNF_PROBE_0(tavor_flash_erase_sector_num_too_large,
538 538 TAVOR_TNF_ERROR, "");
539 539 TAVOR_TNF_EXIT(tavor_ioctl_flash_write);
540 540 return (EFAULT);
541 541 }
542 542
543 543 /* Perform Sector Erase */
544 544 status = tavor_flash_erase_sector(state,
545 545 ioctl_info.tf_sector_num);
546 546 break;
547 547
548 548 case TAVOR_FLASH_ERASE_CHIP:
549 549 /* Perform Chip Erase */
550 550 status = tavor_flash_erase_chip(state);
551 551 break;
552 552
553 553 default:
554 554 TNF_PROBE_0(tavor_ioctl_flash_erase_invalid_type,
555 555 TAVOR_TNF_ERROR, "");
556 556 status = EIO;
557 557 break;
558 558 }
559 559
560 560 mutex_exit(&state->ts_fw_flashlock);
561 561 TAVOR_TNF_EXIT(tavor_ioctl_flash_erase);
562 562 return (status);
563 563 }
564 564
565 565 /*
566 566 * tavor_ioctl_flash_init()
567 567 */
568 568 static int
569 569 tavor_ioctl_flash_init(tavor_state_t *state, dev_t dev, intptr_t arg, int mode)
570 570 {
571 571 tavor_flash_init_ioctl_t init_info;
572 572 int ret;
573 573 int intel_xcmd = 0;
574 574
575 575 TAVOR_TNF_ENTER(tavor_ioctl_flash_init);
576 576
577 577 /*
578 578 * init cannot be called more than once. If we have already init'd the
579 579 * flash, return directly.
580 580 */
581 581 mutex_enter(&state->ts_fw_flashlock);
582 582 if (state->ts_fw_flashstarted == 1) {
583 583 mutex_exit(&state->ts_fw_flashlock);
584 584 TNF_PROBE_0(tavor_ioctl_flash_init_already_started,
585 585 TAVOR_TNF_ERROR, "");
586 586 TAVOR_TNF_EXIT(tavor_ioctl_flash_init);
587 587 return (EIO);
588 588 }
589 589
590 590 /* copyin the user struct to kernel */
591 591 if (ddi_copyin((void *)arg, &init_info,
592 592 sizeof (tavor_flash_init_ioctl_t), mode) != 0) {
593 593 mutex_exit(&state->ts_fw_flashlock);
594 594 TNF_PROBE_0(tavor_flash_init_ioctl_copyin_fail,
595 595 TAVOR_TNF_ERROR, "");
596 596 TAVOR_TNF_EXIT(tavor_ioctl_flash_init);
597 597 return (EFAULT);
598 598 }
599 599
600 600 /* Init Flash */
601 601 tavor_flash_init(state);
602 602
603 603 /* Read CFI info */
604 604 tavor_flash_cfi_init(state, &init_info.tf_cfi_info[0], &intel_xcmd);
605 605
606 606 /*
607 607 * Return error if the command set is unknown.
608 608 */
609 609 if (state->ts_fw_cmdset == TAVOR_FLASH_UNKNOWN_CMDSET) {
610 610 mutex_exit(&state->ts_fw_flashlock);
611 611 TNF_PROBE_1(tavor_ioctl_flash_init_cmdset_fail,
612 612 TAVOR_TNF_ERROR, "", tnf_string, errmsg,
613 613 "UNKNOWN flash command set");
614 614 TAVOR_TNF_EXIT(tavor_ioctl_flash_init);
615 615 return (EFAULT);
616 616 }
617 617
618 618 /* Read HWREV - least significant 8 bits is revision ID */
619 619 init_info.tf_hwrev = pci_config_get32(state->ts_pci_cfghdl,
620 620 TAVOR_HW_FLASH_CFG_HWREV) & 0xFF;
621 621
622 622 /* Fill in the firmwate revision numbers */
623 623 init_info.tf_fwrev.tfi_maj = state->ts_fw.fw_rev_major;
624 624 init_info.tf_fwrev.tfi_min = state->ts_fw.fw_rev_minor;
625 625 init_info.tf_fwrev.tfi_sub = state->ts_fw.fw_rev_subminor;
626 626
627 627 /* Alloc flash mem for one sector size */
628 628 state->ts_fw_sector = (uint32_t *)kmem_zalloc(1 <<
629 629 state->ts_fw_log_sector_sz, KM_SLEEP);
630 630
631 631 /* Set HW part number and length */
632 632 init_info.tf_pn_len = state->ts_hca_pn_len;
633 633 if (state->ts_hca_pn_len != 0) {
634 634 (void) memcpy(init_info.tf_hwpn, state->ts_hca_pn,
635 635 state->ts_hca_pn_len);
636 636 }
637 637
638 638 /* Copy ioctl results back to userland */
639 639 if (ddi_copyout(&init_info, (void *)arg,
640 640 sizeof (tavor_flash_init_ioctl_t), mode) != 0) {
641 641
642 642 tavor_ioctl_flash_cleanup_nolock(state);
643 643
644 644 mutex_exit(&state->ts_fw_flashlock);
645 645 TNF_PROBE_0(tavor_ioctl_flash_init_copyout_fail,
646 646 TAVOR_TNF_ERROR, "");
647 647 TAVOR_TNF_EXIT(tavor_ioctl_flash_init);
648 648 return (EFAULT);
649 649 }
650 650
651 651 /* Set flash state to started */
652 652 state->ts_fw_flashstarted = 1;
653 653 state->ts_fw_flashdev = dev;
654 654
655 655 mutex_exit(&state->ts_fw_flashlock);
656 656
657 657 /*
658 658 * If "flash init" is successful, add an "on close" callback to the
659 659 * current dev node to ensure that "flash fini" gets called later
660 660 * even if the userland process prematurely exits.
661 661 */
662 662 ret = tavor_umap_db_set_onclose_cb(dev,
663 663 TAVOR_ONCLOSE_FLASH_INPROGRESS,
664 664 (void (*)(void *))tavor_ioctl_flash_cleanup, state);
665 665 if (ret != DDI_SUCCESS) {
666 666 (void) tavor_ioctl_flash_fini(state, dev);
667 667
668 668 TNF_PROBE_0(tavor_ioctl_flash_init_set_cb_fail,
669 669 TAVOR_TNF_ERROR, "");
670 670 TAVOR_TNF_EXIT(tavor_ioctl_flash_init);
671 671 return (EFAULT);
672 672 }
673 673
674 674 TAVOR_TNF_EXIT(tavor_ioctl_flash_init);
675 675 return (0);
676 676 }
677 677
678 678 /*
679 679 * tavor_ioctl_flash_fini()
680 680 */
681 681 static int
682 682 tavor_ioctl_flash_fini(tavor_state_t *state, dev_t dev)
683 683 {
684 684 int ret;
685 685
686 686 TAVOR_TNF_ENTER(tavor_ioctl_flash_fini);
687 687
688 688 /*
689 689 * Check that flash init ioctl has been called first. And check
690 690 * that the same dev_t that called init is the one calling fini now.
691 691 */
692 692 mutex_enter(&state->ts_fw_flashlock);
693 693 if ((state->ts_fw_flashdev != dev) ||
694 694 (state->ts_fw_flashstarted == 0)) {
695 695 mutex_exit(&state->ts_fw_flashlock);
696 696 TNF_PROBE_0(tavor_flash_bad_state, TAVOR_TNF_ERROR, "");
697 697 TAVOR_TNF_EXIT(tavor_ioctl_flash_fini);
698 698 return (EIO);
699 699 }
700 700
701 701 tavor_ioctl_flash_cleanup_nolock(state);
702 702
703 703 mutex_exit(&state->ts_fw_flashlock);
704 704
705 705 /*
706 706 * If "flash fini" is successful, remove the "on close" callback
707 707 * that was setup during "flash init".
708 708 */
709 709 ret = tavor_umap_db_clear_onclose_cb(dev,
710 710 TAVOR_ONCLOSE_FLASH_INPROGRESS);
711 711 if (ret != DDI_SUCCESS) {
712 712 TNF_PROBE_0(tavor_flash_fini_clear_cb_fail, TAVOR_TNF_ERROR,
713 713 "");
714 714 TAVOR_TNF_EXIT(tavor_ioctl_flash_fini);
715 715 return (EFAULT);
716 716 }
717 717
718 718 TAVOR_TNF_EXIT(tavor_ioctl_flash_fini);
719 719 return (0);
720 720 }
721 721
722 722
723 723 /*
724 724 * tavor_ioctl_flash_cleanup()
725 725 */
726 726 static void
727 727 tavor_ioctl_flash_cleanup(tavor_state_t *state)
728 728 {
729 729 TAVOR_TNF_ENTER(tavor_ioctl_flash_cleanup);
730 730
731 731 mutex_enter(&state->ts_fw_flashlock);
732 732 tavor_ioctl_flash_cleanup_nolock(state);
733 733 mutex_exit(&state->ts_fw_flashlock);
734 734
735 735 TAVOR_TNF_EXIT(tavor_ioctl_flash_cleanup);
736 736 }
737 737
738 738
739 739 /*
740 740 * tavor_ioctl_flash_cleanup_nolock()
741 741 */
742 742 static void
743 743 tavor_ioctl_flash_cleanup_nolock(tavor_state_t *state)
744 744 {
745 745 TAVOR_TNF_ENTER(tavor_ioctl_flash_cleanup_nolock);
746 746
747 747 ASSERT(MUTEX_HELD(&state->ts_fw_flashlock));
748 748
749 749 /* free flash mem */
750 750 kmem_free(state->ts_fw_sector, 1 << state->ts_fw_log_sector_sz);
751 751
752 752 /* Fini the Flash */
753 753 tavor_flash_fini(state);
754 754
755 755 /* Set flash state to fini */
756 756 state->ts_fw_flashstarted = 0;
757 757 state->ts_fw_flashdev = 0;
758 758
759 759 TAVOR_TNF_EXIT(tavor_ioctl_flash_cleanup_nolock);
760 760 }
761 761
762 762
763 763 /*
764 764 * tavor_ioctl_info()
765 765 */
766 766 static int
767 767 tavor_ioctl_info(tavor_state_t *state, dev_t dev, intptr_t arg, int mode)
768 768 {
769 769 tavor_info_ioctl_t info;
770 770 tavor_flash_init_ioctl_t init_info;
771 771
772 772 TAVOR_TNF_ENTER(tavor_ioctl_info);
773 773
774 774 /*
775 775 * Access to Tavor VTS ioctls is not allowed in "maintenance mode".
776 776 */
777 777 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) {
778 778 TNF_PROBE_0(tavor_ioctl_info_maintenance_mode_fail,
779 779 TAVOR_TNF_ERROR, "");
780 780 TAVOR_TNF_EXIT(tavor_ioctl_info);
781 781 return (EFAULT);
782 782 }
783 783
784 784 /* copyin the user struct to kernel */
785 785 if (ddi_copyin((void *)arg, &info, sizeof (tavor_info_ioctl_t),
786 786 mode) != 0) {
787 787 TNF_PROBE_0(tavor_ioctl_info_copyin_fail, TAVOR_TNF_ERROR, "");
788 788 TAVOR_TNF_EXIT(tavor_ioctl_info);
789 789 return (EFAULT);
790 790 }
791 791
792 792 /*
793 793 * Check ioctl revision
794 794 */
795 795 if (info.ti_revision != TAVOR_VTS_IOCTL_REVISION) {
796 796 TNF_PROBE_0(tavor_ioctl_info_bad_rev, TAVOR_TNF_ERROR, "");
797 797 TAVOR_TNF_EXIT(tavor_ioctl_info);
798 798 return (EINVAL);
799 799 }
800 800
801 801 /*
802 802 * If the 'fw_device_sz' has not been initialized yet, we initialize it
803 803 * here. This is done by leveraging the
804 804 * tavor_ioctl_flash_init()/fini() calls. We also hold our own mutex
805 805 * around this operation in case we have multiple VTS threads in
806 806 * process at the same time.
807 807 */
808 808 mutex_enter(&state->ts_info_lock);
809 809 if (state->ts_fw_device_sz == 0) {
810 810 if (tavor_ioctl_flash_init(state, dev, (intptr_t)&init_info,
811 811 (FKIOCTL | mode)) != 0) {
812 812 mutex_exit(&state->ts_info_lock);
813 813 TNF_PROBE_0(tavor_ioctl_info_flash_init_fail,
814 814 TAVOR_TNF_ERROR, "");
815 815 TAVOR_TNF_EXIT(tavor_ioctl_info);
816 816 return (EFAULT);
817 817 }
818 818 (void) tavor_ioctl_flash_fini(state, dev);
819 819 }
820 820 mutex_exit(&state->ts_info_lock);
821 821
822 822 info.ti_hw_rev = state->ts_adapter.rev_id;
823 823 info.ti_flash_sz = state->ts_fw_device_sz;
824 824 info.ti_fw_rev.tfi_maj = state->ts_fw.fw_rev_major;
825 825 info.ti_fw_rev.tfi_min = state->ts_fw.fw_rev_minor;
826 826 info.ti_fw_rev.tfi_sub = state->ts_fw.fw_rev_subminor;
827 827 info.ti_mem_start_offset = 0;
828 828 info.ti_mem_end_offset = state->ts_ddr.ddr_endaddr -
829 829 state->ts_ddr.ddr_baseaddr;
830 830
831 831 /* Copy ioctl results back to user struct */
832 832 if (ddi_copyout(&info, (void *)arg, sizeof (tavor_info_ioctl_t),
833 833 mode) != 0) {
834 834 TNF_PROBE_0(tavor_ioctl_info_copyout_fail, TAVOR_TNF_ERROR, "");
835 835 TAVOR_TNF_EXIT(tavor_ioctl_info);
836 836 return (EFAULT);
837 837 }
838 838
839 839 TAVOR_TNF_EXIT(tavor_ioctl_info);
840 840 return (0);
841 841 }
842 842
843 843 /*
844 844 * tavor_ioctl_ports()
845 845 */
846 846 static int
847 847 tavor_ioctl_ports(tavor_state_t *state, intptr_t arg, int mode)
848 848 {
849 849 tavor_ports_ioctl_t info;
850 850 tavor_stat_port_ioctl_t portstat;
851 851 ibt_hca_portinfo_t pi;
852 852 uint_t tbl_size;
853 853 ib_gid_t *sgid_tbl;
854 854 ib_pkey_t *pkey_tbl;
855 855 int i;
856 856
857 857 TAVOR_TNF_ENTER(tavor_ioctl_ports);
858 858
859 859 /*
860 860 * Access to Tavor VTS ioctls is not allowed in "maintenance mode".
861 861 */
862 862 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) {
863 863 TNF_PROBE_0(tavor_ioctl_ports_maintenance_mode_fail,
864 864 TAVOR_TNF_ERROR, "");
865 865 TAVOR_TNF_EXIT(tavor_ioctl_ports);
866 866 return (EFAULT);
867 867 }
868 868
869 869 /* copyin the user struct to kernel */
870 870 #ifdef _MULTI_DATAMODEL
871 871 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
872 872 tavor_ports_ioctl32_t info32;
873 873
874 874 if (ddi_copyin((void *)arg, &info32,
875 875 sizeof (tavor_ports_ioctl32_t), mode) != 0) {
876 876 TNF_PROBE_0(tavor_ioctl_ports_copyin_fail,
877 877 TAVOR_TNF_ERROR, "");
878 878 TAVOR_TNF_EXIT(tavor_ioctl_ports);
879 879 return (EFAULT);
880 880 }
881 881 info.tp_revision = info32.tp_revision;
882 882 info.tp_ports =
883 883 (tavor_stat_port_ioctl_t *)(uintptr_t)info32.tp_ports;
884 884 info.tp_num_ports = info32.tp_num_ports;
885 885
886 886 } else
887 887 #endif /* _MULTI_DATAMODEL */
888 888 if (ddi_copyin((void *)arg, &info, sizeof (tavor_ports_ioctl_t),
889 889 mode) != 0) {
890 890 TNF_PROBE_0(tavor_ioctl_ports_copyin_fail, TAVOR_TNF_ERROR, "");
891 891 TAVOR_TNF_EXIT(tavor_ioctl_ports);
892 892 return (EFAULT);
893 893 }
894 894
895 895 /*
896 896 * Check ioctl revision
897 897 */
898 898 if (info.tp_revision != TAVOR_VTS_IOCTL_REVISION) {
899 899 TNF_PROBE_0(tavor_ioctl_ports_bad_rev, TAVOR_TNF_ERROR, "");
900 900 TAVOR_TNF_EXIT(tavor_ioctl_ports);
901 901 return (EINVAL);
↓ open down ↓ |
901 lines elided |
↑ open up ↑ |
902 902 }
903 903
904 904 /* Allocate space for temporary GID table/PKey table */
905 905 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl);
906 906 sgid_tbl = (ib_gid_t *)kmem_zalloc(tbl_size * sizeof (ib_gid_t),
907 907 KM_SLEEP);
908 908 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl);
909 909 pkey_tbl = (ib_pkey_t *)kmem_zalloc(tbl_size * sizeof (ib_pkey_t),
910 910 KM_SLEEP);
911 911
912 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sgid_tbl, *pkey_tbl))
913 -
914 912 /*
915 913 * Setup the number of ports, then loop through all ports and
916 914 * query properties of each.
917 915 */
918 916 info.tp_num_ports = (uint8_t)state->ts_cfg_profile->cp_num_ports;
919 917 for (i = 0; i < info.tp_num_ports; i++) {
920 918 /*
921 919 * Get portstate information from the device. If
922 920 * tavor_port_query() fails, leave zeroes in user
923 921 * struct port entry and continue.
924 922 */
925 923 bzero(&pi, sizeof (ibt_hca_portinfo_t));
926 924 pi.p_sgid_tbl = sgid_tbl;
927 925 pi.p_pkey_tbl = pkey_tbl;
928 926 if (tavor_port_query(state, i + 1, &pi) != 0) {
929 927 TNF_PROBE_0(tavor_ioctl_ports_query_failed,
930 928 TAVOR_TNF_ERROR, "");
931 929 }
932 930
933 931 portstat.tsp_port_num = pi.p_port_num;
934 932 portstat.tsp_state = pi.p_linkstate;
935 933 portstat.tsp_guid = pi.p_sgid_tbl[0].gid_guid;
936 934
937 935 /*
938 936 * Copy queried port results back to user struct. If
939 937 * this fails, then break out of loop, attempt to copy
940 938 * out remaining info to user struct, and return (without
941 939 * error).
942 940 */
943 941 if (ddi_copyout(&portstat,
944 942 &(((tavor_stat_port_ioctl_t *)info.tp_ports)[i]),
945 943 sizeof (tavor_stat_port_ioctl_t), mode) != 0) {
946 944 break;
947 945 }
948 946 }
949 947
950 948 /* Free the temporary space used for GID table/PKey table */
951 949 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl);
952 950 kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t));
953 951 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl);
954 952 kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t));
955 953
956 954 /* Copy ioctl results back to user struct */
957 955 #ifdef _MULTI_DATAMODEL
958 956 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
959 957 tavor_ports_ioctl32_t info32;
960 958
961 959 info32.tp_revision = info.tp_revision;
962 960 info32.tp_ports = (caddr32_t)(uintptr_t)info.tp_ports;
963 961 info32.tp_num_ports = info.tp_num_ports;
964 962
965 963 if (ddi_copyout(&info32, (void *)arg,
966 964 sizeof (tavor_ports_ioctl32_t), mode) != 0) {
967 965 TNF_PROBE_0(tavor_ioctl_ports_copyout_fail,
968 966 TAVOR_TNF_ERROR, "");
969 967 TAVOR_TNF_EXIT(tavor_ioctl_ports);
970 968 return (EFAULT);
971 969 }
972 970 } else
973 971 #endif /* _MULTI_DATAMODEL */
974 972 if (ddi_copyout(&info, (void *)arg, sizeof (tavor_ports_ioctl_t),
975 973 mode) != 0) {
976 974 TNF_PROBE_0(tavor_ioctl_ports_copyout_fail,
977 975 TAVOR_TNF_ERROR, "");
978 976 TAVOR_TNF_EXIT(tavor_ioctl_ports);
979 977 return (EFAULT);
980 978 }
981 979
982 980 TAVOR_TNF_EXIT(tavor_ioctl_ports);
983 981 return (0);
984 982 }
985 983
986 984 /*
987 985 * tavor_ioctl_loopback()
988 986 */
989 987 static int
990 988 tavor_ioctl_loopback(tavor_state_t *state, intptr_t arg, int mode)
991 989 {
↓ open down ↓ |
68 lines elided |
↑ open up ↑ |
992 990 tavor_loopback_ioctl_t lb;
993 991 tavor_loopback_state_t lstate;
994 992 ibt_hca_portinfo_t pi;
995 993 uint_t tbl_size, loopmax, max_usec;
996 994 ib_gid_t *sgid_tbl;
997 995 ib_pkey_t *pkey_tbl;
998 996 int j, iter, ret;
999 997
1000 998 TAVOR_TNF_ENTER(tavor_ioctl_loopback);
1001 999
1002 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(lstate))
1003 -
1004 1000 /*
1005 1001 * Access to Tavor VTS ioctls is not allowed in "maintenance mode".
1006 1002 */
1007 1003 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) {
1008 1004 TNF_PROBE_0(tavor_ioctl_loopback_maintenance_mode_fail,
1009 1005 TAVOR_TNF_ERROR, "");
1010 1006 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1011 1007 return (EFAULT);
1012 1008 }
1013 1009
1014 1010 /* copyin the user struct to kernel */
1015 1011 #ifdef _MULTI_DATAMODEL
1016 1012 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1017 1013 tavor_loopback_ioctl32_t lb32;
1018 1014
1019 1015 if (ddi_copyin((void *)arg, &lb32,
1020 1016 sizeof (tavor_loopback_ioctl32_t), mode) != 0) {
1021 1017 TNF_PROBE_0(tavor_ioctl_loopback_copyin_fail,
1022 1018 TAVOR_TNF_ERROR, "");
1023 1019 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1024 1020 return (EFAULT);
1025 1021 }
1026 1022 lb.tlb_revision = lb32.tlb_revision;
1027 1023 lb.tlb_send_buf = (caddr_t)(uintptr_t)lb32.tlb_send_buf;
1028 1024 lb.tlb_fail_buf = (caddr_t)(uintptr_t)lb32.tlb_fail_buf;
1029 1025 lb.tlb_buf_sz = lb32.tlb_buf_sz;
1030 1026 lb.tlb_num_iter = lb32.tlb_num_iter;
1031 1027 lb.tlb_pass_done = lb32.tlb_pass_done;
1032 1028 lb.tlb_timeout = lb32.tlb_timeout;
1033 1029 lb.tlb_error_type = lb32.tlb_error_type;
1034 1030 lb.tlb_port_num = lb32.tlb_port_num;
1035 1031 lb.tlb_num_retry = lb32.tlb_num_retry;
1036 1032 } else
1037 1033 #endif /* _MULTI_DATAMODEL */
1038 1034 if (ddi_copyin((void *)arg, &lb, sizeof (tavor_loopback_ioctl_t),
1039 1035 mode) != 0) {
1040 1036 TNF_PROBE_0(tavor_ioctl_loopback_copyin_fail,
1041 1037 TAVOR_TNF_ERROR, "");
1042 1038 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1043 1039 return (EFAULT);
1044 1040 }
1045 1041
1046 1042 /* Initialize the internal loopback test state structure */
1047 1043 bzero(&lstate, sizeof (tavor_loopback_state_t));
1048 1044
1049 1045 /*
1050 1046 * Check ioctl revision
1051 1047 */
1052 1048 if (lb.tlb_revision != TAVOR_VTS_IOCTL_REVISION) {
1053 1049 lb.tlb_error_type = TAVOR_LOOPBACK_INVALID_REVISION;
1054 1050 (void) tavor_loopback_copyout(&lb, arg, mode);
1055 1051 TNF_PROBE_0(tavor_ioctl_loopback_bad_rev,
1056 1052 TAVOR_TNF_ERROR, "");
1057 1053 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1058 1054 return (EINVAL);
1059 1055 }
1060 1056
1061 1057 /* Validate that specified port number is legal */
1062 1058 if (!tavor_portnum_is_valid(state, lb.tlb_port_num)) {
1063 1059 lb.tlb_error_type = TAVOR_LOOPBACK_INVALID_PORT;
1064 1060 (void) tavor_loopback_copyout(&lb, arg, mode);
1065 1061 TNF_PROBE_0(tavor_ioctl_loopback_inv_port,
1066 1062 TAVOR_TNF_ERROR, "");
1067 1063 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1068 1064 return (EINVAL);
1069 1065 }
1070 1066
1071 1067 /* Allocate space for temporary GID table/PKey table */
1072 1068 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl);
1073 1069 sgid_tbl = (ib_gid_t *)kmem_zalloc(tbl_size * sizeof (ib_gid_t),
1074 1070 KM_SLEEP);
1075 1071 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl);
1076 1072 pkey_tbl = (ib_pkey_t *)kmem_zalloc(tbl_size * sizeof (ib_pkey_t),
1077 1073 KM_SLEEP);
1078 1074
1079 1075 /*
1080 1076 * Get portstate information from specific port on device
1081 1077 */
1082 1078 bzero(&pi, sizeof (ibt_hca_portinfo_t));
1083 1079 pi.p_sgid_tbl = sgid_tbl;
1084 1080 pi.p_pkey_tbl = pkey_tbl;
1085 1081 if (tavor_port_query(state, lb.tlb_port_num, &pi) != 0) {
1086 1082 /* Free the temporary space used for GID table/PKey table */
1087 1083 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl);
1088 1084 kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t));
1089 1085 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl);
1090 1086 kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t));
1091 1087
1092 1088 lb.tlb_error_type = TAVOR_LOOPBACK_INVALID_PORT;
1093 1089 (void) tavor_loopback_copyout(&lb, arg, mode);
1094 1090 tavor_loopback_free_state(&lstate);
1095 1091 TNF_PROBE_0(tavor_ioctl_loopback_bad_port,
1096 1092 TAVOR_TNF_ERROR, "");
1097 1093 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1098 1094 return (EINVAL);
1099 1095 }
1100 1096
1101 1097 lstate.tls_port = pi.p_port_num;
1102 1098 lstate.tls_lid = pi.p_base_lid;
1103 1099 lstate.tls_pkey_ix = (pi.p_linkstate == TAVOR_PORT_LINK_ACTIVE) ? 1 : 0;
1104 1100 lstate.tls_state = state;
1105 1101 lstate.tls_retry = lb.tlb_num_retry;
1106 1102
1107 1103 /* Free the temporary space used for GID table/PKey table */
1108 1104 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl);
1109 1105 kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t));
1110 1106 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl);
1111 1107 kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t));
1112 1108
1113 1109 /*
1114 1110 * Compute the timeout duration in usec per the formula:
1115 1111 * to_usec_per_retry = 4.096us * (2 ^ supplied_timeout)
1116 1112 * (plus we add a little fudge-factor here too)
1117 1113 */
1118 1114 lstate.tls_timeout = lb.tlb_timeout;
1119 1115 max_usec = (4096 * (1 << lstate.tls_timeout)) / 1000;
1120 1116 max_usec = max_usec * (lstate.tls_retry + 1);
1121 1117 max_usec = max_usec + 10000;
1122 1118
1123 1119 /*
1124 1120 * Determine how many times we should loop before declaring a
1125 1121 * timeout failure.
1126 1122 */
1127 1123 loopmax = max_usec/TAVOR_VTS_LOOPBACK_MIN_WAIT_DUR;
1128 1124 if ((max_usec % TAVOR_VTS_LOOPBACK_MIN_WAIT_DUR) != 0) {
1129 1125 loopmax++;
1130 1126 }
1131 1127
1132 1128 if (lb.tlb_send_buf == NULL || lb.tlb_buf_sz == 0) {
1133 1129 lb.tlb_error_type = TAVOR_LOOPBACK_SEND_BUF_INVALID;
1134 1130 (void) tavor_loopback_copyout(&lb, arg, mode);
1135 1131 tavor_loopback_free_state(&lstate);
1136 1132 TNF_PROBE_0(tavor_ioctl_loopback_buf_null,
1137 1133 TAVOR_TNF_ERROR, "");
1138 1134 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1139 1135 return (EINVAL);
1140 1136 }
1141 1137
1142 1138 /* Allocate protection domain (PD) */
1143 1139 if (tavor_loopback_init(state, &lstate) != 0) {
1144 1140 lb.tlb_error_type = lstate.tls_err;
1145 1141 (void) tavor_loopback_copyout(&lb, arg, mode);
1146 1142 tavor_loopback_free_state(&lstate);
1147 1143 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1148 1144 return (EFAULT);
1149 1145 }
1150 1146
1151 1147 /* Allocate and register a TX buffer */
1152 1148 if (tavor_loopback_alloc_mem(&lstate, &lstate.tls_tx,
1153 1149 lb.tlb_buf_sz) != 0) {
1154 1150 lb.tlb_error_type =
1155 1151 TAVOR_LOOPBACK_SEND_BUF_MEM_REGION_ALLOC_FAIL;
1156 1152 (void) tavor_loopback_copyout(&lb, arg, mode);
1157 1153 tavor_loopback_free_state(&lstate);
1158 1154 TNF_PROBE_0(tavor_ioctl_loopback_txbuf_alloc_fail,
1159 1155 TAVOR_TNF_ERROR, "");
1160 1156 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1161 1157 return (EFAULT);
1162 1158 }
1163 1159
1164 1160 /* Allocate and register an RX buffer */
1165 1161 if (tavor_loopback_alloc_mem(&lstate, &lstate.tls_rx,
1166 1162 lb.tlb_buf_sz) != 0) {
1167 1163 lb.tlb_error_type =
1168 1164 TAVOR_LOOPBACK_RECV_BUF_MEM_REGION_ALLOC_FAIL;
1169 1165 (void) tavor_loopback_copyout(&lb, arg, mode);
1170 1166 tavor_loopback_free_state(&lstate);
1171 1167 TNF_PROBE_0(tavor_ioctl_loopback_rxbuf_alloc_fail,
1172 1168 TAVOR_TNF_ERROR, "");
1173 1169 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1174 1170 return (EFAULT);
1175 1171 }
1176 1172
1177 1173 /* Copy in the transmit buffer data */
1178 1174 if (ddi_copyin((void *)lb.tlb_send_buf, lstate.tls_tx.tlc_buf,
1179 1175 lb.tlb_buf_sz, mode) != 0) {
1180 1176 lb.tlb_error_type = TAVOR_LOOPBACK_SEND_BUF_COPY_FAIL;
1181 1177 (void) tavor_loopback_copyout(&lb, arg, mode);
1182 1178 tavor_loopback_free_state(&lstate);
1183 1179 TNF_PROBE_0(tavor_ioctl_loopback_tx_copyin_fail,
1184 1180 TAVOR_TNF_ERROR, "");
1185 1181 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1186 1182 return (EFAULT);
1187 1183 }
1188 1184
1189 1185 /* Allocate the transmit QP and CQs */
1190 1186 lstate.tls_err = TAVOR_LOOPBACK_XMIT_SEND_CQ_ALLOC_FAIL;
1191 1187 if (tavor_loopback_alloc_qps(&lstate, &lstate.tls_tx) != 0) {
1192 1188 lb.tlb_error_type = lstate.tls_err;
1193 1189 (void) tavor_loopback_copyout(&lb, arg, mode);
1194 1190 tavor_loopback_free_state(&lstate);
1195 1191 TNF_PROBE_0(tavor_ioctl_loopback_txqp_alloc_fail,
1196 1192 TAVOR_TNF_ERROR, "");
1197 1193 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1198 1194 return (EFAULT);
1199 1195 }
1200 1196
1201 1197 /* Allocate the receive QP and CQs */
1202 1198 lstate.tls_err = TAVOR_LOOPBACK_RECV_SEND_CQ_ALLOC_FAIL;
1203 1199 if (tavor_loopback_alloc_qps(&lstate, &lstate.tls_rx) != 0) {
1204 1200 lb.tlb_error_type = lstate.tls_err;
1205 1201 (void) tavor_loopback_copyout(&lb, arg, mode);
1206 1202 tavor_loopback_free_state(&lstate);
1207 1203 TNF_PROBE_0(tavor_ioctl_loopback_rxqp_alloc_fail,
1208 1204 TAVOR_TNF_ERROR, "");
1209 1205 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1210 1206 return (EFAULT);
1211 1207 }
1212 1208
1213 1209 /* Activate the TX QP (connect to RX QP) */
1214 1210 lstate.tls_err = TAVOR_LOOPBACK_XMIT_QP_INIT_FAIL;
1215 1211 if (tavor_loopback_modify_qp(&lstate, &lstate.tls_tx,
1216 1212 lstate.tls_rx.tlc_qp_num) != 0) {
1217 1213 lb.tlb_error_type = lstate.tls_err;
1218 1214 (void) tavor_loopback_copyout(&lb, arg, mode);
1219 1215 tavor_loopback_free_state(&lstate);
1220 1216 TNF_PROBE_0(tavor_ioctl_loopback_txqp_init_fail,
1221 1217 TAVOR_TNF_ERROR, "");
1222 1218 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1223 1219 return (EFAULT);
1224 1220 }
1225 1221
1226 1222 /* Activate the RX QP (connect to TX QP) */
1227 1223 lstate.tls_err = TAVOR_LOOPBACK_RECV_QP_INIT_FAIL;
1228 1224 if (tavor_loopback_modify_qp(&lstate, &lstate.tls_rx,
1229 1225 lstate.tls_tx.tlc_qp_num) != 0) {
1230 1226 lb.tlb_error_type = lstate.tls_err;
1231 1227 (void) tavor_loopback_copyout(&lb, arg, mode);
1232 1228 tavor_loopback_free_state(&lstate);
1233 1229 TNF_PROBE_0(tavor_ioctl_loopback_rxqp_init_fail,
1234 1230 TAVOR_TNF_ERROR, "");
1235 1231 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1236 1232 return (EFAULT);
1237 1233 }
1238 1234
1239 1235 /* Run the loopback test (for specified number of iterations) */
1240 1236 lb.tlb_pass_done = 0;
1241 1237 for (iter = 0; iter < lb.tlb_num_iter; iter++) {
1242 1238 lstate.tls_err = 0;
1243 1239 bzero(lstate.tls_rx.tlc_buf, lb.tlb_buf_sz);
1244 1240
1245 1241 /* Post RDMA Write work request */
1246 1242 if (tavor_loopback_post_send(&lstate, &lstate.tls_tx,
1247 1243 &lstate.tls_rx) != IBT_SUCCESS) {
1248 1244 lb.tlb_error_type = TAVOR_LOOPBACK_WQE_POST_FAIL;
1249 1245 (void) tavor_loopback_copyout(&lb, arg, mode);
1250 1246 tavor_loopback_free_state(&lstate);
1251 1247 TNF_PROBE_0(tavor_ioctl_loopback_wqe_post_fail,
1252 1248 TAVOR_TNF_ERROR, "");
1253 1249 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1254 1250 return (EFAULT);
1255 1251 }
1256 1252
1257 1253 /* Poll the TX CQ for a completion every few ticks */
1258 1254 for (j = 0; j < loopmax; j++) {
1259 1255 delay(drv_usectohz(TAVOR_VTS_LOOPBACK_MIN_WAIT_DUR));
1260 1256
1261 1257 ret = tavor_loopback_poll_cq(&lstate, &lstate.tls_tx);
1262 1258 if (((ret != IBT_SUCCESS) && (ret != IBT_CQ_EMPTY)) ||
1263 1259 ((ret == IBT_CQ_EMPTY) && (j == loopmax - 1))) {
1264 1260 lb.tlb_error_type = TAVOR_LOOPBACK_CQ_POLL_FAIL;
1265 1261 if (ddi_copyout(lstate.tls_rx.tlc_buf,
1266 1262 lb.tlb_fail_buf, lstate.tls_tx.tlc_buf_sz,
1267 1263 mode) != 0) {
1268 1264 TNF_PROBE_0(
1269 1265 tavor_ioctl_loopback_xfer_co_fail,
1270 1266 TAVOR_TNF_ERROR, "");
1271 1267 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1272 1268 return (EFAULT);
1273 1269 }
1274 1270 (void) tavor_loopback_copyout(&lb, arg, mode);
1275 1271 tavor_loopback_free_state(&lstate);
1276 1272 TNF_PROBE_0(tavor_ioctl_loopback_xfer_fail,
1277 1273 TAVOR_TNF_ERROR, "");
1278 1274 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1279 1275 return (EFAULT);
1280 1276 } else if (ret == IBT_CQ_EMPTY) {
1281 1277 continue;
1282 1278 }
1283 1279
1284 1280 /* Compare the data buffers */
1285 1281 if (bcmp(lstate.tls_tx.tlc_buf, lstate.tls_rx.tlc_buf,
1286 1282 lb.tlb_buf_sz) == 0) {
1287 1283 break;
1288 1284 } else {
1289 1285 lb.tlb_error_type =
1290 1286 TAVOR_LOOPBACK_SEND_RECV_COMPARE_FAIL;
1291 1287 if (ddi_copyout(lstate.tls_rx.tlc_buf,
1292 1288 lb.tlb_fail_buf, lstate.tls_tx.tlc_buf_sz,
1293 1289 mode) != 0) {
1294 1290 TNF_PROBE_0(
1295 1291 tavor_ioctl_loopback_bcmp_co_fail,
1296 1292 TAVOR_TNF_ERROR, "");
1297 1293 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1298 1294 return (EFAULT);
1299 1295 }
1300 1296 (void) tavor_loopback_copyout(&lb, arg, mode);
1301 1297 tavor_loopback_free_state(&lstate);
1302 1298 TNF_PROBE_0(tavor_ioctl_loopback_bcmp_fail,
1303 1299 TAVOR_TNF_ERROR, "");
1304 1300 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1305 1301 return (EFAULT);
1306 1302 }
1307 1303 }
1308 1304
1309 1305 lstate.tls_err = TAVOR_LOOPBACK_SUCCESS;
1310 1306 lb.tlb_pass_done = iter + 1;
1311 1307 }
1312 1308
1313 1309 lb.tlb_error_type = TAVOR_LOOPBACK_SUCCESS;
1314 1310
1315 1311 /* Copy ioctl results back to user struct */
1316 1312 ret = tavor_loopback_copyout(&lb, arg, mode);
1317 1313
1318 1314 /* Free up everything and release all consumed resources */
1319 1315 tavor_loopback_free_state(&lstate);
1320 1316
1321 1317 TAVOR_TNF_EXIT(tavor_ioctl_loopback);
1322 1318 return (ret);
1323 1319 }
1324 1320
1325 1321 /*
1326 1322 * tavor_ioctl_ddr_read()
1327 1323 */
1328 1324 static int
1329 1325 tavor_ioctl_ddr_read(tavor_state_t *state, intptr_t arg, int mode)
1330 1326 {
1331 1327 tavor_ddr_read_ioctl_t rdreg;
1332 1328 uint32_t *addr;
1333 1329 uintptr_t baseaddr;
1334 1330 uint64_t ddr_size;
1335 1331
1336 1332 TAVOR_TNF_ENTER(tavor_ioctl_ddr_read);
1337 1333
1338 1334 /*
1339 1335 * Access to Tavor VTS ioctls is not allowed in "maintenance mode".
1340 1336 */
1341 1337 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) {
1342 1338 TNF_PROBE_0(tavor_ioctl_ddr_read_maintenance_mode_fail,
1343 1339 TAVOR_TNF_ERROR, "");
1344 1340 TAVOR_TNF_EXIT(tavor_ioctl_ddr_read);
1345 1341 return (EFAULT);
1346 1342 }
1347 1343
1348 1344 /* copyin the user struct to kernel */
1349 1345 if (ddi_copyin((void *)arg, &rdreg, sizeof (tavor_ddr_read_ioctl_t),
1350 1346 mode) != 0) {
1351 1347 TNF_PROBE_0(tavor_ioctl_ddr_read_copyin_fail,
1352 1348 TAVOR_TNF_ERROR, "");
1353 1349 TAVOR_TNF_EXIT(tavor_ioctl_ddr_read);
1354 1350 return (EFAULT);
1355 1351 }
1356 1352
1357 1353 /*
1358 1354 * Check ioctl revision
1359 1355 */
1360 1356 if (rdreg.tdr_revision != TAVOR_VTS_IOCTL_REVISION) {
1361 1357 TNF_PROBE_0(tavor_ioctl_ddr_read_bad_rev, TAVOR_TNF_ERROR, "");
1362 1358 TAVOR_TNF_EXIT(tavor_ioctl_ddr_read);
1363 1359 return (EINVAL);
1364 1360 }
1365 1361
1366 1362 /*
1367 1363 * Check for valid offset
1368 1364 */
1369 1365 ddr_size = (state->ts_ddr.ddr_endaddr - state->ts_ddr.ddr_baseaddr + 1);
1370 1366 if ((uint64_t)rdreg.tdr_offset >= ddr_size) {
1371 1367 TNF_PROBE_0(tavor_ioctl_ddr_read_bad_offset,
1372 1368 TAVOR_TNF_ERROR, "");
1373 1369 TAVOR_TNF_EXIT(tavor_ioctl_ddr_read);
1374 1370 return (EINVAL);
1375 1371 }
1376 1372
1377 1373 /* Determine base address for requested register read */
1378 1374 baseaddr = (uintptr_t)state->ts_reg_ddr_baseaddr;
1379 1375
1380 1376 /* Ensure that address is properly-aligned */
1381 1377 addr = (uint32_t *)((baseaddr + rdreg.tdr_offset) & ~0x3);
1382 1378
1383 1379 /* Read the register pointed to by addr */
1384 1380 rdreg.tdr_data = ddi_get32(state->ts_reg_cmdhdl, addr);
1385 1381
1386 1382 /* Copy ioctl results back to user struct */
1387 1383 if (ddi_copyout(&rdreg, (void *)arg, sizeof (tavor_ddr_read_ioctl_t),
1388 1384 mode) != 0) {
1389 1385 TNF_PROBE_0(tavor_ioctl_ddr_read_copyout_fail,
1390 1386 TAVOR_TNF_ERROR, "");
1391 1387 TAVOR_TNF_EXIT(tavor_ioctl_ddr_read);
1392 1388 return (EFAULT);
1393 1389 }
1394 1390
1395 1391 TAVOR_TNF_EXIT(tavor_ioctl_ddr_read);
1396 1392 return (0);
1397 1393 }
1398 1394
1399 1395
1400 1396 #ifdef DEBUG
1401 1397 /*
1402 1398 * tavor_ioctl_reg_read()
1403 1399 */
1404 1400 static int
1405 1401 tavor_ioctl_reg_read(tavor_state_t *state, intptr_t arg, int mode)
1406 1402 {
1407 1403 tavor_reg_ioctl_t rdreg;
1408 1404 uint32_t *addr;
1409 1405 uintptr_t baseaddr;
1410 1406 int status;
1411 1407
1412 1408 TAVOR_TNF_ENTER(tavor_ioctl_reg_read);
1413 1409
1414 1410 /*
1415 1411 * Access to Tavor registers is not allowed in "maintenance mode".
1416 1412 * This is primarily because the device may not have BARs to access
1417 1413 */
1418 1414 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) {
1419 1415 TNF_PROBE_0(tavor_ioctl_reg_read_maintence_mode_fail,
1420 1416 TAVOR_TNF_ERROR, "");
1421 1417 TAVOR_TNF_EXIT(tavor_ioctl_reg_read);
1422 1418 return (EFAULT);
1423 1419 }
1424 1420
1425 1421 /* Copy in the tavor_reg_ioctl_t structure */
1426 1422 status = ddi_copyin((void *)arg, &rdreg, sizeof (tavor_reg_ioctl_t),
1427 1423 mode);
1428 1424 if (status != 0) {
1429 1425 TNF_PROBE_0(tavor_ioctl_reg_read_copyin_fail,
1430 1426 TAVOR_TNF_ERROR, "");
1431 1427 TAVOR_TNF_EXIT(tavor_ioctl_reg_read);
1432 1428 return (EFAULT);
1433 1429 }
1434 1430
1435 1431 /* Determine base address for requested register set */
1436 1432 switch (rdreg.trg_reg_set) {
1437 1433 case TAVOR_CMD_BAR:
1438 1434 baseaddr = (uintptr_t)state->ts_reg_cmd_baseaddr;
1439 1435 break;
1440 1436
1441 1437 case TAVOR_UAR_BAR:
1442 1438 baseaddr = (uintptr_t)state->ts_reg_uar_baseaddr;
1443 1439 break;
1444 1440
1445 1441 case TAVOR_DDR_BAR:
1446 1442 baseaddr = (uintptr_t)state->ts_reg_ddr_baseaddr;
1447 1443 break;
1448 1444
1449 1445 default:
1450 1446 TNF_PROBE_0(tavor_ioctl_reg_read_invregset_fail,
1451 1447 TAVOR_TNF_ERROR, "");
1452 1448 TAVOR_TNF_EXIT(tavor_ioctl_reg_read);
1453 1449 return (EFAULT);
1454 1450 }
1455 1451
1456 1452 /* Ensure that address is properly-aligned */
1457 1453 addr = (uint32_t *)((baseaddr + rdreg.trg_offset) & ~0x3);
1458 1454
1459 1455 /* Read the register pointed to by addr */
1460 1456 rdreg.trg_data = ddi_get32(state->ts_reg_cmdhdl, addr);
1461 1457
1462 1458 /* Copy in the result into the tavor_reg_ioctl_t structure */
1463 1459 status = ddi_copyout(&rdreg, (void *)arg, sizeof (tavor_reg_ioctl_t),
1464 1460 mode);
1465 1461 if (status != 0) {
1466 1462 TNF_PROBE_0(tavor_ioctl_reg_read_copyout_fail,
1467 1463 TAVOR_TNF_ERROR, "");
1468 1464 TAVOR_TNF_EXIT(tavor_ioctl_reg_read);
1469 1465 return (EFAULT);
1470 1466 }
1471 1467
1472 1468 TAVOR_TNF_EXIT(tavor_ioctl_reg_read);
1473 1469 return (0);
1474 1470 }
1475 1471
1476 1472
1477 1473 /*
1478 1474 * tavor_ioctl_reg_write()
1479 1475 */
1480 1476 static int
1481 1477 tavor_ioctl_reg_write(tavor_state_t *state, intptr_t arg, int mode)
1482 1478 {
1483 1479 tavor_reg_ioctl_t wrreg;
1484 1480 uint32_t *addr;
1485 1481 uintptr_t baseaddr;
1486 1482 int status;
1487 1483
1488 1484 TAVOR_TNF_ENTER(tavor_ioctl_reg_write);
1489 1485
1490 1486 /*
1491 1487 * Access to Tavor registers is not allowed in "maintenance mode".
1492 1488 * This is primarily because the device may not have BARs to access
1493 1489 */
1494 1490 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) {
1495 1491 TNF_PROBE_0(tavor_ioctl_reg_write_maintence_mode_fail,
1496 1492 TAVOR_TNF_ERROR, "");
1497 1493 TAVOR_TNF_EXIT(tavor_ioctl_reg_write);
1498 1494 return (EFAULT);
1499 1495 }
1500 1496
1501 1497 /* Copy in the tavor_reg_ioctl_t structure */
1502 1498 status = ddi_copyin((void *)arg, &wrreg, sizeof (tavor_reg_ioctl_t),
1503 1499 mode);
1504 1500 if (status != 0) {
1505 1501 TNF_PROBE_0(tavor_ioctl_reg_write_copyin_fail,
1506 1502 TAVOR_TNF_ERROR, "");
1507 1503 TAVOR_TNF_EXIT(tavor_ioctl_reg_write);
1508 1504 return (EFAULT);
1509 1505 }
1510 1506
1511 1507 /* Determine base address for requested register set */
1512 1508 switch (wrreg.trg_reg_set) {
1513 1509 case TAVOR_CMD_BAR:
1514 1510 baseaddr = (uintptr_t)state->ts_reg_cmd_baseaddr;
1515 1511 break;
1516 1512
1517 1513 case TAVOR_UAR_BAR:
1518 1514 baseaddr = (uintptr_t)state->ts_reg_uar_baseaddr;
1519 1515 break;
1520 1516
1521 1517 case TAVOR_DDR_BAR:
1522 1518 baseaddr = (uintptr_t)state->ts_reg_ddr_baseaddr;
1523 1519 break;
1524 1520
1525 1521 default:
1526 1522 TNF_PROBE_0(tavor_ioctl_reg_write_invregset_fail,
1527 1523 TAVOR_TNF_ERROR, "");
1528 1524 TAVOR_TNF_EXIT(tavor_ioctl_reg_write);
1529 1525 return (EFAULT);
1530 1526 }
1531 1527
1532 1528 /* Ensure that address is properly-aligned */
1533 1529 addr = (uint32_t *)((baseaddr + wrreg.trg_offset) & ~0x3);
1534 1530
1535 1531 /* Write the data to the register pointed to by addr */
1536 1532 ddi_put32(state->ts_reg_cmdhdl, addr, wrreg.trg_data);
1537 1533
1538 1534 TAVOR_TNF_EXIT(tavor_ioctl_reg_write);
1539 1535 return (0);
1540 1536 }
1541 1537 #endif /* DEBUG */
1542 1538
1543 1539 /*
1544 1540 * tavor_flash_reset()
1545 1541 */
1546 1542 static void
1547 1543 tavor_flash_reset(tavor_state_t *state)
1548 1544 {
1549 1545 TAVOR_TNF_ENTER(tavor_flash_reset);
1550 1546
1551 1547 /*
1552 1548 * Performs a reset to the flash device. After a reset the flash will
1553 1549 * be operating in normal mode (capable of read/write, etc.).
1554 1550 */
1555 1551 switch (state->ts_fw_cmdset) {
1556 1552 case TAVOR_FLASH_AMD_CMDSET:
1557 1553 tavor_flash_write(state, 0x555, TAVOR_HW_FLASH_RESET_AMD);
1558 1554 break;
1559 1555
1560 1556 case TAVOR_FLASH_INTEL_CMDSET:
1561 1557 tavor_flash_write(state, 0x555, TAVOR_HW_FLASH_RESET_INTEL);
1562 1558 break;
1563 1559
1564 1560 default:
1565 1561 break;
1566 1562 }
1567 1563
1568 1564 TAVOR_TNF_EXIT(tavor_flash_reset);
1569 1565 }
1570 1566
1571 1567 /*
1572 1568 * tavor_flash_read_sector()
1573 1569 */
1574 1570 static void
1575 1571 tavor_flash_read_sector(tavor_state_t *state, uint32_t sector_num)
1576 1572 {
1577 1573 uint32_t addr;
1578 1574 uint32_t end_addr;
1579 1575 uint32_t *image;
1580 1576 int i;
1581 1577
1582 1578 TAVOR_TNF_ENTER(tavor_flash_read_sector);
1583 1579
1584 1580 image = (uint32_t *)&state->ts_fw_sector[0];
1585 1581
1586 1582 /*
1587 1583 * Calculate the start and end address of the sector, based on the
1588 1584 * sector number passed in.
1589 1585 */
1590 1586 addr = sector_num << state->ts_fw_log_sector_sz;
1591 1587 end_addr = addr + (1 << state->ts_fw_log_sector_sz);
1592 1588
1593 1589 /* Set the flash bank correctly for the given address */
1594 1590 tavor_flash_bank(state, addr);
1595 1591
1596 1592 /* Read the entire sector, one quadlet at a time */
1597 1593 for (i = 0; addr < end_addr; i++, addr += 4) {
1598 1594 image[i] = tavor_flash_read(state, addr);
1599 1595 }
1600 1596
1601 1597 TAVOR_TNF_EXIT(tavor_flash_read_sector);
1602 1598 }
1603 1599
1604 1600 /*
1605 1601 * tavor_flash_read_quadlet()
1606 1602 */
1607 1603 static void
1608 1604 tavor_flash_read_quadlet(tavor_state_t *state, uint32_t *data,
1609 1605 uint32_t addr)
1610 1606 {
1611 1607 TAVOR_TNF_ENTER(tavor_flash_read_quadlet);
1612 1608
1613 1609 /* Set the flash bank correctly for the given address */
1614 1610 tavor_flash_bank(state, addr);
1615 1611
1616 1612 /* Read one quadlet of data */
1617 1613 *data = tavor_flash_read(state, addr);
1618 1614
1619 1615 TAVOR_TNF_EXIT(tavor_flash_read_quadlet);
1620 1616 }
1621 1617
1622 1618 /*
1623 1619 * tavor_flash_write_sector()
1624 1620 */
1625 1621 static int
1626 1622 tavor_flash_write_sector(tavor_state_t *state, uint32_t sector_num)
1627 1623 {
1628 1624 uint32_t addr;
1629 1625 uint32_t end_addr;
1630 1626 uchar_t *sector;
1631 1627 int status = 0;
1632 1628 int i;
1633 1629
1634 1630 TAVOR_TNF_ENTER(tavor_flash_write_sector);
1635 1631
1636 1632 sector = (uchar_t *)&state->ts_fw_sector[0];
1637 1633
1638 1634 /*
1639 1635 * Calculate the start and end address of the sector, based on the
1640 1636 * sector number passed in.
1641 1637 */
1642 1638 addr = sector_num << state->ts_fw_log_sector_sz;
1643 1639 end_addr = addr + (1 << state->ts_fw_log_sector_sz);
1644 1640
1645 1641 /* Set the flash bank correctly for the given address */
1646 1642 tavor_flash_bank(state, addr);
1647 1643
1648 1644 /* Erase the sector before writing */
1649 1645 tavor_flash_reset(state);
1650 1646 status = tavor_flash_erase_sector(state, sector_num);
1651 1647 if (status != 0) {
1652 1648 TAVOR_TNF_EXIT(tavor_flash_write_sector);
1653 1649 return (status);
1654 1650 }
1655 1651
1656 1652 /* Write the entire sector, one byte at a time */
1657 1653 for (i = 0; addr < end_addr; i++, addr++) {
1658 1654 status = tavor_flash_write_byte(state, addr, sector[i]);
1659 1655 if (status != 0) {
1660 1656 break;
1661 1657 }
1662 1658 }
1663 1659
1664 1660 tavor_flash_reset(state);
1665 1661 TAVOR_TNF_EXIT(tavor_flash_write_sector);
1666 1662 return (status);
1667 1663 }
1668 1664
1669 1665 /*
1670 1666 * tavor_flash_write_byte()
1671 1667 */
1672 1668 static int
1673 1669 tavor_flash_write_byte(tavor_state_t *state, uint32_t addr, uchar_t data)
1674 1670 {
1675 1671 uint32_t stat;
1676 1672 int status = 0;
1677 1673 int i;
1678 1674
1679 1675 TAVOR_TNF_ENTER(tavor_flash_write_byte);
1680 1676
1681 1677 switch (state->ts_fw_cmdset) {
1682 1678 case TAVOR_FLASH_AMD_CMDSET:
1683 1679 /* Issue Flash Byte program command */
1684 1680 tavor_flash_write(state, addr, 0xAA);
1685 1681 tavor_flash_write(state, addr, 0x55);
1686 1682 tavor_flash_write(state, addr, 0xA0);
1687 1683 tavor_flash_write(state, addr, data);
1688 1684
1689 1685 /*
1690 1686 * Wait for Write Byte to Complete:
1691 1687 * 1) Wait 1usec
1692 1688 * 2) Read status of the write operation
1693 1689 * 3) Determine if we have timed out the write operation
1694 1690 * 4) Compare correct data value to the status value that
1695 1691 * was read from the same address.
1696 1692 */
1697 1693 i = 0;
1698 1694 do {
1699 1695 drv_usecwait(1);
1700 1696 stat = tavor_flash_read(state, addr & ~3);
1701 1697
1702 1698 if (i == tavor_hw_flash_timeout_write) {
1703 1699 cmn_err(CE_WARN,
1704 1700 "tavor_flash_write_byte: ACS write "
1705 1701 "timeout: addr: 0x%x, data: 0x%x\n",
1706 1702 addr, data);
1707 1703 status = EIO;
1708 1704 break;
1709 1705 }
1710 1706
1711 1707 i++;
1712 1708 } while (data != ((stat >> ((3 - (addr & 3)) << 3)) & 0xFF));
1713 1709 break;
1714 1710
1715 1711 case TAVOR_FLASH_INTEL_CMDSET:
1716 1712 /* Issue Flash Byte program command */
1717 1713 tavor_flash_write(state, addr, TAVOR_HW_FLASH_ICS_WRITE);
1718 1714 tavor_flash_write(state, addr, data);
1719 1715
1720 1716 /* wait for completion */
1721 1717 i = 0;
1722 1718 do {
1723 1719 drv_usecwait(1);
1724 1720 stat = tavor_flash_read(state, addr & ~3);
1725 1721
1726 1722 if (i == tavor_hw_flash_timeout_write) {
1727 1723 cmn_err(CE_WARN,
1728 1724 "tavor_flash_write_byte: ICS write "
1729 1725 "timeout: addr: %x, data: %x\n",
1730 1726 addr, data);
1731 1727 status = EIO;
1732 1728 break;
1733 1729 }
1734 1730
1735 1731 i++;
1736 1732 } while ((stat & TAVOR_HW_FLASH_ICS_READY) == 0);
1737 1733
1738 1734 if (stat & TAVOR_HW_FLASH_ICS_ERROR) {
1739 1735 cmn_err(CE_WARN,
1740 1736 "tavor_flash_write_byte: ICS write cmd error: "
1741 1737 "addr: %x, data: %x\n",
1742 1738 addr, data);
1743 1739 status = EIO;
1744 1740 }
1745 1741 break;
1746 1742
1747 1743 default:
1748 1744 cmn_err(CE_WARN,
1749 1745 "tavor_flash_write_byte: unknown cmd set: 0x%x\n",
1750 1746 state->ts_fw_cmdset);
1751 1747 status = EIO;
1752 1748 break;
1753 1749 }
1754 1750
1755 1751 TAVOR_TNF_EXIT(tavor_flash_write_byte);
1756 1752 return (status);
1757 1753 }
1758 1754
1759 1755 /*
1760 1756 * tavor_flash_erase_sector()
1761 1757 */
1762 1758 static int
1763 1759 tavor_flash_erase_sector(tavor_state_t *state, uint32_t sector_num)
1764 1760 {
1765 1761 uint32_t addr;
1766 1762 uint32_t stat;
1767 1763 int status = 0;
1768 1764 int i;
1769 1765
1770 1766 TAVOR_TNF_ENTER(tavor_flash_erase_sector);
1771 1767
1772 1768 /* Get address from sector num */
1773 1769 addr = sector_num << state->ts_fw_log_sector_sz;
1774 1770
1775 1771 switch (state->ts_fw_cmdset) {
1776 1772 case TAVOR_FLASH_AMD_CMDSET:
1777 1773 /* Issue Flash Sector Erase Command */
1778 1774 tavor_flash_write(state, addr, 0xAA);
1779 1775 tavor_flash_write(state, addr, 0x55);
1780 1776 tavor_flash_write(state, addr, 0x80);
1781 1777 tavor_flash_write(state, addr, 0xAA);
1782 1778 tavor_flash_write(state, addr, 0x55);
1783 1779 tavor_flash_write(state, addr, 0x30);
1784 1780
1785 1781 /*
1786 1782 * Wait for Sector Erase to Complete
1787 1783 * 1) Wait 1usec
1788 1784 * 2) read the status at the base addr of the sector
1789 1785 * 3) Determine if we have timed out
1790 1786 * 4) Compare status of address with the value of a fully
1791 1787 * erased quadlet. If these are equal, the sector
1792 1788 * has been erased.
1793 1789 */
1794 1790 i = 0;
1795 1791 do {
1796 1792 /* wait 1usec */
1797 1793 drv_usecwait(1);
1798 1794 stat = tavor_flash_read(state, addr);
1799 1795
1800 1796 if (i == tavor_hw_flash_timeout_erase) {
1801 1797 cmn_err(CE_WARN,
1802 1798 "tavor_flash_erase_sector: "
1803 1799 "ACS erase timeout\n");
1804 1800 status = EIO;
1805 1801 break;
1806 1802 }
1807 1803
1808 1804 i++;
1809 1805 } while (stat != 0xFFFFFFFF);
1810 1806 break;
1811 1807
1812 1808 case TAVOR_FLASH_INTEL_CMDSET:
1813 1809 /* Issue Erase Command */
1814 1810 tavor_flash_write(state, addr, TAVOR_HW_FLASH_ICS_ERASE);
1815 1811 tavor_flash_write(state, addr, TAVOR_HW_FLASH_ICS_CONFIRM);
1816 1812
1817 1813 /* wait for completion */
1818 1814 i = 0;
1819 1815 do {
1820 1816 drv_usecwait(1);
1821 1817 stat = tavor_flash_read(state, addr & ~3);
1822 1818
1823 1819 if (i == tavor_hw_flash_timeout_erase) {
1824 1820 cmn_err(CE_WARN,
1825 1821 "tavor_flash_erase_sector: "
1826 1822 "ICS erase timeout\n");
1827 1823 status = EIO;
1828 1824 break;
1829 1825 }
1830 1826
1831 1827 i++;
1832 1828 } while ((stat & TAVOR_HW_FLASH_ICS_READY) == 0);
1833 1829
1834 1830 if (stat & TAVOR_HW_FLASH_ICS_ERROR) {
1835 1831 cmn_err(CE_WARN,
1836 1832 "tavor_flash_erase_sector: "
1837 1833 "ICS erase cmd error\n");
1838 1834 status = EIO;
1839 1835 }
1840 1836 break;
1841 1837
1842 1838 default:
1843 1839 cmn_err(CE_WARN,
1844 1840 "tavor_flash_erase_sector: unknown cmd set: 0x%x\n",
1845 1841 state->ts_fw_cmdset);
1846 1842 status = EIO;
1847 1843 break;
1848 1844 }
1849 1845
1850 1846 tavor_flash_reset(state);
1851 1847
1852 1848 TAVOR_TNF_EXIT(tavor_flash_erase_sector);
1853 1849 return (status);
1854 1850 }
1855 1851
1856 1852 /*
1857 1853 * tavor_flash_erase_chip()
1858 1854 */
1859 1855 static int
1860 1856 tavor_flash_erase_chip(tavor_state_t *state)
1861 1857 {
1862 1858 uint_t size;
1863 1859 uint32_t stat;
1864 1860 int status = 0;
1865 1861 int num_sect;
1866 1862 int i;
1867 1863
1868 1864 TAVOR_TNF_ENTER(tavor_flash_erase_chip);
1869 1865
1870 1866 switch (state->ts_fw_cmdset) {
1871 1867 case TAVOR_FLASH_AMD_CMDSET:
1872 1868 /* Issue Flash Chip Erase Command */
1873 1869 tavor_flash_write(state, 0, 0xAA);
1874 1870 tavor_flash_write(state, 0, 0x55);
1875 1871 tavor_flash_write(state, 0, 0x80);
1876 1872 tavor_flash_write(state, 0, 0xAA);
1877 1873 tavor_flash_write(state, 0, 0x55);
1878 1874 tavor_flash_write(state, 0, 0x10);
1879 1875
1880 1876 /*
1881 1877 * Wait for Chip Erase to Complete
1882 1878 * 1) Wait 1usec
1883 1879 * 2) read the status at the base addr of the sector
1884 1880 * 3) Determine if we have timed out
1885 1881 * 4) Compare status of address with the value of a
1886 1882 * fully erased quadlet. If these are equal, the
1887 1883 * chip has been erased.
1888 1884 */
1889 1885 i = 0;
1890 1886 do {
1891 1887 /* wait 1usec */
1892 1888 drv_usecwait(1);
1893 1889 stat = tavor_flash_read(state, 0);
1894 1890
1895 1891 if (i == tavor_hw_flash_timeout_erase) {
1896 1892 cmn_err(CE_WARN,
1897 1893 "tavor_flash_erase_chip: erase timeout\n");
1898 1894 status = EIO;
1899 1895 break;
1900 1896 }
1901 1897
1902 1898 i++;
1903 1899 } while (stat != 0xFFFFFFFF);
1904 1900 break;
1905 1901
1906 1902 case TAVOR_FLASH_INTEL_CMDSET:
1907 1903 /*
1908 1904 * The Intel chip doesn't have a chip erase command, so erase
1909 1905 * all blocks one at a time.
1910 1906 */
1911 1907 size = (0x1 << state->ts_fw_log_sector_sz);
1912 1908 num_sect = state->ts_fw_device_sz / size;
1913 1909
1914 1910 for (i = 0; i < num_sect; i++) {
1915 1911 status = tavor_flash_erase_sector(state, i);
1916 1912 if (status != 0) {
1917 1913 cmn_err(CE_WARN,
1918 1914 "tavor_flash_erase_chip: "
1919 1915 "ICS sector %d erase error\n", i);
1920 1916 status = EIO;
1921 1917 break;
1922 1918 }
1923 1919 }
1924 1920 break;
1925 1921
1926 1922 default:
1927 1923 cmn_err(CE_WARN, "tavor_flash_erase_chip: "
1928 1924 "unknown cmd set: 0x%x\n", state->ts_fw_cmdset);
1929 1925 status = EIO;
1930 1926 break;
1931 1927 }
1932 1928
1933 1929 TAVOR_TNF_EXIT(tavor_flash_erase_chip);
1934 1930 return (status);
1935 1931 }
1936 1932
1937 1933 /*
1938 1934 * tavor_flash_bank()
1939 1935 */
1940 1936 static void
1941 1937 tavor_flash_bank(tavor_state_t *state, uint32_t addr)
1942 1938 {
1943 1939 ddi_acc_handle_t hdl;
↓ open down ↓ |
930 lines elided |
↑ open up ↑ |
1944 1940 uint32_t bank;
1945 1941
1946 1942 TAVOR_TNF_ENTER(tavor_flash_bank);
1947 1943
1948 1944 /* Set handle */
1949 1945 hdl = state->ts_pci_cfghdl;
1950 1946
1951 1947 /* Determine the bank setting from the address */
1952 1948 bank = addr & TAVOR_HW_FLASH_BANK_MASK;
1953 1949
1954 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(state->ts_fw_flashbank))
1955 -
1956 1950 /*
1957 1951 * If the bank is different from the currently set bank, we need to
1958 1952 * change it. Also, if an 'addr' of 0 is given, this allows the
1959 1953 * capability to force the flash bank to 0. This is useful at init
1960 1954 * time to initially set the bank value
1961 1955 */
1962 1956 if (state->ts_fw_flashbank != bank || addr == 0) {
1963 1957 /* Set bank using the GPIO settings */
1964 1958 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DATACLEAR, 0x70);
1965 1959 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DATASET,
1966 1960 (bank >> 15) & 0x70);
1967 1961
1968 1962 /* Save the bank state */
1969 1963 state->ts_fw_flashbank = bank;
1970 1964 }
1971 1965
1972 1966 TAVOR_TNF_EXIT(tavor_flash_bank);
1973 1967 }
1974 1968
1975 1969 /*
1976 1970 * tavor_flash_read()
1977 1971 */
1978 1972 static uint32_t
1979 1973 tavor_flash_read(tavor_state_t *state, uint32_t addr)
1980 1974 {
1981 1975 ddi_acc_handle_t hdl;
1982 1976 uint32_t data;
1983 1977 int timeout;
1984 1978
1985 1979 TAVOR_TNF_ENTER(tavor_flash_read);
1986 1980
1987 1981 /* Set handle */
1988 1982 hdl = state->ts_pci_cfghdl;
1989 1983
1990 1984 /*
1991 1985 * The Read operation does the following:
1992 1986 * 1) Write the masked address to the TAVOR_FLASH_ADDR register.
1993 1987 * Only the least significant 19 bits are valid.
1994 1988 * 2) Read back the register until the command has completed.
1995 1989 * 3) Read the data retrieved from the address at the TAVOR_FLASH_DATA
1996 1990 * register.
1997 1991 */
1998 1992 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_ADDR,
1999 1993 (addr & TAVOR_HW_FLASH_ADDR_MASK) | (1 << 29));
2000 1994
2001 1995 timeout = 0;
2002 1996 do {
2003 1997 data = tavor_flash_read_cfg(hdl, TAVOR_HW_FLASH_ADDR);
2004 1998 timeout++;
2005 1999 } while ((data & TAVOR_HW_FLASH_CMD_MASK) &&
2006 2000 (timeout < tavor_hw_flash_timeout_config));
2007 2001
2008 2002 if (timeout == tavor_hw_flash_timeout_config) {
2009 2003 cmn_err(CE_WARN, "tavor_flash_read: config command timeout.\n");
2010 2004 }
2011 2005
2012 2006 data = tavor_flash_read_cfg(hdl, TAVOR_HW_FLASH_DATA);
2013 2007
2014 2008 TAVOR_TNF_EXIT(tavor_flash_read);
2015 2009 return (data);
2016 2010 }
2017 2011
2018 2012 /*
2019 2013 * tavor_flash_write()
2020 2014 */
2021 2015 static void
2022 2016 tavor_flash_write(tavor_state_t *state, uint32_t addr, uchar_t data)
2023 2017 {
2024 2018 ddi_acc_handle_t hdl;
2025 2019 int cmd;
2026 2020 int timeout;
2027 2021
2028 2022 TAVOR_TNF_ENTER(tavor_flash_write);
2029 2023
2030 2024 /* Set handle */
2031 2025 hdl = state->ts_pci_cfghdl;
2032 2026
2033 2027 /*
2034 2028 * The Write operation does the following:
2035 2029 * 1) Write the data to be written to the TAVOR_FLASH_DATA offset.
2036 2030 * 2) Write the address to write the data to to the TAVOR_FLASH_ADDR
2037 2031 * offset.
2038 2032 * 3) Wait until the write completes.
2039 2033 */
2040 2034 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_DATA, data << 24);
2041 2035 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_ADDR,
2042 2036 (addr & 0x7FFFF) | (2 << 29));
2043 2037
2044 2038 timeout = 0;
2045 2039 do {
2046 2040 cmd = tavor_flash_read_cfg(hdl, TAVOR_HW_FLASH_ADDR);
2047 2041 timeout++;
2048 2042 } while ((cmd & TAVOR_HW_FLASH_CMD_MASK) &&
2049 2043 (timeout < tavor_hw_flash_timeout_config));
2050 2044
2051 2045 if (timeout == tavor_hw_flash_timeout_config) {
2052 2046 cmn_err(CE_WARN, "tavor_flash_write: config cmd timeout.\n");
2053 2047 }
2054 2048
2055 2049 TAVOR_TNF_EXIT(tavor_flash_write);
2056 2050 }
2057 2051
2058 2052 /*
2059 2053 * tavor_flash_init()
2060 2054 */
2061 2055 static void
2062 2056 tavor_flash_init(tavor_state_t *state)
2063 2057 {
2064 2058 uint32_t word;
2065 2059 ddi_acc_handle_t hdl;
2066 2060 int sema_cnt;
2067 2061 int gpio;
2068 2062
2069 2063 TAVOR_TNF_ENTER(tavor_flash_init);
2070 2064
2071 2065 /* Set handle */
2072 2066 hdl = state->ts_pci_cfghdl;
2073 2067
2074 2068 /* Init the flash */
2075 2069
2076 2070 /*
2077 2071 * Grab the GPIO semaphore. This allows us exclusive access to the
2078 2072 * GPIO settings on the Tavor for the duration of the flash burning
2079 2073 * procedure.
2080 2074 */
2081 2075 sema_cnt = 0;
2082 2076 do {
2083 2077 word = tavor_flash_read_cfg(hdl, TAVOR_HW_FLASH_GPIO_SEMA);
2084 2078 if (word == 0) {
2085 2079 break;
2086 2080 }
2087 2081
2088 2082 sema_cnt++;
2089 2083 drv_usecwait(1);
2090 2084 } while (sema_cnt < tavor_hw_flash_timeout_gpio_sema);
2091 2085
2092 2086 /*
2093 2087 * Determine if we timed out trying to grab the GPIO semaphore
2094 2088 */
2095 2089 if (sema_cnt == tavor_hw_flash_timeout_gpio_sema) {
2096 2090 cmn_err(CE_WARN, "tavor_flash_init: GPIO SEMA timeout\n");
2097 2091 }
2098 2092
2099 2093 /* Save away original GPIO Values */
2100 2094 state->ts_fw_gpio[0] = tavor_flash_read_cfg(hdl,
2101 2095 TAVOR_HW_FLASH_GPIO_DIR);
2102 2096 state->ts_fw_gpio[1] = tavor_flash_read_cfg(hdl,
2103 2097 TAVOR_HW_FLASH_GPIO_POL);
2104 2098 state->ts_fw_gpio[2] = tavor_flash_read_cfg(hdl,
2105 2099 TAVOR_HW_FLASH_GPIO_MOD);
2106 2100 state->ts_fw_gpio[3] = tavor_flash_read_cfg(hdl,
2107 2101 TAVOR_HW_FLASH_GPIO_DAT);
2108 2102
2109 2103 /* Set New GPIO Values */
2110 2104 gpio = state->ts_fw_gpio[0] | 0x70;
2111 2105 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DIR, gpio);
2112 2106
2113 2107 gpio = state->ts_fw_gpio[1] & ~0x70;
2114 2108 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_POL, gpio);
2115 2109
2116 2110 gpio = state->ts_fw_gpio[2] & ~0x70;
2117 2111 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_MOD, gpio);
2118 2112
2119 2113 /* Set CPUMODE to enable tavor to access the flash device */
2120 2114 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_CPUMODE,
2121 2115 1 << TAVOR_HW_FLASH_CPU_SHIFT);
2122 2116
2123 2117 /* Initialize to bank 0 */
2124 2118 tavor_flash_bank(state, 0);
2125 2119
2126 2120 TAVOR_TNF_EXIT(tavor_flash_init);
2127 2121 }
2128 2122
2129 2123 /*
2130 2124 * tavor_flash_cfi_init
2131 2125 * Implements access to the CFI (Common Flash Interface) data
2132 2126 */
2133 2127 static void
2134 2128 tavor_flash_cfi_init(tavor_state_t *state, uint32_t *cfi_info, int *intel_xcmd)
2135 2129 {
2136 2130 uint32_t data;
2137 2131 uint32_t sector_sz_bytes;
2138 2132 uint32_t bit_count;
2139 2133 uint8_t cfi_ch_info[TAVOR_CFI_INFO_SIZE];
2140 2134 uint32_t cfi_dw_info[TAVOR_CFI_INFO_QSIZE];
2141 2135 int i;
2142 2136
2143 2137 TAVOR_TNF_ENTER(tavor_flash_cfi_init);
2144 2138
2145 2139 /*
2146 2140 * Determine if the user command supports the Intel Extended
2147 2141 * Command Set. The query string is contained in the fourth
2148 2142 * quad word.
2149 2143 */
2150 2144 tavor_flash_cfi_byte(cfi_ch_info, cfi_info[0x04], 0x10);
2151 2145 if (cfi_ch_info[0x10] == 'M' &&
2152 2146 cfi_ch_info[0x11] == 'X' &&
2153 2147 cfi_ch_info[0x12] == '2') {
2154 2148 *intel_xcmd = 1; /* support is there */
2155 2149 }
2156 2150
2157 2151 /* CFI QUERY */
2158 2152 tavor_flash_write(state, 0x55, TAVOR_FLASH_CFI_INIT);
2159 2153
2160 2154 /* Read in CFI data */
2161 2155 for (i = 0; i < TAVOR_CFI_INFO_SIZE; i += 4) {
2162 2156 data = tavor_flash_read(state, i);
2163 2157 cfi_dw_info[i >> 2] = data;
2164 2158 tavor_flash_cfi_byte(cfi_ch_info, data, i);
2165 2159 }
2166 2160
2167 2161 /* Determine chip set */
2168 2162 state->ts_fw_cmdset = TAVOR_FLASH_UNKNOWN_CMDSET;
2169 2163 if (cfi_ch_info[0x20] == 'Q' &&
2170 2164 cfi_ch_info[0x22] == 'R' &&
2171 2165 cfi_ch_info[0x24] == 'Y') {
2172 2166 /*
2173 2167 * Mode: x16 working in x8 mode (Intel).
2174 2168 * Pack data - skip spacing bytes.
2175 2169 */
2176 2170 for (i = 0; i < TAVOR_CFI_INFO_SIZE; i += 2) {
2177 2171 cfi_ch_info[i/2] = cfi_ch_info[i];
2178 2172 }
2179 2173 }
2180 2174 state->ts_fw_cmdset = cfi_ch_info[0x13];
2181 2175 if (state->ts_fw_cmdset != TAVOR_FLASH_INTEL_CMDSET &&
2182 2176 state->ts_fw_cmdset != TAVOR_FLASH_AMD_CMDSET) {
2183 2177 cmn_err(CE_WARN,
2184 2178 "tavor_flash_cfi_init: UNKNOWN chip cmd set\n");
2185 2179 state->ts_fw_cmdset = TAVOR_FLASH_UNKNOWN_CMDSET;
2186 2180 goto out;
2187 2181 }
2188 2182
2189 2183 /* Determine total bytes in one sector size */
2190 2184 sector_sz_bytes = ((cfi_ch_info[0x30] << 8) | cfi_ch_info[0x2F]) << 8;
2191 2185
2192 2186 /* Calculate equivalent of log2 (n) */
2193 2187 for (bit_count = 0; sector_sz_bytes > 1; bit_count++) {
2194 2188 sector_sz_bytes >>= 1;
2195 2189 }
2196 2190
2197 2191 /* Set sector size */
2198 2192 state->ts_fw_log_sector_sz = bit_count;
2199 2193
2200 2194 /* Set flash size */
2201 2195 state->ts_fw_device_sz = 0x1 << cfi_ch_info[0x27];
2202 2196
2203 2197 /* Reset to turn off CFI mode */
2204 2198 tavor_flash_reset(state);
2205 2199
2206 2200 /*
2207 2201 * Pass CFI data back to user command.
2208 2202 */
2209 2203 for (i = 0; i < TAVOR_FLASH_CFI_SIZE_QUADLET; i++) {
2210 2204 tavor_flash_cfi_dword(&cfi_info[i], cfi_ch_info, i << 2);
2211 2205 }
2212 2206
2213 2207 if (*intel_xcmd == 1) {
2214 2208 /*
2215 2209 * Inform the user cmd that this driver does support the
2216 2210 * Intel Extended Command Set.
2217 2211 */
2218 2212 cfi_ch_info[0x10] = 'M';
2219 2213 cfi_ch_info[0x11] = 'X';
2220 2214 cfi_ch_info[0x12] = '2';
2221 2215 } else {
2222 2216 cfi_ch_info[0x10] = 'Q';
2223 2217 cfi_ch_info[0x11] = 'R';
2224 2218 cfi_ch_info[0x12] = 'Y';
2225 2219 }
2226 2220 cfi_ch_info[0x13] = state->ts_fw_cmdset;
2227 2221 tavor_flash_cfi_dword(&cfi_info[0x4], cfi_ch_info, 0x10);
2228 2222 out:
2229 2223 TAVOR_TNF_EXIT(tavor_flash_cfi_init);
2230 2224 }
2231 2225
2232 2226 /*
2233 2227 * tavor_flash_fini()
2234 2228 */
2235 2229 static void
2236 2230 tavor_flash_fini(tavor_state_t *state)
2237 2231 {
2238 2232 ddi_acc_handle_t hdl;
2239 2233
2240 2234 TAVOR_TNF_ENTER(tavor_flash_fini);
2241 2235
2242 2236 /* Set handle */
2243 2237 hdl = state->ts_pci_cfghdl;
2244 2238
2245 2239 /* Restore original GPIO Values */
2246 2240 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DIR,
2247 2241 state->ts_fw_gpio[0]);
2248 2242 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_POL,
2249 2243 state->ts_fw_gpio[1]);
2250 2244 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_MOD,
2251 2245 state->ts_fw_gpio[2]);
2252 2246 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DAT,
2253 2247 state->ts_fw_gpio[3]);
2254 2248
2255 2249 /* Give up semaphore */
2256 2250 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_SEMA, 0);
2257 2251
2258 2252 TAVOR_TNF_EXIT(tavor_flash_fini);
2259 2253 }
2260 2254
2261 2255 /*
2262 2256 * tavor_flash_read_cfg
2263 2257 */
2264 2258 static uint32_t
2265 2259 tavor_flash_read_cfg(ddi_acc_handle_t pci_config_hdl, uint32_t addr)
2266 2260 {
2267 2261 uint32_t read;
2268 2262
2269 2263 TAVOR_TNF_ENTER(tavor_flash_read_cfg);
2270 2264
2271 2265 /*
2272 2266 * Perform flash read operation:
2273 2267 * 1) Place addr to read from on the TAVOR_HW_FLASH_CFG_ADDR register
2274 2268 * 2) Read data at that addr from the TAVOR_HW_FLASH_CFG_DATA register
2275 2269 */
2276 2270 pci_config_put32(pci_config_hdl, TAVOR_HW_FLASH_CFG_ADDR, addr);
2277 2271 read = pci_config_get32(pci_config_hdl, TAVOR_HW_FLASH_CFG_DATA);
2278 2272
2279 2273 TAVOR_TNF_EXIT(tavor_flash_read_cfg);
2280 2274
2281 2275 return (read);
2282 2276 }
2283 2277
2284 2278 /*
2285 2279 * tavor_flash_write_cfg
2286 2280 */
2287 2281 static void
2288 2282 tavor_flash_write_cfg(ddi_acc_handle_t pci_config_hdl, uint32_t addr,
2289 2283 uint32_t data)
2290 2284 {
2291 2285 TAVOR_TNF_ENTER(tavor_flash_write_cfg);
2292 2286
2293 2287 /*
2294 2288 * Perform flash write operation:
2295 2289 * 1) Place addr to write to on the TAVOR_HW_FLASH_CFG_ADDR register
2296 2290 * 2) Place data to write on to the TAVOR_HW_FLASH_CFG_DATA register
2297 2291 */
2298 2292 pci_config_put32(pci_config_hdl, TAVOR_HW_FLASH_CFG_ADDR, addr);
2299 2293 pci_config_put32(pci_config_hdl, TAVOR_HW_FLASH_CFG_DATA, data);
2300 2294
2301 2295 TAVOR_TNF_EXIT(tavor_flash_write_cfg);
2302 2296 }
2303 2297
2304 2298 /*
2305 2299 * Support routines to convert Common Flash Interface (CFI) data
2306 2300 * from a 32 bit word to a char array, and from a char array to
2307 2301 * a 32 bit word.
2308 2302 */
2309 2303 static void
2310 2304 tavor_flash_cfi_byte(uint8_t *ch, uint32_t dword, int i)
2311 2305 {
2312 2306 ch[i] = (uint8_t)((dword & 0xFF000000) >> 24);
2313 2307 ch[i+1] = (uint8_t)((dword & 0x00FF0000) >> 16);
2314 2308 ch[i+2] = (uint8_t)((dword & 0x0000FF00) >> 8);
2315 2309 ch[i+3] = (uint8_t)((dword & 0x000000FF));
2316 2310 }
2317 2311
2318 2312 static void
2319 2313 tavor_flash_cfi_dword(uint32_t *dword, uint8_t *ch, int i)
2320 2314 {
2321 2315 *dword = (uint32_t)
2322 2316 ((uint32_t)ch[i] << 24 |
2323 2317 (uint32_t)ch[i+1] << 16 |
2324 2318 (uint32_t)ch[i+2] << 8 |
2325 2319 (uint32_t)ch[i+3]);
↓ open down ↓ |
360 lines elided |
↑ open up ↑ |
2326 2320 }
2327 2321
2328 2322 /*
2329 2323 * tavor_loopback_free_qps
2330 2324 */
2331 2325 static void
2332 2326 tavor_loopback_free_qps(tavor_loopback_state_t *lstate)
2333 2327 {
2334 2328 int i;
2335 2329
2336 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
2337 -
2338 2330 if (lstate->tls_tx.tlc_qp_hdl != NULL) {
2339 2331 (void) tavor_qp_free(lstate->tls_state,
2340 2332 &lstate->tls_tx.tlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL,
2341 2333 TAVOR_NOSLEEP);
2342 2334 }
2343 2335 if (lstate->tls_rx.tlc_qp_hdl != NULL) {
2344 2336 (void) tavor_qp_free(lstate->tls_state,
2345 2337 &lstate->tls_rx.tlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL,
2346 2338 TAVOR_NOSLEEP);
2347 2339 }
2348 2340 lstate->tls_tx.tlc_qp_hdl = NULL;
2349 2341 lstate->tls_rx.tlc_qp_hdl = NULL;
2350 2342 for (i = 0; i < 2; i++) {
2351 2343 if (lstate->tls_tx.tlc_cqhdl[i] != NULL) {
2352 2344 (void) tavor_cq_free(lstate->tls_state,
2353 2345 &lstate->tls_tx.tlc_cqhdl[i], TAVOR_NOSLEEP);
2354 2346 }
2355 2347 if (lstate->tls_rx.tlc_cqhdl[i] != NULL) {
2356 2348 (void) tavor_cq_free(lstate->tls_state,
2357 2349 &lstate->tls_rx.tlc_cqhdl[i], TAVOR_NOSLEEP);
2358 2350 }
2359 2351 lstate->tls_tx.tlc_cqhdl[i] = NULL;
2360 2352 lstate->tls_rx.tlc_cqhdl[i] = NULL;
2361 2353 }
2362 2354 }
2363 2355
2364 2356 /*
2365 2357 * tavor_loopback_free_state
2366 2358 */
2367 2359 static void
2368 2360 tavor_loopback_free_state(tavor_loopback_state_t *lstate)
2369 2361 {
2370 2362 tavor_loopback_free_qps(lstate);
2371 2363 if (lstate->tls_tx.tlc_mrhdl != NULL) {
2372 2364 (void) tavor_mr_deregister(lstate->tls_state,
2373 2365 &lstate->tls_tx.tlc_mrhdl, TAVOR_MR_DEREG_ALL,
2374 2366 TAVOR_NOSLEEP);
2375 2367 }
2376 2368 if (lstate->tls_rx.tlc_mrhdl != NULL) {
2377 2369 (void) tavor_mr_deregister(lstate->tls_state,
2378 2370 &lstate->tls_rx.tlc_mrhdl, TAVOR_MR_DEREG_ALL,
2379 2371 TAVOR_NOSLEEP);
2380 2372 }
2381 2373 if (lstate->tls_pd_hdl != NULL) {
2382 2374 (void) tavor_pd_free(lstate->tls_state, &lstate->tls_pd_hdl);
2383 2375 }
2384 2376 if (lstate->tls_tx.tlc_buf != NULL) {
2385 2377 kmem_free(lstate->tls_tx.tlc_buf, lstate->tls_tx.tlc_buf_sz);
2386 2378 }
2387 2379 if (lstate->tls_rx.tlc_buf != NULL) {
2388 2380 kmem_free(lstate->tls_rx.tlc_buf, lstate->tls_rx.tlc_buf_sz);
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
2389 2381 }
2390 2382 bzero(lstate, sizeof (tavor_loopback_state_t));
2391 2383 }
2392 2384
2393 2385 /*
2394 2386 * tavor_loopback_init
2395 2387 */
2396 2388 static int
2397 2389 tavor_loopback_init(tavor_state_t *state, tavor_loopback_state_t *lstate)
2398 2390 {
2399 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
2400 -
2401 2391 lstate->tls_hca_hdl = (ibc_hca_hdl_t)state;
2402 2392 lstate->tls_status = tavor_pd_alloc(lstate->tls_state,
2403 2393 &lstate->tls_pd_hdl, TAVOR_NOSLEEP);
2404 2394 if (lstate->tls_status != IBT_SUCCESS) {
2405 2395 lstate->tls_err = TAVOR_LOOPBACK_PROT_DOMAIN_ALLOC_FAIL;
2406 2396 TNF_PROBE_0(tavor_ioctl_loopback_alloc_pd_fail,
2407 2397 TAVOR_TNF_ERROR, "");
2408 2398 return (EFAULT);
2409 2399 }
2410 2400
2411 2401 return (0);
2412 2402 }
2413 2403
2414 2404 /*
2415 2405 * tavor_loopback_init_qp_info
2416 2406 */
2417 2407 static void
2418 2408 tavor_loopback_init_qp_info(tavor_loopback_state_t *lstate,
2419 2409 tavor_loopback_comm_t *comm)
2420 2410 {
2421 2411 bzero(&comm->tlc_cq_attr, sizeof (ibt_cq_attr_t));
2422 2412 bzero(&comm->tlc_qp_attr, sizeof (ibt_qp_alloc_attr_t));
2423 2413 bzero(&comm->tlc_qp_info, sizeof (ibt_qp_info_t));
2424 2414
2425 2415 comm->tlc_wrid = 1;
2426 2416 comm->tlc_cq_attr.cq_size = 128;
2427 2417 comm->tlc_qp_attr.qp_sizes.cs_sq_sgl = 3;
2428 2418 comm->tlc_qp_attr.qp_sizes.cs_rq_sgl = 3;
2429 2419 comm->tlc_qp_attr.qp_sizes.cs_sq = 16;
2430 2420 comm->tlc_qp_attr.qp_sizes.cs_rq = 16;
2431 2421 comm->tlc_qp_attr.qp_flags = IBT_WR_SIGNALED;
2432 2422
2433 2423 comm->tlc_qp_info.qp_state = IBT_STATE_RESET;
2434 2424 comm->tlc_qp_info.qp_trans = IBT_RC_SRV;
2435 2425 comm->tlc_qp_info.qp_flags = IBT_CEP_RDMA_RD | IBT_CEP_RDMA_WR;
2436 2426 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
2437 2427 lstate->tls_port;
2438 2428 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_pkey_ix =
2439 2429 lstate->tls_pkey_ix;
2440 2430 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_timeout =
2441 2431 lstate->tls_timeout;
2442 2432 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_srvl = 0;
2443 2433 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_srate =
2444 2434 IBT_SRATE_4X;
2445 2435 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_send_grh = 0;
2446 2436 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid =
2447 2437 lstate->tls_lid;
2448 2438 comm->tlc_qp_info.qp_transport.rc.rc_retry_cnt = lstate->tls_retry;
2449 2439 comm->tlc_qp_info.qp_transport.rc.rc_sq_psn = 0;
2450 2440 comm->tlc_qp_info.qp_transport.rc.rc_rq_psn = 0;
2451 2441 comm->tlc_qp_info.qp_transport.rc.rc_rdma_ra_in = 4;
2452 2442 comm->tlc_qp_info.qp_transport.rc.rc_rdma_ra_out = 4;
2453 2443 comm->tlc_qp_info.qp_transport.rc.rc_dst_qpn = 0;
2454 2444 comm->tlc_qp_info.qp_transport.rc.rc_min_rnr_nak = IBT_RNR_NAK_655ms;
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
2455 2445 comm->tlc_qp_info.qp_transport.rc.rc_path_mtu = IB_MTU_1K;
2456 2446 }
2457 2447
2458 2448 /*
2459 2449 * tavor_loopback_alloc_mem
2460 2450 */
2461 2451 static int
2462 2452 tavor_loopback_alloc_mem(tavor_loopback_state_t *lstate,
2463 2453 tavor_loopback_comm_t *comm, int sz)
2464 2454 {
2465 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
2466 -
2467 2455 /* Allocate buffer of specified size */
2468 2456 comm->tlc_buf_sz = sz;
2469 2457 comm->tlc_buf = kmem_zalloc(sz, KM_NOSLEEP);
2470 2458 if (comm->tlc_buf == NULL) {
2471 2459 return (EFAULT);
2472 2460 }
2473 2461
2474 2462 /* Register the buffer as a memory region */
2475 2463 comm->tlc_memattr.mr_vaddr = (uint64_t)(uintptr_t)comm->tlc_buf;
2476 2464 comm->tlc_memattr.mr_len = (ib_msglen_t)sz;
2477 2465 comm->tlc_memattr.mr_as = NULL;
2478 2466 comm->tlc_memattr.mr_flags = IBT_MR_NOSLEEP |
2479 2467 IBT_MR_ENABLE_REMOTE_WRITE | IBT_MR_ENABLE_LOCAL_WRITE;
2480 2468
2481 2469 comm->tlc_status = tavor_mr_register(lstate->tls_state,
2482 2470 lstate->tls_pd_hdl, &comm->tlc_memattr, &comm->tlc_mrhdl, NULL);
2483 2471
2484 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm->tlc_mrhdl))
2485 -
2486 2472 comm->tlc_mrdesc.md_vaddr = comm->tlc_mrhdl->mr_bindinfo.bi_addr;
2487 2473 comm->tlc_mrdesc.md_lkey = comm->tlc_mrhdl->mr_lkey;
2488 2474 comm->tlc_mrdesc.md_rkey = comm->tlc_mrhdl->mr_rkey;
2489 2475 if (comm->tlc_status != IBT_SUCCESS) {
2490 2476 return (EFAULT);
2491 2477 }
2492 2478 return (0);
2493 2479 }
2494 2480
2495 2481 /*
2496 2482 * tavor_loopback_alloc_qps
2497 2483 */
2498 2484 static int
2499 2485 tavor_loopback_alloc_qps(tavor_loopback_state_t *lstate,
2500 2486 tavor_loopback_comm_t *comm)
2501 2487 {
2502 2488 uint32_t i, real_size;
2503 2489 tavor_qp_info_t qpinfo;
2504 2490
2505 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
2506 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
2507 -
2508 2491 /* Allocate send and recv CQs */
2509 2492 for (i = 0; i < 2; i++) {
2510 2493 bzero(&comm->tlc_cq_attr, sizeof (ibt_cq_attr_t));
2511 2494 comm->tlc_cq_attr.cq_size = 128;
2512 2495 comm->tlc_status = tavor_cq_alloc(lstate->tls_state,
2513 2496 (ibt_cq_hdl_t)NULL, &comm->tlc_cq_attr, &real_size,
2514 2497 &comm->tlc_cqhdl[i], TAVOR_NOSLEEP);
2515 2498 if (comm->tlc_status != IBT_SUCCESS) {
2516 2499 lstate->tls_err += i;
2517 2500 return (EFAULT);
2518 2501 }
2519 2502 }
2520 2503
2521 2504 /* Allocate the QP */
2522 2505 tavor_loopback_init_qp_info(lstate, comm);
2523 2506 comm->tlc_qp_attr.qp_pd_hdl = (ibt_pd_hdl_t)lstate->tls_pd_hdl;
2524 2507 comm->tlc_qp_attr.qp_scq_hdl = (ibt_cq_hdl_t)comm->tlc_cqhdl[0];
2525 2508 comm->tlc_qp_attr.qp_rcq_hdl = (ibt_cq_hdl_t)comm->tlc_cqhdl[1];
2526 2509 comm->tlc_qp_attr.qp_ibc_scq_hdl = (ibt_opaque1_t)comm->tlc_cqhdl[0];
2527 2510 comm->tlc_qp_attr.qp_ibc_rcq_hdl = (ibt_opaque1_t)comm->tlc_cqhdl[1];
2528 2511 qpinfo.qpi_attrp = &comm->tlc_qp_attr;
2529 2512 qpinfo.qpi_type = IBT_RC_RQP;
2530 2513 qpinfo.qpi_ibt_qphdl = NULL;
2531 2514 qpinfo.qpi_queueszp = &comm->tlc_chan_sizes;
2532 2515 qpinfo.qpi_qpn = &comm->tlc_qp_num;
2533 2516 comm->tlc_status = tavor_qp_alloc(lstate->tls_state, &qpinfo,
2534 2517 TAVOR_NOSLEEP, NULL);
2535 2518 if (comm->tlc_status == DDI_SUCCESS) {
2536 2519 comm->tlc_qp_hdl = qpinfo.qpi_qphdl;
2537 2520 }
2538 2521
2539 2522 if (comm->tlc_status != IBT_SUCCESS) {
2540 2523 lstate->tls_err += 2;
2541 2524 return (EFAULT);
2542 2525 }
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
2543 2526 return (0);
2544 2527 }
2545 2528
2546 2529 /*
2547 2530 * tavor_loopback_modify_qp
2548 2531 */
2549 2532 static int
2550 2533 tavor_loopback_modify_qp(tavor_loopback_state_t *lstate,
2551 2534 tavor_loopback_comm_t *comm, uint_t qp_num)
2552 2535 {
2553 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
2554 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
2555 -
2556 2536 /* Modify QP to INIT */
2557 2537 tavor_loopback_init_qp_info(lstate, comm);
2558 2538 comm->tlc_qp_info.qp_state = IBT_STATE_INIT;
2559 2539 comm->tlc_status = tavor_qp_modify(lstate->tls_state, comm->tlc_qp_hdl,
2560 2540 IBT_CEP_SET_STATE, &comm->tlc_qp_info, &comm->tlc_queue_sizes);
2561 2541 if (comm->tlc_status != IBT_SUCCESS) {
2562 2542 return (EFAULT);
2563 2543 }
2564 2544
2565 2545 /*
2566 2546 * Modify QP to RTR (set destination LID and QP number to local
2567 2547 * LID and QP number)
2568 2548 */
2569 2549 comm->tlc_qp_info.qp_state = IBT_STATE_RTR;
2570 2550 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid
2571 2551 = lstate->tls_lid;
2572 2552 comm->tlc_qp_info.qp_transport.rc.rc_dst_qpn = qp_num;
2573 2553 comm->tlc_status = tavor_qp_modify(lstate->tls_state, comm->tlc_qp_hdl,
2574 2554 IBT_CEP_SET_STATE, &comm->tlc_qp_info, &comm->tlc_queue_sizes);
2575 2555 if (comm->tlc_status != IBT_SUCCESS) {
2576 2556 lstate->tls_err += 1;
2577 2557 return (EFAULT);
2578 2558 }
2579 2559
2580 2560 /* Modify QP to RTS */
2581 2561 comm->tlc_qp_info.qp_current_state = IBT_STATE_RTR;
2582 2562 comm->tlc_qp_info.qp_state = IBT_STATE_RTS;
2583 2563 comm->tlc_status = tavor_qp_modify(lstate->tls_state, comm->tlc_qp_hdl,
2584 2564 IBT_CEP_SET_STATE, &comm->tlc_qp_info, &comm->tlc_queue_sizes);
2585 2565 if (comm->tlc_status != IBT_SUCCESS) {
2586 2566 lstate->tls_err += 2;
2587 2567 return (EFAULT);
2588 2568 }
2589 2569 return (0);
2590 2570 }
2591 2571
2592 2572 /*
2593 2573 * tavor_loopback_copyout
2594 2574 */
2595 2575 static int
2596 2576 tavor_loopback_copyout(tavor_loopback_ioctl_t *lb, intptr_t arg, int mode)
2597 2577 {
2598 2578 #ifdef _MULTI_DATAMODEL
2599 2579 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2600 2580 tavor_loopback_ioctl32_t lb32;
2601 2581
2602 2582 lb32.tlb_revision = lb->tlb_revision;
2603 2583 lb32.tlb_send_buf =
2604 2584 (caddr32_t)(uintptr_t)lb->tlb_send_buf;
2605 2585 lb32.tlb_fail_buf =
2606 2586 (caddr32_t)(uintptr_t)lb->tlb_fail_buf;
2607 2587 lb32.tlb_buf_sz = lb->tlb_buf_sz;
2608 2588 lb32.tlb_num_iter = lb->tlb_num_iter;
2609 2589 lb32.tlb_pass_done = lb->tlb_pass_done;
2610 2590 lb32.tlb_timeout = lb->tlb_timeout;
2611 2591 lb32.tlb_error_type = lb->tlb_error_type;
2612 2592 lb32.tlb_port_num = lb->tlb_port_num;
2613 2593 lb32.tlb_num_retry = lb->tlb_num_retry;
2614 2594
2615 2595 if (ddi_copyout(&lb32, (void *)arg,
2616 2596 sizeof (tavor_loopback_ioctl32_t), mode) != 0) {
2617 2597 TNF_PROBE_0(tavor_ioctl_loopback_copyout_fail,
2618 2598 TAVOR_TNF_ERROR, "");
2619 2599 return (EFAULT);
2620 2600 }
2621 2601 } else
2622 2602 #endif /* _MULTI_DATAMODEL */
2623 2603 if (ddi_copyout(lb, (void *)arg, sizeof (tavor_loopback_ioctl_t),
2624 2604 mode) != 0) {
2625 2605 TNF_PROBE_0(tavor_ioctl_loopback_copyout_fail,
2626 2606 TAVOR_TNF_ERROR, "");
2627 2607 return (EFAULT);
2628 2608 }
2629 2609 return (0);
2630 2610 }
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
2631 2611
2632 2612 /*
2633 2613 * tavor_loopback_post_send
2634 2614 */
2635 2615 static int
2636 2616 tavor_loopback_post_send(tavor_loopback_state_t *lstate,
2637 2617 tavor_loopback_comm_t *tx, tavor_loopback_comm_t *rx)
2638 2618 {
2639 2619 int ret;
2640 2620
2641 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tx))
2642 -
2643 2621 bzero(&tx->tlc_sgl, sizeof (ibt_wr_ds_t));
2644 2622 bzero(&tx->tlc_wr, sizeof (ibt_send_wr_t));
2645 2623
2646 2624 /* Initialize local address for TX buffer */
2647 2625 tx->tlc_sgl.ds_va = tx->tlc_mrdesc.md_vaddr;
2648 2626 tx->tlc_sgl.ds_key = tx->tlc_mrdesc.md_lkey;
2649 2627 tx->tlc_sgl.ds_len = tx->tlc_buf_sz;
2650 2628
2651 2629 /* Initialize the remaining details of the work request */
2652 2630 tx->tlc_wr.wr_id = tx->tlc_wrid++;
2653 2631 tx->tlc_wr.wr_flags = IBT_WR_SEND_SIGNAL;
2654 2632 tx->tlc_wr.wr_nds = 1;
2655 2633 tx->tlc_wr.wr_sgl = &tx->tlc_sgl;
2656 2634 tx->tlc_wr.wr_opcode = IBT_WRC_RDMAW;
2657 2635 tx->tlc_wr.wr_trans = IBT_RC_SRV;
2658 2636
2659 2637 /* Initialize the remote address for RX buffer */
2660 2638 tx->tlc_wr.wr.rc.rcwr.rdma.rdma_raddr = rx->tlc_mrdesc.md_vaddr;
2661 2639 tx->tlc_wr.wr.rc.rcwr.rdma.rdma_rkey = rx->tlc_mrdesc.md_rkey;
2662 2640 tx->tlc_complete = 0;
2663 2641 ret = tavor_post_send(lstate->tls_state, tx->tlc_qp_hdl, &tx->tlc_wr,
2664 2642 1, NULL);
2665 2643 if (ret != IBT_SUCCESS) {
2666 2644 return (EFAULT);
2667 2645 }
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
2668 2646 return (0);
2669 2647 }
2670 2648
2671 2649 /*
2672 2650 * tavor_loopback_poll_cq
2673 2651 */
2674 2652 static int
2675 2653 tavor_loopback_poll_cq(tavor_loopback_state_t *lstate,
2676 2654 tavor_loopback_comm_t *comm)
2677 2655 {
2678 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
2679 -
2680 2656 comm->tlc_wc.wc_status = 0;
2681 2657 comm->tlc_num_polled = 0;
2682 2658 comm->tlc_status = tavor_cq_poll(lstate->tls_state,
2683 2659 comm->tlc_cqhdl[0], &comm->tlc_wc, 1, &comm->tlc_num_polled);
2684 2660 if ((comm->tlc_status == IBT_SUCCESS) &&
2685 2661 (comm->tlc_wc.wc_status != IBT_WC_SUCCESS)) {
2686 2662 comm->tlc_status = ibc_get_ci_failure(0);
2687 2663 }
2688 2664 return (comm->tlc_status);
2689 2665 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX