Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/fibre-channel/fca/oce/oce_mbx.c
+++ new/usr/src/uts/common/io/fibre-channel/fca/oce/oce_mbx.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 /* Copyright © 2003-2011 Emulex. All rights reserved. */
23 23
24 24
25 25 /*
26 26 * Source file containing the implementation of MBOX
27 27 * and related helper functions
28 28 */
29 29
30 30 #include <oce_impl.h>
31 31
32 32 static ddi_dma_attr_t oce_sgl_dma_attr = {
33 33 DMA_ATTR_V0, /* version number */
34 34 0x0000000000000000ull, /* low address */
35 35 0xFFFFFFFFFFFFFFFFull, /* high address */
36 36 0x0000000000010000ull, /* dma counter max */
37 37 0x1000, /* alignment 4K for mbx bufs */
38 38 0x1, /* burst sizes */
39 39 0x00000004, /* minimum transfer size */
40 40 0x00000000FFFFFFFFull, /* maximum transfer size */
41 41 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */
42 42 MAX_MBX_SGE, /* scatter/gather list length */
43 43 0x00000001, /* granularity */
44 44 0 /* DMA flags */
45 45 };
46 46
47 47 static ddi_device_acc_attr_t oce_sgl_buf_accattr = {
48 48 DDI_DEVICE_ATTR_V0,
49 49 DDI_NEVERSWAP_ACC,
50 50 DDI_STRICTORDER_ACC,
51 51 };
52 52
53 53 /*
54 54 * common inline function to fill an ioctl request header
55 55 *
56 56 * hdr - pointer to a buffer where the header will be initialized
57 57 * dom - domain
58 58 * port - port number
59 59 * opcode - command code for this MBX
60 60 * timeout - timeout in seconds
61 61 * pyld_len - length of the command buffer described by this header
62 62 *
63 63 * return none
64 64 */
65 65 void
66 66 mbx_common_req_hdr_init(struct mbx_hdr *hdr,
67 67 uint8_t dom, uint8_t port,
68 68 uint8_t subsys, uint8_t opcode,
69 69 uint32_t timeout, uint32_t pyld_len)
70 70 {
71 71 ASSERT(hdr != NULL);
72 72
73 73 hdr->u0.req.opcode = opcode;
74 74 hdr->u0.req.subsystem = subsys;
75 75 hdr->u0.req.port_number = port;
76 76 hdr->u0.req.domain = dom;
77 77
78 78 hdr->u0.req.timeout = timeout;
79 79 hdr->u0.req.request_length = pyld_len - sizeof (struct mbx_hdr);
80 80 hdr->u0.req.rsvd0 = 0;
81 81 } /* mbx_common_req_hdr_init */
82 82
83 83 /*
84 84 * function to initialize the hw with host endian information
85 85 *
86 86 * dev - software handle to the device
87 87 *
88 88 * return 0 on success, ETIMEDOUT on failure
89 89 */
90 90 int
91 91 oce_mbox_init(struct oce_dev *dev)
92 92 {
93 93 struct oce_bmbx *mbx;
94 94 uint8_t *ptr;
95 95 int ret = 0;
96 96
97 97 ASSERT(dev != NULL);
98 98
99 99 mbx = (struct oce_bmbx *)DBUF_VA(dev->bmbx);
100 100 ptr = (uint8_t *)&mbx->mbx;
101 101
102 102 /* Endian Signature */
103 103 *ptr++ = 0xff;
104 104 *ptr++ = 0x12;
105 105 *ptr++ = 0x34;
106 106 *ptr++ = 0xff;
107 107 *ptr++ = 0xff;
108 108 *ptr++ = 0x56;
109 109 *ptr++ = 0x78;
110 110 *ptr = 0xff;
111 111
112 112 ret = oce_mbox_dispatch(dev, 0);
113 113
114 114 if (ret != 0)
115 115 oce_log(dev, CE_NOTE, MOD_CONFIG,
116 116 "Failed to set endian %d", ret);
117 117
118 118 return (ret);
119 119 } /* oce_mbox_init */
120 120
121 121 /*
122 122 * function to wait till we get a mbox ready after writing to the
123 123 * mbox doorbell
124 124 *
125 125 * dev - software handle to the device
↓ open down ↓ |
125 lines elided |
↑ open up ↑ |
126 126 *
127 127 * return 0=ready, ETIMEDOUT=>not ready but timed out
128 128 */
129 129 int
130 130 oce_mbox_wait(struct oce_dev *dev, uint32_t tmo_sec)
131 131 {
132 132 clock_t tmo;
133 133 clock_t now, tstamp;
134 134 pd_mpu_mbox_db_t mbox_db;
135 135
136 - tmo = (tmo_sec > 0) ? drv_usectohz(tmo_sec * 1000000) :
136 + tmo = (tmo_sec > 0) ? drv_sectohz(tmo_sec) :
137 137 drv_usectohz(DEFAULT_MQ_MBOX_TIMEOUT);
138 138
139 139 /* Add the default timeout to wait for a mailbox to complete */
140 140 tmo += drv_usectohz(MBX_READY_TIMEOUT);
141 141
142 142 tstamp = ddi_get_lbolt();
143 143 for (;;) {
144 144 now = ddi_get_lbolt();
145 145 if ((now - tstamp) >= tmo) {
146 146 tmo = 0;
147 147 break;
148 148 }
149 149
150 150 mbox_db.dw0 = OCE_DB_READ32(dev, PD_MPU_MBOX_DB);
151 151 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
152 152 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
153 153 oce_fm_ereport(dev, DDI_FM_DEVICE_INVAL_STATE);
154 154 }
155 155
156 156 if (mbox_db.bits.ready) {
157 157 return (0);
158 158 }
159 159 drv_usecwait(5);
160 160 }
161 161
162 162 return (ETIMEDOUT);
163 163 } /* oce_mbox_wait */
164 164
165 165 /*
166 166 * function to dispatch a mailbox command present in the mq mbox
167 167 *
168 168 * dev - software handle to the device
169 169 *
170 170 * return 0 on success, ETIMEDOUT on failure
171 171 */
172 172 int
173 173 oce_mbox_dispatch(struct oce_dev *dev, uint32_t tmo_sec)
174 174 {
175 175 pd_mpu_mbox_db_t mbox_db;
176 176 uint32_t pa;
177 177 int ret;
178 178
179 179 /* sync the bmbx */
180 180 (void) DBUF_SYNC(dev->bmbx, DDI_DMA_SYNC_FORDEV);
181 181
182 182 /* write 30 bits of address hi dword */
183 183 pa = (uint32_t)(DBUF_PA(dev->bmbx) >> 34);
184 184 bzero(&mbox_db, sizeof (pd_mpu_mbox_db_t));
185 185 mbox_db.bits.ready = 0;
186 186 mbox_db.bits.hi = 1;
187 187 mbox_db.bits.address = pa;
188 188
189 189 /* wait for mbox ready */
190 190 ret = oce_mbox_wait(dev, tmo_sec);
191 191 if (ret != 0) {
192 192 return (ret);
193 193 }
194 194
195 195 /* ring the doorbell */
196 196 OCE_DB_WRITE32(dev, PD_MPU_MBOX_DB, mbox_db.dw0);
197 197
198 198 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
199 199 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
200 200 }
201 201
202 202 /* wait for mbox ready */
203 203 ret = oce_mbox_wait(dev, tmo_sec);
204 204 if (ret != 0) {
205 205 oce_log(dev, CE_NOTE, MOD_CONFIG,
206 206 "BMBX TIMED OUT PROGRAMMING HI ADDR: %d", ret);
207 207 /* if mbx times out, hw is in invalid state */
208 208 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
209 209 oce_fm_ereport(dev, DDI_FM_DEVICE_INVAL_STATE);
210 210 return (ret);
211 211 }
212 212
213 213 /* now write 30 bits of address lo dword */
214 214 pa = (uint32_t)(DBUF_PA(dev->bmbx) >> 4) & 0x3fffffff;
215 215 mbox_db.bits.ready = 0;
216 216 mbox_db.bits.hi = 0;
217 217 mbox_db.bits.address = pa;
218 218
219 219 /* ring the doorbell */
220 220 OCE_DB_WRITE32(dev, PD_MPU_MBOX_DB, mbox_db.dw0);
221 221 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
222 222 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
223 223 }
224 224
225 225 /* wait for mbox ready */
226 226 ret = oce_mbox_wait(dev, tmo_sec);
227 227 /* sync */
228 228 (void) ddi_dma_sync(DBUF_DHDL(dev->bmbx), 0, 0,
229 229 DDI_DMA_SYNC_FORKERNEL);
230 230 if (oce_fm_check_dma_handle(dev, DBUF_DHDL(dev->bmbx)) != DDI_FM_OK) {
231 231 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
232 232 return (EIO);
233 233 }
234 234 return (ret);
235 235 } /* oce_mbox_dispatch */
236 236
237 237 /*
238 238 * function to post a MBX to the mbox
239 239 *
240 240 * dev - software handle to the device
241 241 * mbx - pointer to the MBX to send
242 242 * mbxctx - pointer to the mbx context structure
243 243 *
244 244 * return 0 on success, ETIMEDOUT on failure
245 245 */
246 246 int
247 247 oce_mbox_post(struct oce_dev *dev, struct oce_mbx *mbx,
248 248 struct oce_mbx_ctx *mbxctx)
249 249 {
250 250 struct oce_mbx *mb_mbx = NULL;
251 251 struct oce_mq_cqe *mb_cqe = NULL;
252 252 struct oce_bmbx *mb = NULL;
253 253 int ret = 0;
254 254 uint32_t tmo = 0;
255 255
256 256 mutex_enter(&dev->bmbx_lock);
257 257
258 258 mb = (struct oce_bmbx *)DBUF_VA(dev->bmbx);
259 259 mb_mbx = &mb->mbx;
260 260
261 261 /* get the tmo */
262 262 tmo = mbx->tag[0];
263 263 mbx->tag[0] = 0;
264 264
265 265 /* copy mbx into mbox */
266 266 bcopy(mbx, mb_mbx, sizeof (struct oce_mbx));
267 267
268 268 /* now dispatch */
269 269 ret = oce_mbox_dispatch(dev, tmo);
270 270 if (ret != 0) {
271 271 mutex_exit(&dev->bmbx_lock);
272 272 return (ret);
273 273 }
274 274
275 275 /* sync */
276 276
277 277 (void) ddi_dma_sync(DBUF_DHDL(dev->bmbx), 0, 0,
278 278 DDI_DMA_SYNC_FORKERNEL);
279 279 ret = oce_fm_check_dma_handle(dev, DBUF_DHDL(dev->bmbx));
280 280 if (ret != DDI_FM_OK) {
281 281 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
282 282 mutex_exit(&dev->bmbx_lock);
283 283 return (EIO);
284 284 }
285 285
286 286 /*
287 287 * the command completed successfully. Now get the
288 288 * completion queue entry
289 289 */
290 290 mb_cqe = &mb->cqe;
291 291 DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof (struct oce_mq_cqe));
292 292
293 293 /* copy mbox mbx back */
294 294 bcopy(mb_mbx, mbx, sizeof (struct oce_mbx));
295 295
296 296 /* check mbox status */
297 297 if (mb_cqe->u0.s.completion_status != 0) {
298 298 oce_log(dev, CE_WARN, MOD_CONFIG,
299 299 "MBOX Command Failed with Status: %d %d",
300 300 mb_cqe->u0.s.completion_status,
301 301 mb_cqe->u0.s.extended_status);
302 302 mutex_exit(&dev->bmbx_lock);
303 303 return (EIO);
304 304 }
305 305
306 306 /*
307 307 * store the mbx context in the cqe tag section so that
308 308 * the upper layer handling the cqe can associate the mbx
309 309 * with the response
310 310 */
311 311 if (mbxctx) {
312 312 /* save context */
313 313 mbxctx->mbx = mb_mbx;
314 314 bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
315 315 sizeof (struct oce_mbx_ctx *));
316 316 }
317 317
318 318 mutex_exit(&dev->bmbx_lock);
319 319 return (0);
320 320 } /* oce_mbox_post */
321 321
322 322 /*
323 323 * function to get the firmware version
324 324 *
325 325 * dev - software handle to the device
326 326 *
327 327 * return 0 on success, EIO on failure
328 328 */
329 329 int
330 330 oce_get_fw_version(struct oce_dev *dev)
331 331 {
332 332 struct oce_mbx mbx;
333 333 struct mbx_get_common_fw_version *fwcmd;
334 334 int ret = 0;
335 335
336 336 bzero(&mbx, sizeof (struct oce_mbx));
337 337
338 338 /* initialize the ioctl header */
339 339 fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
340 340 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
341 341 MBX_SUBSYSTEM_COMMON,
342 342 OPCODE_GET_COMMON_FW_VERSION,
343 343 MBX_TIMEOUT_SEC,
344 344 sizeof (struct mbx_get_common_fw_version));
345 345
346 346 /* fill rest of mbx */
347 347 mbx.u0.s.embedded = 1;
348 348 mbx.payload_length = sizeof (struct mbx_get_common_fw_version);
349 349 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
350 350
351 351 /* now post the command */
352 352 ret = oce_mbox_post(dev, &mbx, NULL);
353 353
354 354 if (ret != 0) {
355 355 return (ret);
356 356 }
357 357 bcopy(fwcmd->params.rsp.fw_ver_str, dev->fw_version, 32);
358 358
359 359 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s %s",
360 360 fwcmd->params.rsp.fw_ver_str,
361 361 fwcmd->params.rsp.fw_on_flash_ver_str);
362 362
363 363 return (0);
364 364 } /* oce_get_fw_version */
365 365
366 366 /*
367 367 * function to invoke f/w reset via. mailbox
368 368 * does not hold bootstap lock called by quiesce
369 369 *
370 370 * dev - software handle to the device
371 371 *
372 372 * return 0 on success, ETIMEDOUT on failure
373 373 *
374 374 */
375 375 int
376 376 oce_reset_fun(struct oce_dev *dev)
377 377 {
378 378 struct oce_mbx *mbx;
379 379 struct oce_bmbx *mb;
380 380 struct ioctl_common_function_reset *fwcmd;
381 381
382 382 mb = (struct oce_bmbx *)DBUF_VA(dev->bmbx);
383 383 mbx = &mb->mbx;
384 384 bzero(mbx, sizeof (struct oce_mbx));
385 385 /* initialize the ioctl header */
386 386 fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
387 387 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
388 388 MBX_SUBSYSTEM_COMMON,
389 389 OPCODE_COMMON_FUNCTION_RESET,
390 390 MBX_TIMEOUT_SEC,
391 391 sizeof (struct ioctl_common_function_reset));
392 392
393 393 /* fill rest of mbx */
394 394 mbx->u0.s.embedded = 1;
395 395 mbx->payload_length = sizeof (struct ioctl_common_function_reset);
396 396 DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
397 397
398 398 return (oce_mbox_dispatch(dev, 0));
399 399 } /* oce_reset_fun */
400 400
401 401 /*
402 402 * function to read the mac address associated with an interface
403 403 *
404 404 * dev - software handle to the device
405 405 * if_id - interface id to read the address from
406 406 * perm - set to 1 if reading the factory mac address. In this case
407 407 * if_id is ignored
408 408 * type - type of the mac address, whether network or storage
409 409 * mac - [OUTPUT] pointer to a buffer containing the mac address
410 410 * when the command succeeds
411 411 *
412 412 * return 0 on success, EIO on failure
413 413 */
414 414 int
415 415 oce_read_mac_addr(struct oce_dev *dev, uint32_t if_id, uint8_t perm,
416 416 uint8_t type, struct mac_address_format *mac)
417 417 {
418 418 struct oce_mbx mbx;
419 419 struct mbx_query_common_iface_mac *fwcmd;
420 420 int ret = 0;
421 421
422 422 bzero(&mbx, sizeof (struct oce_mbx));
423 423 /* initialize the ioctl header */
424 424 fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
425 425 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
426 426 MBX_SUBSYSTEM_COMMON,
427 427 OPCODE_QUERY_COMMON_IFACE_MAC,
428 428 MBX_TIMEOUT_SEC,
429 429 sizeof (struct mbx_query_common_iface_mac));
430 430
431 431 /* fill the command */
432 432 fwcmd->params.req.permanent = perm;
433 433 if (perm)
434 434 fwcmd->params.req.if_id = (uint16_t)if_id;
435 435 else
436 436 fwcmd->params.req.if_id = 0;
437 437 fwcmd->params.req.type = type;
438 438
439 439 /* fill rest of mbx */
440 440 mbx.u0.s.embedded = 1;
441 441 mbx.payload_length = sizeof (struct mbx_query_common_iface_mac);
442 442 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
443 443
444 444 /* now post the command */
445 445 ret = oce_mbox_post(dev, &mbx, NULL);
446 446 if (ret != 0) {
447 447 return (ret);
448 448 }
449 449
450 450 /* get the response */
451 451 oce_log(dev, CE_NOTE, MOD_CONFIG,
452 452 "MAC addr size = 0x%x",
453 453 LE_16(fwcmd->params.rsp.mac.size_of_struct));
454 454 oce_log(dev, CE_NOTE, MOD_CONFIG,
455 455 "MAC_ADDR:0x%x:0x%x:0x%x:0x%x:0x%x:0x%x",
456 456 fwcmd->params.rsp.mac.mac_addr[0],
457 457 fwcmd->params.rsp.mac.mac_addr[1],
458 458 fwcmd->params.rsp.mac.mac_addr[2],
459 459 fwcmd->params.rsp.mac.mac_addr[3],
460 460 fwcmd->params.rsp.mac.mac_addr[4],
461 461 fwcmd->params.rsp.mac.mac_addr[5]);
462 462
463 463 /* copy the mac addres in the output parameter */
464 464 mac->size_of_struct = LE_16(fwcmd->params.rsp.mac.size_of_struct);
465 465 bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
466 466 mac->size_of_struct);
467 467
468 468 return (0);
469 469 } /* oce_read_mac_addr */
470 470
471 471 /*
472 472 * function to create an interface using the OPCODE_CREATE_COMMON_IFACE
473 473 * command
474 474 *
475 475 * dev - software handle to the device
476 476 * cap_flags - capability flags
477 477 * en_flags - enable capability flags
478 478 * vlan_tag - optional vlan tag to associate with the if
479 479 * mac_addr - pointer to a buffer containing the mac address
480 480 * if_id - [OUTPUT] pointer to an integer to hold the ID of the
481 481 * interface created
482 482 *
483 483 * return 0 on success, EIO on failure
484 484 */
485 485 int
486 486 oce_if_create(struct oce_dev *dev, uint32_t cap_flags, uint32_t en_flags,
487 487 uint16_t vlan_tag, uint8_t *mac_addr,
488 488 uint32_t *if_id)
489 489 {
490 490 struct oce_mbx mbx;
491 491 struct mbx_create_common_iface *fwcmd;
492 492 int ret = 0;
493 493
494 494 bzero(&mbx, sizeof (struct oce_mbx));
495 495
496 496 /* initialize the ioctl header */
497 497 fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
498 498 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
499 499 MBX_SUBSYSTEM_COMMON,
500 500 OPCODE_CREATE_COMMON_IFACE,
501 501 MBX_TIMEOUT_SEC,
502 502 sizeof (struct mbx_create_common_iface));
503 503 DW_SWAP(u32ptr(&fwcmd->hdr), sizeof (struct mbx_hdr));
504 504
505 505 /* fill the command */
506 506 fwcmd->params.req.version = 0;
507 507 fwcmd->params.req.cap_flags = LE_32(cap_flags);
508 508 fwcmd->params.req.enable_flags = LE_32(en_flags);
509 509 if (mac_addr != NULL) {
510 510 bcopy(mac_addr, &fwcmd->params.req.mac_addr[0],
511 511 ETHERADDRL);
512 512 fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
513 513 fwcmd->params.req.mac_invalid = B_FALSE;
514 514 } else {
515 515 fwcmd->params.req.mac_invalid = B_TRUE;
516 516 }
517 517
518 518 /* fill rest of mbx */
519 519 mbx.u0.s.embedded = 1;
520 520 mbx.payload_length = sizeof (struct mbx_create_common_iface);
521 521 DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
522 522
523 523 /* now post the command */
524 524 ret = oce_mbox_post(dev, &mbx, NULL);
525 525 if (ret != 0) {
526 526 return (ret);
527 527 }
528 528
529 529
530 530
531 531 /* get response */
532 532 *if_id = LE_32(fwcmd->params.rsp.if_id);
533 533 oce_log(dev, CE_NOTE, MOD_CONFIG,
534 534 "IF_ID = 0x%x", *if_id);
535 535
536 536 /* If asked to set mac addr save the pmac handle */
537 537 if (mac_addr != NULL) {
538 538 dev->pmac_id = LE_32(fwcmd->params.rsp.pmac_id);
539 539 oce_log(dev, CE_NOTE, MOD_CONFIG,
540 540 "PMAC_ID = 0x%x", dev->pmac_id);
541 541 }
542 542 return (0);
543 543 } /* oce_if_create */
544 544
545 545 /*
546 546 * function to delete an interface
547 547 *
548 548 * dev - software handle to the device
549 549 * if_id - ID of the interface to delete
550 550 *
551 551 * return 0 on success, EIO on failure
552 552 */
553 553 int
554 554 oce_if_del(struct oce_dev *dev, uint32_t if_id)
555 555 {
556 556 struct oce_mbx mbx;
557 557 struct mbx_destroy_common_iface *fwcmd;
558 558 int ret = 0;
559 559
560 560 bzero(&mbx, sizeof (struct oce_mbx));
561 561 /* initialize the ioctl header */
562 562 fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
563 563 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
564 564 MBX_SUBSYSTEM_COMMON,
565 565 OPCODE_DESTROY_COMMON_IFACE,
566 566 MBX_TIMEOUT_SEC,
567 567 sizeof (struct mbx_destroy_common_iface));
568 568
569 569 /* fill the command */
570 570 fwcmd->params.req.if_id = if_id;
571 571
572 572 /* fill rest of mbx */
573 573 mbx.u0.s.embedded = 1;
574 574 mbx.payload_length = sizeof (struct mbx_destroy_common_iface);
575 575 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
576 576
577 577 /* post the command */
578 578 ret = oce_mbox_post(dev, &mbx, NULL);
579 579 return (ret);
580 580 } /* oce_if_del */
581 581
582 582 /*
583 583 * function to query the link status from the hardware
584 584 *
585 585 * dev - software handle to the device
586 586 * link_status - [OUT] pointer to the structure returning the link attributes
587 587 *
588 588 * return 0 on success, EIO on failure
589 589 */
590 590 int
591 591 oce_get_link_status(struct oce_dev *dev, struct link_status *link)
592 592 {
593 593 struct oce_mbx mbx;
594 594 struct mbx_query_common_link_status *fwcmd;
595 595 int ret = 0;
596 596
597 597 bzero(&mbx, sizeof (struct oce_mbx));
598 598
599 599 /* initialize the ioctl header */
600 600 fwcmd = (struct mbx_query_common_link_status *)&mbx.payload;
601 601 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
602 602 MBX_SUBSYSTEM_COMMON,
603 603 OPCODE_QUERY_COMMON_LINK_STATUS,
604 604 MBX_TIMEOUT_SEC,
605 605 sizeof (struct mbx_query_common_link_status));
606 606
607 607 /* fill rest of mbx */
608 608 mbx.u0.s.embedded = 1;
609 609 mbx.payload_length = sizeof (struct mbx_query_common_link_status);
610 610 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
611 611
612 612 /* post the command */
613 613 ret = oce_mbox_post(dev, &mbx, NULL);
614 614
615 615 if (ret != 0) {
616 616 return (ret);
617 617 }
618 618
619 619 /* interpret response */
620 620 bcopy(&fwcmd->params.rsp, link, sizeof (struct link_status));
621 621 link->logical_link_status = LE_32(link->logical_link_status);
622 622 link->qos_link_speed = LE_16(link->qos_link_speed);
623 623
624 624 return (0);
625 625 } /* oce_get_link_status */
626 626
627 627 /*
628 628 * function to configure the rx filter on the interface
629 629 *
630 630 * dev - software handle to the device
631 631 * filter - mbx command containing the filter parameters
632 632 *
633 633 * return 0 on success, EIO on failure
634 634 */
635 635 int
636 636 oce_set_rx_filter(struct oce_dev *dev,
637 637 struct mbx_set_common_ntwk_rx_filter *filter)
638 638 {
639 639 struct oce_mbx mbx;
640 640 struct mbx_set_common_ntwk_rx_filter *fwcmd;
641 641 int ret;
642 642
643 643 bzero(&mbx, sizeof (struct oce_mbx));
644 644 fwcmd = (struct mbx_set_common_ntwk_rx_filter *)&mbx.payload;
645 645 /* fill the command */
646 646 bcopy(filter, fwcmd, sizeof (struct mbx_set_common_ntwk_rx_filter));
647 647
648 648 /* initialize the ioctl header */
649 649 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
650 650 MBX_SUBSYSTEM_COMMON,
651 651 OPCODE_COMMON_NTWK_RX_FILTER,
652 652 MBX_TIMEOUT_SEC,
653 653 sizeof (struct mbx_set_common_ntwk_rx_filter));
654 654
655 655 /* fill rest of mbx */
656 656 mbx.u0.s.embedded = 1;
657 657 mbx.payload_length = sizeof (struct mbx_set_common_ntwk_rx_filter);
658 658 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
659 659
660 660 /* post the command */
661 661 ret = oce_mbox_post(dev, &mbx, NULL);
662 662
663 663 return (ret);
664 664 } /* oce_set_rx_filter */
665 665
666 666 /*
667 667 * function to send the mbx command to update the mcast table with fw
668 668 *
669 669 * dev - software handle to the device
670 670 * mca_table - array of mcast address to update
671 671 * mca_cnt - number of elements in mca_table
672 672 * enable_promisc - flag to enable/disable mcast-promiscuous mode
673 673 *
674 674 * return 0 on success, EIO on failure
675 675 */
676 676 int
677 677 oce_set_multicast_table(struct oce_dev *dev, uint32_t if_id,
678 678 struct ether_addr *mca_table, uint16_t mca_cnt, boolean_t promisc)
679 679 {
680 680 struct oce_mbx mbx;
681 681 struct mbx_set_common_iface_multicast *fwcmd;
682 682 int ret;
683 683
684 684 bzero(&mbx, sizeof (struct oce_mbx));
685 685 fwcmd = (struct mbx_set_common_iface_multicast *)&mbx.payload;
686 686
687 687 /* initialize the ioctl header */
688 688 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
689 689 MBX_SUBSYSTEM_COMMON,
690 690 OPCODE_SET_COMMON_IFACE_MULTICAST,
691 691 MBX_TIMEOUT_SEC,
692 692 sizeof (struct mbx_set_common_iface_multicast));
693 693
694 694 /* fill the command */
695 695 fwcmd->params.req.if_id = (uint8_t)if_id;
696 696 if (mca_table != NULL) {
697 697 bcopy(mca_table, &fwcmd->params.req.mac[0],
698 698 mca_cnt * ETHERADDRL);
699 699 }
700 700 fwcmd->params.req.num_mac = LE_16(mca_cnt);
701 701 fwcmd->params.req.promiscuous = (uint8_t)promisc;
702 702
703 703 /* fill rest of mbx */
704 704 mbx.u0.s.embedded = B_TRUE;
705 705 mbx.payload_length = sizeof (struct mbx_set_common_iface_multicast);
706 706 /* Swap only MBX header + BOOTSTRAP HDR */
707 707 DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ));
708 708
709 709 /* post the command */
710 710 ret = oce_mbox_post(dev, &mbx, NULL);
711 711
712 712 return (ret);
713 713 } /* oce_set_multicast_table */
714 714
715 715 /*
716 716 * function to query the fw attributes from the hw
717 717 *
718 718 * dev - software handle to the device
719 719 *
720 720 * return 0 on success, EIO on failure
721 721 */
722 722 int
723 723 oce_get_fw_config(struct oce_dev *dev)
724 724 {
725 725 struct oce_mbx mbx;
726 726 struct mbx_common_query_fw_config *fwcmd;
727 727 int ret = 0;
728 728
729 729 bzero(&mbx, sizeof (struct oce_mbx));
730 730 /* initialize the ioctl header */
731 731 fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
732 732 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
733 733 MBX_SUBSYSTEM_COMMON,
734 734 OPCODE_QUERY_COMMON_FIRMWARE_CONFIG,
735 735 MBX_TIMEOUT_SEC,
736 736 sizeof (struct mbx_common_query_fw_config));
737 737
738 738 /* fill rest of mbx */
739 739 mbx.u0.s.embedded = 1;
740 740 mbx.payload_length = sizeof (struct mbx_common_query_fw_config);
741 741 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
742 742
743 743 /* now post the command */
744 744 ret = oce_mbox_post(dev, &mbx, NULL);
745 745
746 746 if (ret != 0) {
747 747 return (ret);
748 748 }
749 749
750 750 /* swap and copy into buffer */
751 751 DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_common_query_fw_config));
752 752
753 753 dev->config_number = fwcmd->params.rsp.config_number;
754 754 dev->asic_revision = fwcmd->params.rsp.asic_revision;
755 755 dev->port_id = fwcmd->params.rsp.port_id;
756 756 dev->function_mode = fwcmd->params.rsp.function_mode;
757 757
758 758 /* get the max rings alloted for this function */
759 759 if (fwcmd->params.rsp.ulp[0].mode & ULP_NIC_MODE) {
760 760 dev->max_tx_rings = fwcmd->params.rsp.ulp[0].wq_count;
761 761 dev->max_rx_rings = fwcmd->params.rsp.ulp[0].rq_count;
762 762 } else {
763 763 dev->max_tx_rings = fwcmd->params.rsp.ulp[1].wq_count;
764 764 dev->max_rx_rings = fwcmd->params.rsp.ulp[1].rq_count;
765 765 }
766 766 dev->function_caps = fwcmd->params.rsp.function_caps;
767 767 return (0);
768 768 } /* oce_get_fw_config */
769 769
770 770 /*
771 771 * function to retrieve statistic counters from the hardware
772 772 *
773 773 * dev - software handle to the device
774 774 *
775 775 * return 0 on success, EIO on failure
776 776 */
777 777 int
778 778 oce_get_hw_stats(struct oce_dev *dev)
779 779 {
780 780 struct oce_mbx mbx;
781 781 struct mbx_get_nic_stats *fwcmd = dev->hw_stats;
782 782 int ret = 0;
783 783
784 784 bzero(&mbx, sizeof (struct oce_mbx));
785 785 /* initialize the ioctl header */
786 786 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
787 787 MBX_SUBSYSTEM_NIC,
788 788 OPCODE_GET_NIC_STATS,
789 789 MBX_TIMEOUT_SEC,
790 790 sizeof (struct mbx_get_nic_stats));
791 791 DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_get_nic_stats));
792 792
793 793 /* fill rest of mbx */
794 794 mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(DBUF_PA(dev->stats_dbuf));
795 795 mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(DBUF_PA(dev->stats_dbuf));
796 796 mbx.payload.u0.u1.sgl[0].length = sizeof (struct mbx_get_nic_stats);
797 797 mbx.payload_length = sizeof (struct mbx_get_nic_stats);
798 798
799 799 mbx.u0.s.embedded = 0;
800 800 mbx.u0.s.sge_count = 1;
801 801
802 802 DW_SWAP(u32ptr(&mbx), sizeof (struct oce_mq_sge) + OCE_BMBX_RHDR_SZ);
803 803
804 804 bzero(&dev->hw_stats->params, sizeof (dev->hw_stats->params));
805 805
806 806 /* sync for device */
807 807 (void) DBUF_SYNC(dev->stats_dbuf, DDI_DMA_SYNC_FORDEV);
808 808
809 809 /* now post the command */
810 810 ret = oce_mbox_post(dev, &mbx, NULL);
811 811 /* sync the stats */
812 812 (void) DBUF_SYNC(dev->stats_dbuf, DDI_DMA_SYNC_FORKERNEL);
813 813
814 814 /* Check the mailbox status and command completion status */
815 815 if (ret != 0) {
816 816 return (ret);
817 817 }
818 818
819 819 DW_SWAP(u32ptr(dev->hw_stats), sizeof (struct mbx_get_nic_stats));
820 820 return (0);
821 821 } /* oce_get_hw_stats */
822 822
823 823 /*
824 824 * function to set the number of vectors with the cev
825 825 *
826 826 * dev - software handle to the device
827 827 * num_vectors - number of MSI messages
828 828 *
829 829 * return 0 on success, EIO on failure
830 830 */
831 831 int
832 832 oce_num_intr_vectors_set(struct oce_dev *dev, uint32_t num_vectors)
833 833 {
834 834 struct oce_mbx mbx;
835 835 struct mbx_common_cev_modify_msi_messages *fwcmd;
836 836 int ret = 0;
837 837
838 838 bzero(&mbx, sizeof (struct oce_mbx));
839 839 /* initialize the ioctl header */
840 840 fwcmd = (struct mbx_common_cev_modify_msi_messages *)&mbx.payload;
841 841 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
842 842 MBX_SUBSYSTEM_COMMON,
843 843 OPCODE_COMMON_CEV_MODIFY_MSI_MESSAGES,
844 844 MBX_TIMEOUT_SEC,
845 845 sizeof (struct mbx_common_cev_modify_msi_messages));
846 846
847 847 /* fill the command */
848 848 fwcmd->params.req.num_msi_msgs = LE_32(num_vectors);
849 849
850 850 /* fill rest of mbx */
851 851 mbx.u0.s.embedded = 1;
852 852 mbx.payload_length =
853 853 sizeof (struct mbx_common_cev_modify_msi_messages);
854 854 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
855 855
856 856 /* post the command */
857 857 ret = oce_mbox_post(dev, &mbx, NULL);
858 858
859 859 return (ret);
860 860 } /* oce_num_intr_vectors_set */
861 861
862 862 /*
863 863 * function to set flow control capability in the hardware
864 864 *
865 865 * dev - software handle to the device
866 866 * flow_control - flow control flags to set
867 867 *
868 868 * return 0 on success, EIO on failure
869 869 */
870 870 int
871 871 oce_set_flow_control(struct oce_dev *dev, uint32_t flow_control)
872 872 {
873 873 struct oce_mbx mbx;
874 874 struct mbx_common_get_set_flow_control *fwcmd =
875 875 (struct mbx_common_get_set_flow_control *)&mbx.payload;
876 876 int ret;
877 877
878 878 bzero(&mbx, sizeof (struct oce_mbx));
879 879 /* initialize the ioctl header */
880 880 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
881 881 MBX_SUBSYSTEM_COMMON,
882 882 OPCODE_SET_COMMON_FLOW_CONTROL,
883 883 MBX_TIMEOUT_SEC,
884 884 sizeof (struct mbx_common_get_set_flow_control));
885 885
886 886 /* fill command */
887 887 if (flow_control & OCE_FC_TX)
888 888 fwcmd->tx_flow_control = 1;
889 889
890 890 if (flow_control & OCE_FC_RX)
891 891 fwcmd->rx_flow_control = 1;
892 892
893 893 /* fill rest of mbx */
894 894 mbx.u0.s.embedded = 1;
895 895 mbx.payload_length = sizeof (struct mbx_common_get_set_flow_control);
896 896 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
897 897
898 898 /* post the command */
899 899 ret = oce_mbox_post(dev, &mbx, NULL);
900 900
901 901 return (ret);
902 902 } /* oce_set_flow_control */
903 903
904 904 /*
905 905 * function to get the current flow control setting with the hardware
906 906 *
907 907 * dev - software handle to the device
908 908 * flow_control - [OUT] pointer to location where flow_control setting
909 909 * is returned
910 910 *
911 911 * return 0 on success, EIO on failure
912 912 */
913 913 int
914 914 oce_get_flow_control(struct oce_dev *dev, uint32_t *flow_control)
915 915 {
916 916 struct oce_mbx mbx;
917 917 struct mbx_common_get_set_flow_control *fwcmd;
918 918 int ret;
919 919
920 920 DEV_LOCK(dev);
921 921 if (dev->suspended) {
922 922 DEV_UNLOCK(dev);
923 923 return (EIO);
924 924 }
925 925 DEV_UNLOCK(dev);
926 926
927 927 bzero(&mbx, sizeof (struct oce_mbx));
928 928 fwcmd = (struct mbx_common_get_set_flow_control *)&mbx.payload;
929 929
930 930 /* initialize the ioctl header */
931 931 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
932 932 MBX_SUBSYSTEM_COMMON,
933 933 OPCODE_GET_COMMON_FLOW_CONTROL,
934 934 MBX_TIMEOUT_SEC,
935 935 sizeof (struct mbx_common_get_set_flow_control));
936 936
937 937 /* fill rest of mbx */
938 938 mbx.u0.s.embedded = 1;
939 939 mbx.payload_length = sizeof (struct mbx_common_get_set_flow_control);
940 940 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
941 941
942 942 /* post the command */
943 943 ret = oce_mbox_post(dev, &mbx, NULL);
944 944
945 945 if (ret != 0) {
946 946 return (ret);
947 947 }
948 948
949 949 /* get the flow control */
950 950 DW_SWAP(u32ptr(fwcmd),
951 951 sizeof (struct mbx_common_get_set_flow_control));
952 952 *flow_control = 0;
953 953 if (fwcmd->tx_flow_control)
954 954 *flow_control |= OCE_FC_TX;
955 955
956 956 if (fwcmd->rx_flow_control)
957 957 *flow_control |= OCE_FC_RX;
958 958
959 959 return (0);
960 960 } /* oce_get_flow_control */
961 961
962 962 /*
963 963 * function to enable/disable device promiscuous mode
964 964 *
965 965 * dev - software handle to the device
966 966 * enable - enable/disable flag
967 967 *
968 968 * return 0 on success, EIO on failure
969 969 */
970 970 int
971 971 oce_set_promiscuous(struct oce_dev *dev, boolean_t enable)
972 972 {
973 973 struct oce_mbx mbx;
974 974 struct mbx_config_nic_promiscuous *fwcmd;
975 975 int ret;
976 976
977 977 bzero(&mbx, sizeof (struct oce_mbx));
978 978
979 979 fwcmd = (struct mbx_config_nic_promiscuous *)&mbx.payload;
980 980
981 981 if (dev->port_id == 0) {
982 982 fwcmd->params.req.port0_promisc = (uint8_t)enable;
983 983
984 984 } else {
985 985 fwcmd->params.req.port1_promisc = (uint8_t)enable;
986 986 }
987 987
988 988 /* initialize the ioctl header */
989 989 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
990 990 MBX_SUBSYSTEM_NIC,
991 991 OPCODE_CONFIG_NIC_PROMISCUOUS,
992 992 MBX_TIMEOUT_SEC,
993 993 sizeof (struct mbx_config_nic_promiscuous));
994 994 /* fill rest of mbx */
995 995 mbx.u0.s.embedded = 1;
996 996 mbx.payload_length = sizeof (struct mbx_config_nic_promiscuous);
997 997 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
998 998
999 999 /* post the command */
1000 1000 ret = oce_mbox_post(dev, &mbx, NULL);
1001 1001
1002 1002 return (ret);
1003 1003 }
1004 1004
1005 1005 /*
1006 1006 * function to add a unicast address to an interface
1007 1007 *
1008 1008 * dev - software handle to the device
1009 1009 * mac - unicast address
1010 1010 *
1011 1011 * return 0 on success, EIO on failure
1012 1012 */
1013 1013 int
1014 1014 oce_add_mac(struct oce_dev *dev, uint32_t if_id,
1015 1015 const uint8_t *mac, uint32_t *pmac_id)
1016 1016 {
1017 1017 struct oce_mbx mbx;
1018 1018 struct mbx_add_common_iface_mac *fwcmd;
1019 1019 int ret;
1020 1020
1021 1021 bzero(&mbx, sizeof (struct oce_mbx));
1022 1022 fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1023 1023 fwcmd->params.req.if_id = LE_32(if_id);
1024 1024 bcopy(mac, &fwcmd->params.req.mac_address[0], ETHERADDRL);
1025 1025
1026 1026 /* initialize the ioctl header */
1027 1027 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1028 1028 MBX_SUBSYSTEM_COMMON,
1029 1029 OPCODE_ADD_COMMON_IFACE_MAC,
1030 1030 MBX_TIMEOUT_SEC,
1031 1031 sizeof (struct mbx_add_common_iface_mac));
1032 1032
1033 1033 /* fill rest of mbx */
1034 1034 mbx.u0.s.embedded = 1;
1035 1035 mbx.payload_length = sizeof (struct mbx_add_common_iface_mac);
1036 1036 DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ);
1037 1037
1038 1038 /* post the command */
1039 1039 ret = oce_mbox_post(dev, &mbx, NULL);
1040 1040
1041 1041 if (ret != 0) {
1042 1042 return (ret);
1043 1043 }
1044 1044
1045 1045 *pmac_id = LE_32(fwcmd->params.rsp.pmac_id);
1046 1046 return (0);
1047 1047 }
1048 1048
1049 1049 /*
1050 1050 * function to delete an unicast address associated with an interface
1051 1051 *
1052 1052 * dev - software handle to the device
1053 1053 * pmac_id - handle to the address added using ace_add_mac
1054 1054 *
1055 1055 * return 0 on success, EIO on failure
1056 1056 */
1057 1057 int
1058 1058 oce_del_mac(struct oce_dev *dev, uint32_t if_id, uint32_t *pmac_id)
1059 1059 {
1060 1060 struct oce_mbx mbx;
1061 1061 struct mbx_del_common_iface_mac *fwcmd;
1062 1062 int ret;
1063 1063
1064 1064 bzero(&mbx, sizeof (struct oce_mbx));
1065 1065 fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1066 1066 fwcmd->params.req.if_id = if_id;
1067 1067 fwcmd->params.req.pmac_id = *pmac_id;
1068 1068
1069 1069 /* initialize the ioctl header */
1070 1070 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1071 1071 MBX_SUBSYSTEM_COMMON,
1072 1072 OPCODE_DEL_COMMON_IFACE_MAC,
1073 1073 MBX_TIMEOUT_SEC,
1074 1074 sizeof (struct mbx_add_common_iface_mac));
1075 1075
1076 1076 /* fill rest of mbx */
1077 1077 mbx.u0.s.embedded = 1;
1078 1078 mbx.payload_length = sizeof (struct mbx_del_common_iface_mac);
1079 1079 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1080 1080
1081 1081 /* post the command */
1082 1082 ret = oce_mbox_post(dev, &mbx, NULL);
1083 1083
1084 1084 return (ret);
1085 1085 }
1086 1086
1087 1087
1088 1088 /*
1089 1089 * function to send the mbx command to configure vlan
1090 1090 *
1091 1091 * dev - software handle to the device
1092 1092 * vtag_arr - array of vlan tags
1093 1093 * vtag_cnt - number of elements in array
1094 1094 * untagged - boolean TRUE/FLASE
1095 1095 * enable_promisc - flag to enable/disable VLAN promiscuous mode
1096 1096 *
1097 1097 * return 0 on success, EIO on failure
1098 1098 */
1099 1099 int
1100 1100 oce_config_vlan(struct oce_dev *dev, uint32_t if_id,
1101 1101 struct normal_vlan *vtag_arr, uint8_t vtag_cnt,
1102 1102 boolean_t untagged, boolean_t enable_promisc)
1103 1103 {
1104 1104 struct oce_mbx mbx;
1105 1105 struct mbx_common_config_vlan *fwcmd;
1106 1106 int ret;
1107 1107
1108 1108 bzero(&mbx, sizeof (struct oce_mbx));
1109 1109 fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
1110 1110
1111 1111 /* initialize the ioctl header */
1112 1112 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1113 1113 MBX_SUBSYSTEM_COMMON,
1114 1114 OPCODE_CONFIG_COMMON_IFACE_VLAN,
1115 1115 MBX_TIMEOUT_SEC,
1116 1116 sizeof (struct mbx_common_config_vlan));
1117 1117
1118 1118 fwcmd->params.req.if_id = (uint8_t)if_id;
1119 1119 fwcmd->params.req.promisc = (uint8_t)enable_promisc;
1120 1120 fwcmd->params.req.untagged = (uint8_t)untagged;
1121 1121 fwcmd->params.req.num_vlans = vtag_cnt;
1122 1122
1123 1123 /* Set the vlan tag filter on hw */
1124 1124 if (!enable_promisc) {
1125 1125 bcopy(fwcmd->params.req.tags.normal_vlans, vtag_arr,
1126 1126 vtag_cnt * sizeof (struct normal_vlan));
1127 1127 }
1128 1128
1129 1129 /* fill rest of mbx */
1130 1130 mbx.u0.s.embedded = B_TRUE;
1131 1131 mbx.payload_length = sizeof (struct mbx_common_config_vlan);
1132 1132 DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
1133 1133
1134 1134 /* post the command */
1135 1135 ret = oce_mbox_post(dev, &mbx, NULL);
1136 1136
1137 1137 return (ret);
1138 1138 } /* oce_config_vlan */
1139 1139
1140 1140
1141 1141 /*
1142 1142 * function to enable or disable the link
1143 1143 *
1144 1144 * dev - software handle to the device
1145 1145 * mca_table - array of mcast address to update
1146 1146 * mca_cnt - number of elements in mca_table
1147 1147 * enable_promisc - flag to enable/disable mcast-promiscuous mode
1148 1148 *
1149 1149 * return 0 on success, EIO on failure
1150 1150 */
1151 1151 int
1152 1152 oce_config_link(struct oce_dev *dev, boolean_t enable)
1153 1153 {
1154 1154 struct oce_mbx mbx;
1155 1155 struct mbx_common_func_link_cfg *fwcmd;
1156 1156 int ret;
1157 1157
1158 1158 bzero(&mbx, sizeof (struct oce_mbx));
1159 1159 fwcmd = (struct mbx_common_func_link_cfg *)&mbx.payload;
1160 1160
1161 1161 /* initialize the ioctl header */
1162 1162 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1163 1163 MBX_SUBSYSTEM_COMMON,
1164 1164 OPCODE_COMMON_FUNCTION_LINK_CONFIG,
1165 1165 MBX_TIMEOUT_SEC,
1166 1166 sizeof (struct mbx_common_config_vlan));
1167 1167
1168 1168 fwcmd->params.req.enable = enable;
1169 1169
1170 1170 /* fill rest of mbx */
1171 1171 mbx.u0.s.embedded = B_TRUE;
1172 1172 mbx.payload_length = sizeof (struct mbx_common_func_link_cfg);
1173 1173 DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
1174 1174
1175 1175 /* post the command */
1176 1176 ret = oce_mbox_post(dev, &mbx, NULL);
1177 1177
1178 1178 return (ret);
1179 1179 } /* oce_config_link */
1180 1180
1181 1181 int
1182 1182 oce_config_rss(struct oce_dev *dev, uint16_t if_id, char *hkey, char *itbl,
1183 1183 int tbl_sz, uint16_t rss_type, uint8_t flush)
1184 1184 {
1185 1185 struct oce_mbx mbx;
1186 1186 struct mbx_config_nic_rss *fwcmd;
1187 1187 int i;
1188 1188 int ret = 0;
1189 1189
1190 1190 bzero(&mbx, sizeof (struct oce_mbx));
1191 1191 fwcmd = (struct mbx_config_nic_rss *)&mbx.payload;
1192 1192
1193 1193 /* initialize the ioctl header */
1194 1194 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1195 1195 MBX_SUBSYSTEM_NIC,
1196 1196 OPCODE_CONFIG_NIC_RSS,
1197 1197 MBX_TIMEOUT_SEC,
1198 1198 sizeof (struct mbx_config_nic_rss));
1199 1199 fwcmd->params.req.enable_rss = LE_16(rss_type);
1200 1200 fwcmd->params.req.flush = flush;
1201 1201 fwcmd->params.req.if_id = LE_32(if_id);
1202 1202
1203 1203 if (hkey != NULL) {
1204 1204 bcopy(hkey, fwcmd->params.req.hash, OCE_HKEY_SIZE);
1205 1205 }
1206 1206
1207 1207
1208 1208 /* Fill the indirection table */
1209 1209 for (i = 0; i < tbl_sz; i++) {
1210 1210 fwcmd->params.req.cputable[i] = itbl[i];
1211 1211 }
1212 1212
1213 1213 fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(tbl_sz));
1214 1214
1215 1215 /* fill rest of mbx */
1216 1216 mbx.u0.s.embedded = B_TRUE;
1217 1217 mbx.payload_length = sizeof (struct mbx_config_nic_rss);
1218 1218 DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ));
1219 1219
1220 1220 /* post the command */
1221 1221 ret = oce_mbox_post(dev, &mbx, NULL);
1222 1222
1223 1223 return (ret);
1224 1224 }
1225 1225
1226 1226 /*
1227 1227 * function called from the gld ioctl entry point to send a mbx to fw
1228 1228 *
1229 1229 * dev - software handle to the device
1230 1230 * mp - mblk_t containing the user data
1231 1231 * payload_len = [OUT] pointer to return the length of the payload written
1232 1232 *
1233 1233 * return 0 on Success
1234 1234 */
1235 1235 int
1236 1236 oce_issue_mbox(struct oce_dev *dev, queue_t *wq, mblk_t *mp,
1237 1237 uint32_t *payload_len)
1238 1238 {
1239 1239 int ret;
1240 1240 struct oce_mbx mbx;
1241 1241 struct mbx_hdr hdr;
1242 1242 ddi_dma_handle_t dma_handle;
1243 1243 boolean_t is_embedded = B_FALSE;
1244 1244 uint32_t payload_length;
1245 1245 int num_buf = 0;
1246 1246 int alloc_len;
1247 1247 caddr_t sg_va;
1248 1248 ddi_acc_handle_t acc_handle;
1249 1249 size_t actual_len;
1250 1250
1251 1251 _NOTE(ARGUNUSED(wq));
1252 1252
1253 1253 bzero(&mbx, sizeof (struct oce_mbx));
1254 1254
1255 1255 bcopy(mp->b_cont->b_rptr, &hdr, sizeof (struct mbx_hdr));
1256 1256 DW_SWAP(u32ptr(&hdr), sizeof (struct mbx_hdr));
1257 1257
1258 1258 payload_length = hdr.u0.req.request_length +
1259 1259 sizeof (struct mbx_hdr);
1260 1260
1261 1261 is_embedded = (payload_length <= sizeof (struct oce_mbx_payload));
1262 1262
1263 1263 alloc_len = msgdsize(mp->b_cont);
1264 1264
1265 1265 oce_log(dev, CE_NOTE, MOD_CONFIG, "Mailbox: "
1266 1266 "DW[0] 0x%x DW[1] 0x%x DW[2]0x%x DW[3]0x%x,"
1267 1267 "MBLKL(%lu) ALLOCLEN(%d)",
1268 1268 hdr.u0.dw[0], hdr.u0.dw[1],
1269 1269 hdr.u0.dw[2], hdr.u0.dw[3],
1270 1270 MBLKL(mp->b_cont), alloc_len);
1271 1271
1272 1272 /* get the timeout from the command header */
1273 1273 mbx.tag[0] = hdr.u0.req.timeout;
1274 1274
1275 1275 if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) {
1276 1276 struct mbx_common_read_write_flashrom *fwcmd =
1277 1277 (struct mbx_common_read_write_flashrom *)
1278 1278 mp->b_cont->b_rptr;
1279 1279
1280 1280 if (dev->cookie != 0 && dev->cookie != hdr.u0.req.rsvd0)
1281 1281 return (EINVAL);
1282 1282
1283 1283 if (dev->cookie == 0)
1284 1284 dev->cookie = hdr.u0.req.rsvd0;
1285 1285 hdr.u0.req.rsvd0 = 0;
1286 1286
1287 1287 oce_log(dev, CE_NOTE, MOD_CONFIG, "Mailbox params:"
1288 1288 "OPCODE(%d) OPTYPE = %d SIZE = %d OFFSET = %d",
1289 1289 fwcmd->flash_op_code, fwcmd->flash_op_type,
1290 1290 fwcmd->data_buffer_size, fwcmd->data_offset);
1291 1291 }
1292 1292
1293 1293 if (!is_embedded) {
1294 1294 mblk_t *tmp = NULL;
1295 1295 ddi_dma_cookie_t cookie;
1296 1296 uint32_t count = 0;
1297 1297 int offset = 0;
1298 1298
1299 1299 /* allocate dma handle */
1300 1300 ret = ddi_dma_alloc_handle(dev->dip,
1301 1301 &oce_sgl_dma_attr, DDI_DMA_DONTWAIT, NULL,
1302 1302 &dma_handle);
1303 1303 if (ret != DDI_SUCCESS) {
1304 1304 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
1305 1305 "Failed to alloc DMA handle");
1306 1306 ret = ENOMEM;
1307 1307 goto fail;
1308 1308 }
1309 1309
1310 1310 /* allocate the DMA-able memory */
1311 1311 ret = ddi_dma_mem_alloc(dma_handle, alloc_len,
1312 1312 &oce_sgl_buf_accattr,
1313 1313 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1314 1314 DDI_DMA_DONTWAIT,
1315 1315 NULL, &sg_va, &actual_len, &acc_handle);
1316 1316 if (ret != DDI_SUCCESS) {
1317 1317 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
1318 1318 "Failed to alloc DMA memory");
1319 1319 ret = ENOMEM;
1320 1320 goto dma_alloc_fail;
1321 1321 }
1322 1322
1323 1323 for (tmp = mp->b_cont; tmp != NULL; tmp = tmp->b_cont) {
1324 1324 bcopy((caddr_t)tmp->b_rptr, sg_va + offset, MBLKL(tmp));
1325 1325 offset += MBLKL(tmp);
1326 1326 }
1327 1327
1328 1328 /* bind mblk mem to handle */
1329 1329 ret = ddi_dma_addr_bind_handle(
1330 1330 dma_handle,
1331 1331 (struct as *)0, sg_va,
1332 1332 alloc_len,
1333 1333 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1334 1334 DDI_DMA_DONTWAIT, NULL, &cookie, &count);
1335 1335 if (ret != DDI_DMA_MAPPED) {
1336 1336 ret = ENOMEM;
1337 1337 oce_log(dev, CE_NOTE, MOD_CONFIG,
1338 1338 "Failed to bind DMA handle ret code: %d",
1339 1339 ret);
1340 1340 goto dma_bind_fail;
1341 1341 }
1342 1342
1343 1343 for (num_buf = 0; num_buf < count; num_buf++) {
1344 1344 /* fill the mbx sglist */
1345 1345 mbx.payload.u0.u1.sgl[num_buf].pa_lo =
1346 1346 ADDR_LO(cookie.dmac_laddress);
1347 1347 mbx.payload.u0.u1.sgl[num_buf].pa_hi =
1348 1348 ADDR_HI(cookie.dmac_laddress);
1349 1349 mbx.payload.u0.u1.sgl[num_buf].length =
1350 1350 (uint32_t)cookie.dmac_size;
1351 1351 mbx.payload_length +=
1352 1352 mbx.payload.u0.u1.sgl[num_buf].length;
1353 1353 mbx.u0.s.sge_count++;
1354 1354
1355 1355 if (count > 1)
1356 1356 (void) ddi_dma_nextcookie(dma_handle, &cookie);
1357 1357 }
1358 1358 mbx.u0.s.embedded = 0;
1359 1359
1360 1360 DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ +
1361 1361 (sizeof (struct oce_mq_sge) * count));
1362 1362 } else {
1363 1363 /* fill rest of mbx */
1364 1364 mbx.u0.s.embedded = 1;
1365 1365 mbx.payload_length = payload_length;
1366 1366 bcopy(mp->b_cont->b_rptr, &mbx.payload, payload_length);
1367 1367
1368 1368 DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
1369 1369 }
1370 1370
1371 1371 /* now post the command */
1372 1372 ret = oce_mbox_post(dev, &mbx, NULL);
1373 1373
1374 1374 bcopy(mp->b_cont->b_rptr, &hdr, sizeof (struct mbx_hdr));
1375 1375 DW_SWAP(u32ptr(&hdr), sizeof (struct mbx_hdr));
1376 1376
1377 1377 if (ret != DDI_SUCCESS) {
1378 1378 oce_log(dev, CE_WARN, MOD_CONFIG,
1379 1379 "Failed to post the mailbox: %d", ret);
1380 1380
1381 1381 *payload_len = hdr.u0.rsp.rsp_length +
1382 1382 sizeof (struct mbx_hdr);
1383 1383 if (is_embedded) {
1384 1384 bcopy(&mbx.payload, mp->b_cont->b_rptr,
1385 1385 MBLKL(mp->b_cont));
1386 1386 goto fail;
1387 1387 } else {
1388 1388 (void) ddi_dma_sync(dma_handle, 0, 0,
1389 1389 DDI_DMA_SYNC_FORKERNEL);
1390 1390
1391 1391 if (oce_fm_check_dma_handle(dev, dma_handle) !=
1392 1392 DDI_FM_OK) {
1393 1393 ddi_fm_service_impact(dev->dip,
1394 1394 DDI_SERVICE_DEGRADED);
1395 1395 }
1396 1396 bcopy(sg_va, mp->b_cont->b_rptr,
1397 1397 sizeof (struct mbx_hdr));
1398 1398 goto post_fail;
1399 1399 }
1400 1400 }
1401 1401
1402 1402 if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) {
1403 1403 struct mbx_common_read_write_flashrom *fwcmd =
1404 1404 (struct mbx_common_read_write_flashrom *)
1405 1405 mp->b_cont->b_rptr;
1406 1406
1407 1407 if (LE_32(fwcmd->flash_op_code) == MGMT_FLASHROM_OPCODE_FLASH)
1408 1408 dev->cookie = 0;
1409 1409 }
1410 1410
1411 1411 payload_length = hdr.u0.rsp.rsp_length + sizeof (struct mbx_hdr);
1412 1412
1413 1413 /* Copy the response back only if this is an embedded mbx cmd */
1414 1414 if (is_embedded) {
1415 1415 bcopy(&mbx.payload, mp->b_cont->b_rptr,
1416 1416 min(payload_length, MBLKL(mp->b_cont)));
1417 1417 } else {
1418 1418 mblk_t *tmp = NULL;
1419 1419 int offset = 0;
1420 1420 /* sync */
1421 1421 (void) ddi_dma_sync(dma_handle, 0, 0,
1422 1422 DDI_DMA_SYNC_FORKERNEL);
1423 1423 if (oce_fm_check_dma_handle(dev, dma_handle) != DDI_FM_OK) {
1424 1424 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
1425 1425 }
1426 1426
1427 1427 /* copy back from kernel allocated buffer to user buffer */
1428 1428 for (tmp = mp->b_cont; tmp != NULL; tmp = tmp->b_cont) {
1429 1429 bcopy(sg_va + offset, tmp->b_rptr, MBLKL(tmp));
1430 1430 offset += MBLKL(tmp);
1431 1431 }
1432 1432
1433 1433 /* unbind and free dma handles */
1434 1434 (void) ddi_dma_unbind_handle(dma_handle);
1435 1435 ddi_dma_mem_free(&acc_handle);
1436 1436 ddi_dma_free_handle(&dma_handle);
1437 1437 }
1438 1438
1439 1439 *payload_len = payload_length;
1440 1440
1441 1441 return (0);
1442 1442
1443 1443 post_fail:
1444 1444 (void) ddi_dma_unbind_handle(dma_handle);
1445 1445
1446 1446 dma_bind_fail:
1447 1447 ddi_dma_mem_free(&acc_handle);
1448 1448
1449 1449 dma_alloc_fail:
1450 1450 ddi_dma_free_handle(&dma_handle);
1451 1451
1452 1452 fail:
1453 1453 alloc_err:
1454 1454 if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) {
1455 1455 dev->cookie = 0;
1456 1456 }
1457 1457 return (ret);
1458 1458 }
↓ open down ↓ |
1312 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX