]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/oce/oce_mbox.c
Upgrade Unbound to 1.6.0. More to follow.
[FreeBSD/FreeBSD.git] / sys / dev / oce / oce_mbox.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (C) 2013 Emulex
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  *    this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Emulex Corporation nor the names of its
18  *    contributors may be used to endorse or promote products derived from
19  *    this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Contact Information:
34  * freebsd-drivers@emulex.com
35  *
36  * Emulex
37  * 3333 Susan Street
38  * Costa Mesa, CA 92626
39  */
40
41 /* $FreeBSD$ */
42
43 #include "oce_if.h"
44 extern uint32_t sfp_vpd_dump_buffer[TRANSCEIVER_DATA_NUM_ELE];
45
46 int
47 oce_wait_ready(POCE_SOFTC sc)
48 {
49 #define SLIPORT_READY_TIMEOUT 30000
50         uint32_t sliport_status, i;
51
52         if (!IS_XE201(sc)) 
53                 return (-1);
54
55         for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
56                 sliport_status = OCE_READ_REG32(sc, db, SLIPORT_STATUS_OFFSET);
57                 if (sliport_status & SLIPORT_STATUS_RDY_MASK)
58                         return 0;
59
60                 if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
61                         !(sliport_status & SLIPORT_STATUS_RN_MASK)) {
62                         device_printf(sc->dev, "Error detected in the card\n");
63                         return EIO;
64                 }
65
66                 DELAY(1000);
67         }
68
69         device_printf(sc->dev, "Firmware wait timed out\n");
70
71         return (-1);
72 }
73
74 /**
75  * @brief Reset (firmware) common function
76  * @param sc            software handle to the device
77  * @returns             0 on success, ETIMEDOUT on failure
78  */
79 int
80 oce_reset_fun(POCE_SOFTC sc)
81 {
82         struct oce_mbx *mbx;
83         struct oce_bmbx *mb;
84         struct ioctl_common_function_reset *fwcmd;
85         int rc = 0;
86
87         if (IS_XE201(sc)) {
88                 OCE_WRITE_REG32(sc, db, SLIPORT_CONTROL_OFFSET,
89                                         SLI_PORT_CONTROL_IP_MASK);
90
91                 rc = oce_wait_ready(sc);
92                 if (rc) {
93                         device_printf(sc->dev, "Firmware reset Failed\n");
94                 }
95
96                 return rc;
97         }
98
99         mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
100         mbx = &mb->mbx;
101         bzero(mbx, sizeof(struct oce_mbx));
102
103         fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
104         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
105                         MBX_SUBSYSTEM_COMMON,
106                         OPCODE_COMMON_FUNCTION_RESET,
107                         10,     /* MBX_TIMEOUT_SEC */
108                         sizeof(struct
109                                 ioctl_common_function_reset),
110                         OCE_MBX_VER_V0);
111
112         mbx->u0.s.embedded = 1;
113         mbx->payload_length =
114                 sizeof(struct ioctl_common_function_reset);
115
116         rc = oce_mbox_dispatch(sc, 2);
117
118         return rc;
119 }
120
121
122 /**
123  * @brief               This funtions tells firmware we are
124  *                      done with commands.
125  * @param sc            software handle to the device
126  * @returns             0 on success, ETIMEDOUT on failure
127  */
128 int
129 oce_fw_clean(POCE_SOFTC sc)
130 {
131         struct oce_bmbx *mbx;
132         uint8_t *ptr;
133         int ret = 0;
134
135         mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
136         ptr = (uint8_t *) &mbx->mbx;
137
138         /* Endian Signature */
139         *ptr++ = 0xff;
140         *ptr++ = 0xaa;
141         *ptr++ = 0xbb;
142         *ptr++ = 0xff;
143         *ptr++ = 0xff;
144         *ptr++ = 0xcc;
145         *ptr++ = 0xdd;
146         *ptr = 0xff;
147
148         ret = oce_mbox_dispatch(sc, 2);
149         
150         return ret;
151 }
152
153
154 /**
155  * @brief Mailbox wait
156  * @param sc            software handle to the device
157  * @param tmo_sec       timeout in seconds
158  */
159 static int
160 oce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
161 {
162         tmo_sec *= 10000;
163         pd_mpu_mbox_db_t mbox_db;
164
165         for (;;) {
166                 if (tmo_sec != 0) {
167                         if (--tmo_sec == 0)
168                                 break;
169                 }
170
171                 mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
172
173                 if (mbox_db.bits.ready)
174                         return 0;
175
176                 DELAY(100);
177         }
178
179         device_printf(sc->dev, "Mailbox timed out\n");
180
181         return ETIMEDOUT;
182 }
183
184
185 /**
186  * @brief Mailbox dispatch
187  * @param sc            software handle to the device
188  * @param tmo_sec       timeout in seconds
189  */
190 int
191 oce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
192 {
193         pd_mpu_mbox_db_t mbox_db;
194         uint32_t pa;
195         int rc;
196
197         oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
198         pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
199         bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
200         mbox_db.bits.ready = 0;
201         mbox_db.bits.hi = 1;
202         mbox_db.bits.address = pa;
203
204         rc = oce_mbox_wait(sc, tmo_sec);
205         if (rc == 0) {
206                 OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
207
208                 pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
209                 mbox_db.bits.ready = 0;
210                 mbox_db.bits.hi = 0;
211                 mbox_db.bits.address = pa;
212
213                 rc = oce_mbox_wait(sc, tmo_sec);
214
215                 if (rc == 0) {
216                         OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
217
218                         rc = oce_mbox_wait(sc, tmo_sec);
219
220                         oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
221                 }
222         }
223
224         return rc;
225 }
226
227
228
229 /**
230  * @brief               Mailbox common request header initialization
231  * @param hdr           mailbox header
232  * @param dom           domain
233  * @param port          port
234  * @param subsys        subsystem
235  * @param opcode        opcode
236  * @param timeout       timeout
237  * @param pyld_len      payload length
238  */
239 void
240 mbx_common_req_hdr_init(struct mbx_hdr *hdr,
241                         uint8_t dom, uint8_t port,
242                         uint8_t subsys, uint8_t opcode,
243                         uint32_t timeout, uint32_t pyld_len,
244                         uint8_t version)
245 {
246         hdr->u0.req.opcode = opcode;
247         hdr->u0.req.subsystem = subsys;
248         hdr->u0.req.port_number = port;
249         hdr->u0.req.domain = dom;
250
251         hdr->u0.req.timeout = timeout;
252         hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
253         hdr->u0.req.version = version;
254 }
255
256
257
258 /**
259  * @brief Function to initialize the hw with host endian information
260  * @param sc            software handle to the device
261  * @returns             0 on success, ETIMEDOUT on failure
262  */
263 int
264 oce_mbox_init(POCE_SOFTC sc)
265 {
266         struct oce_bmbx *mbx;
267         uint8_t *ptr;
268         int ret = 0;
269
270         if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
271                 mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
272                 ptr = (uint8_t *) &mbx->mbx;
273
274                 /* Endian Signature */
275                 *ptr++ = 0xff;
276                 *ptr++ = 0x12;
277                 *ptr++ = 0x34;
278                 *ptr++ = 0xff;
279                 *ptr++ = 0xff;
280                 *ptr++ = 0x56;
281                 *ptr++ = 0x78;
282                 *ptr = 0xff;
283
284                 ret = oce_mbox_dispatch(sc, 0);
285         }
286         
287         return ret;
288 }
289
290
291 /**
292  * @brief               Function to get the firmware version
293  * @param sc            software handle to the device
294  * @returns             0 on success, EIO on failure
295  */
296 int
297 oce_get_fw_version(POCE_SOFTC sc)
298 {
299         struct oce_mbx mbx;
300         struct mbx_get_common_fw_version *fwcmd;
301         int ret = 0;
302
303         bzero(&mbx, sizeof(struct oce_mbx));
304
305         fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
306         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
307                                 MBX_SUBSYSTEM_COMMON,
308                                 OPCODE_COMMON_GET_FW_VERSION,
309                                 MBX_TIMEOUT_SEC,
310                                 sizeof(struct mbx_get_common_fw_version),
311                                 OCE_MBX_VER_V0);
312
313         mbx.u0.s.embedded = 1;
314         mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
315         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
316
317         ret = oce_mbox_post(sc, &mbx, NULL);
318         if (!ret)
319                 ret = fwcmd->hdr.u0.rsp.status;
320         if (ret) {
321                 device_printf(sc->dev,
322                               "%s failed - cmd status: %d addi status: %d\n",
323                               __FUNCTION__, ret,
324                               fwcmd->hdr.u0.rsp.additional_status);
325                 goto error;
326         }
327
328         bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
329 error:
330         return ret;
331 }
332
333
334 /**
335  * @brief       Firmware will send gracious notifications during
336  *              attach only after sending first mcc commnad. We  
337  *              use MCC queue only for getting async and mailbox
338  *              for sending cmds. So to get gracious notifications
339  *              atleast send one dummy command on mcc.
340  */
341 int 
342 oce_first_mcc_cmd(POCE_SOFTC sc)
343 {
344         struct oce_mbx *mbx;
345         struct oce_mq *mq = sc->mq;
346         struct mbx_get_common_fw_version *fwcmd;
347         uint32_t reg_value;
348
349         mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
350         bzero(mbx, sizeof(struct oce_mbx));
351         
352         fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload;
353         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
354                                 MBX_SUBSYSTEM_COMMON,
355                                 OPCODE_COMMON_GET_FW_VERSION,
356                                 MBX_TIMEOUT_SEC,
357                                 sizeof(struct mbx_get_common_fw_version),
358                                 OCE_MBX_VER_V0);
359         mbx->u0.s.embedded = 1;
360         mbx->payload_length = sizeof(struct mbx_get_common_fw_version);
361         bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map,
362                                 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
363         RING_PUT(mq->ring, 1);
364         reg_value = (1 << 16) | mq->mq_id;
365         OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value);
366
367         return 0;
368 }
369
370 /**
371  * @brief               Function to post a MBX to the mbox
372  * @param sc            software handle to the device
373  * @param mbx           pointer to the MBX to send
374  * @param mbxctx        pointer to the mbx context structure
375  * @returns             0 on success, error on failure
376  */
377 int
378 oce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
379 {
380         struct oce_mbx *mb_mbx = NULL;
381         struct oce_mq_cqe *mb_cqe = NULL;
382         struct oce_bmbx *mb = NULL;
383         int rc = 0;
384         uint32_t tmo = 0;
385         uint32_t cstatus = 0;
386         uint32_t xstatus = 0;
387
388         LOCK(&sc->bmbx_lock);
389
390         mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
391         mb_mbx = &mb->mbx;
392
393         /* get the tmo */
394         tmo = mbx->tag[0];
395         mbx->tag[0] = 0;
396
397         /* copy mbx into mbox */
398         bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
399
400         /* now dispatch */
401         rc = oce_mbox_dispatch(sc, tmo);
402         if (rc == 0) {
403                 /*
404                  * the command completed successfully. Now get the
405                  * completion queue entry
406                  */
407                 mb_cqe = &mb->cqe;
408                 DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
409         
410                 /* copy mbox mbx back */
411                 bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
412
413                 /* pick up the mailbox status */
414                 cstatus = mb_cqe->u0.s.completion_status;
415                 xstatus = mb_cqe->u0.s.extended_status;
416
417                 /*
418                  * store the mbx context in the cqe tag section so that
419                  * the upper layer handling the cqe can associate the mbx
420                  * with the response
421                  */
422                 if (cstatus == 0 && mbxctx) {
423                         /* save context */
424                         mbxctx->mbx = mb_mbx;
425                         bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
426                                 sizeof(struct oce_mbx_ctx *));
427                 }
428         }
429
430         UNLOCK(&sc->bmbx_lock);
431
432         return rc;
433 }
434
435 /**
436  * @brief Function to read the mac address associated with an interface
437  * @param sc            software handle to the device
438  * @param if_id         interface id to read the address from
439  * @param perm          set to 1 if reading the factory mac address.
440  *                      In this case if_id is ignored
441  * @param type          type of the mac address, whether network or storage
442  * @param[out] mac      [OUTPUT] pointer to a buffer containing the
443  *                      mac address when the command succeeds.
444  * @returns             0 on success, EIO on failure
445  */
446 int
447 oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
448                 uint8_t perm, uint8_t type, struct mac_address_format *mac)
449 {
450         struct oce_mbx mbx;
451         struct mbx_query_common_iface_mac *fwcmd;
452         int ret = 0;
453
454         bzero(&mbx, sizeof(struct oce_mbx));
455
456         fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
457         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
458                                 MBX_SUBSYSTEM_COMMON,
459                                 OPCODE_COMMON_QUERY_IFACE_MAC,
460                                 MBX_TIMEOUT_SEC,
461                                 sizeof(struct mbx_query_common_iface_mac),
462                                 OCE_MBX_VER_V0);
463
464         fwcmd->params.req.permanent = perm;
465         if (!perm)
466                 fwcmd->params.req.if_id = (uint16_t) if_id;
467         else
468                 fwcmd->params.req.if_id = 0;
469
470         fwcmd->params.req.type = type;
471
472         mbx.u0.s.embedded = 1;
473         mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
474         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
475
476         ret = oce_mbox_post(sc, &mbx, NULL);
477         if (!ret)
478                 ret = fwcmd->hdr.u0.rsp.status;
479         if (ret) {
480                 device_printf(sc->dev,
481                               "%s failed - cmd status: %d addi status: %d\n",
482                               __FUNCTION__, ret,
483                               fwcmd->hdr.u0.rsp.additional_status);
484                 goto error;
485         }
486
487         /* copy the mac addres in the output parameter */
488         mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
489         bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
490                 mac->size_of_struct);
491 error:
492         return ret;
493 }
494
495 /**
496  * @brief Function to query the fw attributes from the hw
497  * @param sc            software handle to the device
498  * @returns             0 on success, EIO on failure
499  */
500 int 
501 oce_get_fw_config(POCE_SOFTC sc)
502 {
503         struct oce_mbx mbx;
504         struct mbx_common_query_fw_config *fwcmd;
505         int ret = 0;
506
507         bzero(&mbx, sizeof(struct oce_mbx));
508
509         fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
510         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
511                                 MBX_SUBSYSTEM_COMMON,
512                                 OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
513                                 MBX_TIMEOUT_SEC,
514                                 sizeof(struct mbx_common_query_fw_config),
515                                 OCE_MBX_VER_V0);
516
517         mbx.u0.s.embedded = 1;
518         mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
519         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
520
521         ret = oce_mbox_post(sc, &mbx, NULL);
522         if (!ret)
523                 ret = fwcmd->hdr.u0.rsp.status;
524         if (ret) {
525                 device_printf(sc->dev,
526                               "%s failed - cmd status: %d addi status: %d\n",
527                               __FUNCTION__, ret,
528                               fwcmd->hdr.u0.rsp.additional_status);
529                 goto error;
530         }
531
532         DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
533
534         sc->config_number = HOST_32(fwcmd->params.rsp.config_number);
535         sc->asic_revision = HOST_32(fwcmd->params.rsp.asic_revision);
536         sc->port_id       = HOST_32(fwcmd->params.rsp.port_id);
537         sc->function_mode = HOST_32(fwcmd->params.rsp.function_mode);
538         if ((sc->function_mode & (ULP_NIC_MODE | ULP_RDMA_MODE)) ==
539             (ULP_NIC_MODE | ULP_RDMA_MODE)) {
540           sc->rdma_flags = OCE_RDMA_FLAG_SUPPORTED;
541         }
542         sc->function_caps = HOST_32(fwcmd->params.rsp.function_caps);
543
544         if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
545                 sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[0].nic_wq_tot);
546                 sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[0].lro_rqid_tot);
547         } else {
548                 sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[1].nic_wq_tot);
549                 sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[1].lro_rqid_tot);
550         }
551         
552 error:
553         return ret;
554
555 }
556
557 /**
558  *
559  * @brief function to create a device interface 
560  * @param sc            software handle to the device
561  * @param cap_flags     capability flags
562  * @param en_flags      enable capability flags
563  * @param vlan_tag      optional vlan tag to associate with the if
564  * @param mac_addr      pointer to a buffer containing the mac address
565  * @param[out] if_id    [OUTPUT] pointer to an integer to hold the ID of the
566  interface created
567  * @returns             0 on success, EIO on failure
568  */
569 int
570 oce_if_create(POCE_SOFTC sc,
571                 uint32_t cap_flags,
572                 uint32_t en_flags,
573                 uint16_t vlan_tag,
574                 uint8_t *mac_addr,
575                 uint32_t *if_id)
576 {
577         struct oce_mbx mbx;
578         struct mbx_create_common_iface *fwcmd;
579         int rc = 0;
580
581         bzero(&mbx, sizeof(struct oce_mbx));
582
583         fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
584         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
585                                 MBX_SUBSYSTEM_COMMON,
586                                 OPCODE_COMMON_CREATE_IFACE,
587                                 MBX_TIMEOUT_SEC,
588                                 sizeof(struct mbx_create_common_iface),
589                                 OCE_MBX_VER_V0);
590         DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
591
592         fwcmd->params.req.version = 0;
593         fwcmd->params.req.cap_flags = LE_32(cap_flags);
594         fwcmd->params.req.enable_flags = LE_32(en_flags);
595         if (mac_addr != NULL) {
596                 bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
597                 fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
598                 fwcmd->params.req.mac_invalid = 0;
599         } else {
600                 fwcmd->params.req.mac_invalid = 1;
601         }
602
603         mbx.u0.s.embedded = 1;
604         mbx.payload_length = sizeof(struct mbx_create_common_iface);
605         DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
606
607         rc = oce_mbox_post(sc, &mbx, NULL);
608         if (!rc)
609                 rc = fwcmd->hdr.u0.rsp.status;
610         if (rc) {
611                 device_printf(sc->dev,
612                               "%s failed - cmd status: %d addi status: %d\n",
613                               __FUNCTION__, rc,
614                               fwcmd->hdr.u0.rsp.additional_status);
615                 goto error;
616         }
617
618         *if_id = HOST_32(fwcmd->params.rsp.if_id);
619
620         if (mac_addr != NULL)
621                 sc->pmac_id = HOST_32(fwcmd->params.rsp.pmac_id);
622 error:
623         return rc;
624 }
625
626 /**
627  * @brief               Function to delete an interface
628  * @param sc            software handle to the device
629  * @param if_id         ID of the interface to delete
630  * @returns             0 on success, EIO on failure
631  */
632 int
633 oce_if_del(POCE_SOFTC sc, uint32_t if_id)
634 {
635         struct oce_mbx mbx;
636         struct mbx_destroy_common_iface *fwcmd;
637         int rc = 0;
638
639         bzero(&mbx, sizeof(struct oce_mbx));
640
641         fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
642         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
643                                 MBX_SUBSYSTEM_COMMON,
644                                 OPCODE_COMMON_DESTROY_IFACE,
645                                 MBX_TIMEOUT_SEC,
646                                 sizeof(struct mbx_destroy_common_iface),
647                                 OCE_MBX_VER_V0);
648
649         fwcmd->params.req.if_id = if_id;
650
651         mbx.u0.s.embedded = 1;
652         mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
653         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
654
655         rc = oce_mbox_post(sc, &mbx, NULL);
656         if (!rc)
657                 rc = fwcmd->hdr.u0.rsp.status;
658         if (rc)
659                 device_printf(sc->dev,
660                               "%s failed - cmd status: %d addi status: %d\n",
661                               __FUNCTION__, rc,
662                               fwcmd->hdr.u0.rsp.additional_status);
663         return rc;
664 }
665
666 /**
667  * @brief Function to send the mbx command to configure vlan
668  * @param sc            software handle to the device
669  * @param if_id         interface identifier index
670  * @param vtag_arr      array of vlan tags
671  * @param vtag_cnt      number of elements in array
672  * @param untagged      boolean TRUE/FLASE
673  * @param enable_promisc flag to enable/disable VLAN promiscuous mode
674  * @returns             0 on success, EIO on failure
675  */
676 int
677 oce_config_vlan(POCE_SOFTC sc,
678                 uint32_t if_id,
679                 struct normal_vlan *vtag_arr,
680                 uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
681 {
682         struct oce_mbx mbx;
683         struct mbx_common_config_vlan *fwcmd;
684         int rc = 0;
685
686         if (sc->vlans_added > sc->max_vlans)
687                 goto vlan_promisc;
688
689         bzero(&mbx, sizeof(struct oce_mbx));
690         fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
691
692         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
693                                 MBX_SUBSYSTEM_COMMON,
694                                 OPCODE_COMMON_CONFIG_IFACE_VLAN,
695                                 MBX_TIMEOUT_SEC,
696                                 sizeof(struct mbx_common_config_vlan),
697                                 OCE_MBX_VER_V0);
698
699         fwcmd->params.req.if_id = (uint8_t) if_id;
700         fwcmd->params.req.promisc = (uint8_t) enable_promisc;
701         fwcmd->params.req.untagged = (uint8_t) untagged;
702         fwcmd->params.req.num_vlans = vtag_cnt;
703
704         if (!enable_promisc) {
705                 bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
706                         vtag_cnt * sizeof(struct normal_vlan));
707         }
708         mbx.u0.s.embedded = 1;
709         mbx.payload_length = sizeof(struct mbx_common_config_vlan);
710         DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
711
712         rc = oce_mbox_post(sc, &mbx, NULL);
713         if (!rc)
714                 rc = fwcmd->hdr.u0.rsp.status;
715         if (rc)
716                 device_printf(sc->dev,
717                               "%s failed - cmd status: %d addi status: %d\n",
718                               __FUNCTION__, rc,
719                               fwcmd->hdr.u0.rsp.additional_status);
720
721         goto done;
722
723 vlan_promisc:
724         /* Enable Vlan Promis */
725         oce_rxf_set_promiscuous(sc, (1 << 1));
726         device_printf(sc->dev,"Enabling Vlan Promisc Mode\n");
727 done:
728         return rc;
729
730 }
731
732 /**
733  * @brief Function to set flow control capability in the hardware
734  * @param sc            software handle to the device
735  * @param flow_control  flow control flags to set
736  * @returns             0 on success, EIO on failure
737  */
738 int
739 oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
740 {
741         struct oce_mbx mbx;
742         struct mbx_common_get_set_flow_control *fwcmd =
743                 (struct mbx_common_get_set_flow_control *)&mbx.payload;
744         int rc;
745
746         bzero(&mbx, sizeof(struct oce_mbx));
747
748         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
749                                 MBX_SUBSYSTEM_COMMON,
750                                 OPCODE_COMMON_SET_FLOW_CONTROL,
751                                 MBX_TIMEOUT_SEC,
752                                 sizeof(struct mbx_common_get_set_flow_control),
753                                 OCE_MBX_VER_V0);
754
755         if (flow_control & OCE_FC_TX)
756                 fwcmd->tx_flow_control = 1;
757
758         if (flow_control & OCE_FC_RX)
759                 fwcmd->rx_flow_control = 1;
760
761         mbx.u0.s.embedded = 1;
762         mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
763         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
764
765         rc = oce_mbox_post(sc, &mbx, NULL);
766         if (!rc)
767                 rc = fwcmd->hdr.u0.rsp.status;
768         if (rc)
769                 device_printf(sc->dev,
770                               "%s failed - cmd status: %d addi status: %d\n",
771                               __FUNCTION__, rc,
772                               fwcmd->hdr.u0.rsp.additional_status);
773         return rc;
774 }
775
776 /**
777  * @brief Initialize the RSS CPU indirection table
778  *
779  * The table is used to choose the queue to place the incomming packets.
780  * Incomming packets are hashed.  The lowest bits in the hash result
781  * are used as the index into the CPU indirection table.
782  * Each entry in the table contains the RSS CPU-ID returned by the NIC
783  * create.  Based on the CPU ID, the receive completion is routed to
784  * the corresponding RSS CQs.  (Non-RSS packets are always completed
785  * on the default (0) CQ).
786  *
787  * @param sc            software handle to the device
788  * @param *fwcmd        pointer to the rss mbox command
789  * @returns             none
790  */
791 static int
792 oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
793 {
794         int i = 0, j = 0, rc = 0;
795         uint8_t *tbl = fwcmd->params.req.cputable;
796         struct oce_rq *rq = NULL;
797
798
799         for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) {
800                 for_all_rss_queues(sc, rq, i) {
801                         if ((j + i) >= INDIRECTION_TABLE_ENTRIES)
802                                 break;
803                         tbl[j + i] = rq->rss_cpuid;
804                 }
805         }
806         if (i == 0) {
807                 device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
808                 rc = ENXIO;
809
810         } 
811         
812         /* fill log2 value indicating the size of the CPU table */
813         if (rc == 0)
814                 fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(INDIRECTION_TABLE_ENTRIES));
815
816         return rc;
817 }
818
819 /**
820  * @brief Function to set flow control capability in the hardware
821  * @param sc            software handle to the device
822  * @param if_id         interface id to read the address from
823  * @param enable_rss    0=disable, RSS_ENABLE_xxx flags otherwise
824  * @returns             0 on success, EIO on failure
825  */
826 int
827 oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
828 {
829         int rc;
830         struct oce_mbx mbx;
831         struct mbx_config_nic_rss *fwcmd =
832                                 (struct mbx_config_nic_rss *)&mbx.payload;
833         int version;
834
835         bzero(&mbx, sizeof(struct oce_mbx));
836
837         if (IS_XE201(sc) || IS_SH(sc)) {
838                 version = OCE_MBX_VER_V1;
839                 fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
840                                                RSS_ENABLE_UDP_IPV6;
841         } else
842                 version = OCE_MBX_VER_V0; 
843
844         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
845                                 MBX_SUBSYSTEM_NIC,
846                                 NIC_CONFIG_RSS,
847                                 MBX_TIMEOUT_SEC,
848                                 sizeof(struct mbx_config_nic_rss),
849                                 version);
850         if (enable_rss)
851                 fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 |
852                                                  RSS_ENABLE_TCP_IPV4 |
853                                                  RSS_ENABLE_IPV6 |
854                                                  RSS_ENABLE_TCP_IPV6);
855
856         if(!sc->enable_hwlro) 
857                 fwcmd->params.req.flush = OCE_FLUSH;
858         else
859                 fwcmd->params.req.flush = 0;
860
861         fwcmd->params.req.if_id = LE_32(if_id);
862
863         srandom(arc4random());  /* random entropy seed */
864         read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
865         
866         rc = oce_rss_itbl_init(sc, fwcmd);
867         if (rc == 0) {
868                 mbx.u0.s.embedded = 1;
869                 mbx.payload_length = sizeof(struct mbx_config_nic_rss);
870                 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
871
872                 rc = oce_mbox_post(sc, &mbx, NULL);
873                 if (!rc)
874                         rc = fwcmd->hdr.u0.rsp.status;
875                 if (rc)
876                 device_printf(sc->dev,
877                               "%s failed - cmd status: %d addi status: %d\n",
878                               __FUNCTION__, rc,
879                               fwcmd->hdr.u0.rsp.additional_status);
880         }
881         return rc;
882 }
883
884 /**
885  * @brief               RXF function to enable/disable device promiscuous mode
886  * @param sc            software handle to the device
887  * @param enable        enable/disable flag
888  * @returns             0 on success, EIO on failure
889  * @note
890  *      The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
891  *      This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
892  */
893 int
894 oce_rxf_set_promiscuous(POCE_SOFTC sc, uint8_t enable)
895 {
896         struct mbx_set_common_iface_rx_filter *fwcmd;
897         int sz = sizeof(struct mbx_set_common_iface_rx_filter);
898         iface_rx_filter_ctx_t *req;
899         OCE_DMA_MEM sgl;
900         int rc;
901
902         /* allocate mbx payload's dma scatter/gather memory */
903         rc = oce_dma_alloc(sc, sz, &sgl, 0);
904         if (rc)
905                 return rc;
906
907         fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
908
909         req =  &fwcmd->params.req;
910         req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
911                                 MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
912         /* Bit 0 Mac promisc, Bit 1 Vlan promisc */
913         if (enable & 0x01)
914                 req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS;
915
916         if (enable & 0x02)
917                 req->iface_flags |= MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
918
919         req->if_id = sc->if_id;
920
921         rc = oce_set_common_iface_rx_filter(sc, &sgl);
922         oce_dma_free(sc, &sgl);
923         
924         return rc;
925 }
926
927
928 /**
929  * @brief                       Function modify and select rx filter options
930  * @param sc                    software handle to the device
931  * @param sgl                   scatter/gather request/response
932  * @returns                     0 on success, error code on failure
933  */
934 int
935 oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
936 {
937         struct oce_mbx mbx;
938         int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
939         struct mbx_set_common_iface_rx_filter *fwcmd;
940         int rc;
941
942         bzero(&mbx, sizeof(struct oce_mbx));
943         fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
944
945         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
946                                 MBX_SUBSYSTEM_COMMON,
947                                 OPCODE_COMMON_SET_IFACE_RX_FILTER,
948                                 MBX_TIMEOUT_SEC,
949                                 mbx_sz,
950                                 OCE_MBX_VER_V0);
951
952         oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
953         mbx.u0.s.embedded = 0;
954         mbx.u0.s.sge_count = 1;
955         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
956         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
957         mbx.payload.u0.u1.sgl[0].length = mbx_sz;
958         mbx.payload_length = mbx_sz;
959         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
960
961         rc = oce_mbox_post(sc, &mbx, NULL);
962         if (!rc)
963                 rc = fwcmd->hdr.u0.rsp.status;
964         if (rc)
965                 device_printf(sc->dev,
966                               "%s failed - cmd status: %d addi status: %d\n",
967                               __FUNCTION__, rc,
968                               fwcmd->hdr.u0.rsp.additional_status);
969         return rc;
970 }
971
972 /**
973  * @brief Function to query the link status from the hardware
974  * @param sc            software handle to the device
975  * @param[out] link     pointer to the structure returning link attributes
976  * @returns             0 on success, EIO on failure
977  */
978 int
979 oce_get_link_status(POCE_SOFTC sc, struct link_status *link)
980 {
981         struct oce_mbx mbx;
982         struct mbx_query_common_link_config *fwcmd;
983         int rc = 0, version;
984
985         bzero(&mbx, sizeof(struct oce_mbx));
986
987         IS_BE2(sc) ? (version = OCE_MBX_VER_V0) : (version = OCE_MBX_VER_V1);
988
989         fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
990         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
991                                 MBX_SUBSYSTEM_COMMON,
992                                 OPCODE_COMMON_QUERY_LINK_CONFIG,
993                                 MBX_TIMEOUT_SEC,
994                                 sizeof(struct mbx_query_common_link_config),
995                                 version);
996
997         mbx.u0.s.embedded = 1;
998         mbx.payload_length = sizeof(struct mbx_query_common_link_config);
999         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1000
1001         rc = oce_mbox_post(sc, &mbx, NULL);
1002
1003         if (!rc)
1004                 rc = fwcmd->hdr.u0.rsp.status;
1005         if (rc) {
1006                 device_printf(sc->dev,
1007                               "%s failed - cmd status: %d addi status: %d\n",
1008                               __FUNCTION__, rc,
1009                               fwcmd->hdr.u0.rsp.additional_status);
1010                 goto error;
1011         }
1012         /* interpret response */
1013         link->qos_link_speed = HOST_16(fwcmd->params.rsp.qos_link_speed);
1014         link->phys_port_speed = fwcmd->params.rsp.physical_port_speed;
1015         link->logical_link_status = fwcmd->params.rsp.logical_link_status;
1016 error:
1017         return rc;
1018 }
1019
1020
1021 /**
1022  * @brief Function to get NIC statistics
1023  * @param sc            software handle to the device
1024  * @param *stats        pointer to where to store statistics
1025  * @param reset_stats   resets statistics of set
1026  * @returns             0 on success, EIO on failure
1027  * @note                command depricated in Lancer
1028  */
1029 #define OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, version)                             \
1030 int                                                                                     \
1031 oce_mbox_get_nic_stats_v##version(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)           \
1032 {                                                                                       \
1033         struct oce_mbx mbx;                                                             \
1034         struct mbx_get_nic_stats_v##version *fwcmd;                                     \
1035         int rc = 0;                                                                     \
1036                                                                                         \
1037         bzero(&mbx, sizeof(struct oce_mbx));                                            \
1038         fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v##version);        \
1039         bzero(fwcmd, sizeof(*fwcmd));                                                   \
1040                                                                                         \
1041         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,                                      \
1042                                 MBX_SUBSYSTEM_NIC,                                      \
1043                                 NIC_GET_STATS,                                          \
1044                                 MBX_TIMEOUT_SEC,                                        \
1045                                 sizeof(*fwcmd),                                         \
1046                                 OCE_MBX_VER_V##version);                                \
1047                                                                                         \
1048         mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */              \
1049         mbx.u0.s.sge_count = 1; /* using scatter gather instead */                      \
1050                                                                                         \
1051         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);                             \
1052         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);                \
1053         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);                \
1054         mbx.payload.u0.u1.sgl[0].length = sizeof(*fwcmd);                               \
1055         mbx.payload_length = sizeof(*fwcmd);                                            \
1056         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);                   \
1057                                                                                         \
1058         rc = oce_mbox_post(sc, &mbx, NULL);                                             \
1059         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);                            \
1060         if (!rc)                                                                        \
1061                 rc = fwcmd->hdr.u0.rsp.status;                                          \
1062         if (rc)                                                                         \
1063                 device_printf(sc->dev,                                                  \
1064                               "%s failed - cmd status: %d addi status: %d\n",           \
1065                               __FUNCTION__, rc,                                         \
1066                               fwcmd->hdr.u0.rsp.additional_status);                     \
1067         return rc;                                                                      \
1068 }
1069
1070 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 0);
1071 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 1);
1072 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 2);
1073
1074
1075 /**
1076  * @brief Function to get pport (physical port) statistics
1077  * @param sc            software handle to the device
1078  * @param *stats        pointer to where to store statistics
1079  * @param reset_stats   resets statistics of set
1080  * @returns             0 on success, EIO on failure
1081  */
1082 int
1083 oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1084                                 uint32_t reset_stats)
1085 {
1086         struct oce_mbx mbx;
1087         struct mbx_get_pport_stats *fwcmd;
1088         int rc = 0;
1089
1090         bzero(&mbx, sizeof(struct oce_mbx));
1091         fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
1092         bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
1093
1094         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1095                                 MBX_SUBSYSTEM_NIC,
1096                                 NIC_GET_PPORT_STATS,
1097                                 MBX_TIMEOUT_SEC,
1098                                 sizeof(struct mbx_get_pport_stats),
1099                                 OCE_MBX_VER_V0);
1100
1101         fwcmd->params.req.reset_stats = reset_stats;
1102         fwcmd->params.req.port_number = sc->port_id;
1103         
1104         mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
1105         mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1106
1107         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1108         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1109         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1110         mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
1111
1112         mbx.payload_length = sizeof(struct mbx_get_pport_stats);
1113         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1114
1115         rc = oce_mbox_post(sc, &mbx, NULL);
1116         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1117
1118         if (!rc)
1119                 rc = fwcmd->hdr.u0.rsp.status;
1120         if (rc)
1121                 device_printf(sc->dev,
1122                               "%s failed - cmd status: %d addi status: %d\n",
1123                               __FUNCTION__, rc,
1124                               fwcmd->hdr.u0.rsp.additional_status);
1125         return rc;
1126 }
1127
1128
1129 /**
1130  * @brief Function to get vport (virtual port) statistics
1131  * @param sc            software handle to the device
1132  * @param *stats        pointer to where to store statistics
1133  * @param reset_stats   resets statistics of set
1134  * @returns             0 on success, EIO on failure
1135  */
1136 int
1137 oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1138                                 uint32_t req_size, uint32_t reset_stats)
1139 {
1140         struct oce_mbx mbx;
1141         struct mbx_get_vport_stats *fwcmd;
1142         int rc = 0;
1143
1144         bzero(&mbx, sizeof(struct oce_mbx));
1145
1146         fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
1147         bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
1148
1149         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1150                                 MBX_SUBSYSTEM_NIC,
1151                                 NIC_GET_VPORT_STATS,
1152                                 MBX_TIMEOUT_SEC,
1153                                 sizeof(struct mbx_get_vport_stats),
1154                                 OCE_MBX_VER_V0);
1155
1156         fwcmd->params.req.reset_stats = reset_stats;
1157         fwcmd->params.req.vport_number = sc->if_id;
1158         
1159         mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
1160         mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1161
1162         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1163         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1164         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1165         mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
1166
1167         mbx.payload_length = sizeof(struct mbx_get_vport_stats);
1168         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1169
1170         rc = oce_mbox_post(sc, &mbx, NULL);
1171         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1172
1173         if (!rc)
1174                 rc = fwcmd->hdr.u0.rsp.status;
1175         if (rc)
1176                 device_printf(sc->dev,
1177                               "%s failed - cmd status: %d addi status: %d\n",
1178                               __FUNCTION__, rc,
1179                               fwcmd->hdr.u0.rsp.additional_status);
1180         return rc;
1181 }
1182
1183
1184 /**
1185  * @brief               Function to update the muticast filter with 
1186  *                      values in dma_mem 
1187  * @param sc            software handle to the device
1188  * @param dma_mem       pointer to dma memory region
1189  * @returns             0 on success, EIO on failure
1190  */
1191 int
1192 oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
1193 {
1194         struct oce_mbx mbx;
1195         struct oce_mq_sge *sgl;
1196         struct mbx_set_common_iface_multicast *req = NULL;
1197         int rc = 0;
1198
1199         req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
1200         mbx_common_req_hdr_init(&req->hdr, 0, 0,
1201                                 MBX_SUBSYSTEM_COMMON,
1202                                 OPCODE_COMMON_SET_IFACE_MULTICAST,
1203                                 MBX_TIMEOUT_SEC,
1204                                 sizeof(struct mbx_set_common_iface_multicast),
1205                                 OCE_MBX_VER_V0);
1206
1207         bzero(&mbx, sizeof(struct oce_mbx));
1208
1209         mbx.u0.s.embedded = 0; /*Non embeded*/
1210         mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
1211         mbx.u0.s.sge_count = 1;
1212         sgl = &mbx.payload.u0.u1.sgl[0];
1213         sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
1214         sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
1215         sgl->length = htole32(mbx.payload_length);
1216
1217         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1218
1219         rc = oce_mbox_post(sc, &mbx, NULL);
1220         if (!rc)
1221                 rc = req->hdr.u0.rsp.status;
1222         if (rc)
1223                 device_printf(sc->dev,
1224                               "%s failed - cmd status: %d addi status: %d\n",
1225                               __FUNCTION__, rc,
1226                               req->hdr.u0.rsp.additional_status);
1227         return rc;
1228 }
1229
1230
1231 /**
1232  * @brief               Function to send passthrough Ioctls
1233  * @param sc            software handle to the device
1234  * @param dma_mem       pointer to dma memory region
1235  * @param req_size      size of dma_mem
1236  * @returns             0 on success, EIO on failure
1237  */
1238 int
1239 oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
1240 {
1241         struct oce_mbx mbx;
1242         struct oce_mq_sge *sgl;
1243         int rc = 0;
1244
1245         bzero(&mbx, sizeof(struct oce_mbx));
1246
1247         mbx.u0.s.embedded  = 0; /*Non embeded*/
1248         mbx.payload_length = req_size;
1249         mbx.u0.s.sge_count = 1;
1250         sgl = &mbx.payload.u0.u1.sgl[0];
1251         sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
1252         sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
1253         sgl->length = htole32(req_size);
1254
1255         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1256
1257         rc = oce_mbox_post(sc, &mbx, NULL);
1258         return rc;
1259 }
1260
1261
1262 int
1263 oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
1264                  uint32_t if_id, uint32_t *pmac_id)
1265 {
1266         struct oce_mbx mbx;
1267         struct mbx_add_common_iface_mac *fwcmd;
1268         int rc = 0;
1269
1270         bzero(&mbx, sizeof(struct oce_mbx));
1271
1272         fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1273         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1274                                 MBX_SUBSYSTEM_COMMON,
1275                                 OPCODE_COMMON_ADD_IFACE_MAC,
1276                                 MBX_TIMEOUT_SEC,
1277                                 sizeof(struct mbx_add_common_iface_mac),
1278                                 OCE_MBX_VER_V0);
1279                                 
1280         fwcmd->params.req.if_id = (uint16_t) if_id;
1281         bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
1282
1283         mbx.u0.s.embedded = 1;
1284         mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
1285         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1286         rc = oce_mbox_post(sc, &mbx, NULL);
1287         if (!rc)
1288                 rc = fwcmd->hdr.u0.rsp.status;
1289         if (rc) {
1290                 device_printf(sc->dev,
1291                               "%s failed - cmd status: %d addi status: %d\n",
1292                               __FUNCTION__, rc,
1293                               fwcmd->hdr.u0.rsp.additional_status);
1294                 goto error;
1295         }
1296         *pmac_id = fwcmd->params.rsp.pmac_id;
1297 error:
1298         return rc;
1299 }
1300
1301
1302 int
1303 oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
1304 {
1305         struct oce_mbx mbx;
1306         struct mbx_del_common_iface_mac *fwcmd;
1307         int rc = 0;
1308
1309         bzero(&mbx, sizeof(struct oce_mbx));
1310
1311         fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1312         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1313                                 MBX_SUBSYSTEM_COMMON,
1314                                 OPCODE_COMMON_DEL_IFACE_MAC,
1315                                 MBX_TIMEOUT_SEC,
1316                                 sizeof(struct mbx_del_common_iface_mac),
1317                                 OCE_MBX_VER_V0);
1318
1319         fwcmd->params.req.if_id = (uint16_t)if_id;
1320         fwcmd->params.req.pmac_id = pmac_id;
1321
1322         mbx.u0.s.embedded = 1;
1323         mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
1324         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1325
1326         rc = oce_mbox_post(sc, &mbx, NULL);
1327         if (!rc)
1328                 rc = fwcmd->hdr.u0.rsp.status;
1329         if (rc)
1330                 device_printf(sc->dev,
1331                               "%s failed - cmd status: %d addi status: %d\n",
1332                               __FUNCTION__, rc,
1333                               fwcmd->hdr.u0.rsp.additional_status);
1334         return rc;
1335 }
1336
1337
1338
1339 int
1340 oce_mbox_check_native_mode(POCE_SOFTC sc)
1341 {
1342         struct oce_mbx mbx;
1343         struct mbx_common_set_function_cap *fwcmd;
1344         int rc = 0;
1345
1346         bzero(&mbx, sizeof(struct oce_mbx));
1347
1348         fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
1349         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1350                                 MBX_SUBSYSTEM_COMMON,
1351                                 OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
1352                                 MBX_TIMEOUT_SEC,
1353                                 sizeof(struct mbx_common_set_function_cap),
1354                                 OCE_MBX_VER_V0);
1355
1356         fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS | 
1357                                                         CAP_BE3_NATIVE_ERX_API;
1358
1359         fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
1360
1361         mbx.u0.s.embedded = 1;
1362         mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
1363         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1364
1365         rc = oce_mbox_post(sc, &mbx, NULL);
1366         if (!rc)
1367                 rc = fwcmd->hdr.u0.rsp.status;
1368         if (rc) {
1369                 device_printf(sc->dev,
1370                               "%s failed - cmd status: %d addi status: %d\n",
1371                               __FUNCTION__, rc,
1372                               fwcmd->hdr.u0.rsp.additional_status);
1373                 goto error;
1374         }
1375         sc->be3_native = HOST_32(fwcmd->params.rsp.capability_flags)
1376                         & CAP_BE3_NATIVE_ERX_API;
1377
1378 error:
1379         return 0;
1380 }
1381
1382
1383
1384 int
1385 oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
1386                 uint8_t loopback_type, uint8_t enable)
1387 {
1388         struct oce_mbx mbx;
1389         struct mbx_lowlevel_set_loopback_mode *fwcmd;
1390         int rc = 0;
1391
1392
1393         bzero(&mbx, sizeof(struct oce_mbx));
1394
1395         fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
1396         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1397                                 MBX_SUBSYSTEM_LOWLEVEL,
1398                                 OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
1399                                 MBX_TIMEOUT_SEC,
1400                                 sizeof(struct mbx_lowlevel_set_loopback_mode),
1401                                 OCE_MBX_VER_V0);
1402
1403         fwcmd->params.req.src_port = port_num;
1404         fwcmd->params.req.dest_port = port_num;
1405         fwcmd->params.req.loopback_type = loopback_type;
1406         fwcmd->params.req.loopback_state = enable;
1407
1408         mbx.u0.s.embedded = 1;
1409         mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
1410         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1411
1412         rc = oce_mbox_post(sc, &mbx, NULL);
1413         if (!rc)
1414                 rc = fwcmd->hdr.u0.rsp.status;
1415         if (rc)
1416                 device_printf(sc->dev,
1417                               "%s failed - cmd status: %d addi status: %d\n",
1418                               __FUNCTION__, rc,
1419                               fwcmd->hdr.u0.rsp.additional_status);
1420
1421         return rc;
1422
1423 }
1424
1425 int
1426 oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
1427         uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
1428         uint64_t pattern)
1429 {
1430         
1431         struct oce_mbx mbx;
1432         struct mbx_lowlevel_test_loopback_mode *fwcmd;
1433         int rc = 0;
1434
1435
1436         bzero(&mbx, sizeof(struct oce_mbx));
1437
1438         fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
1439         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1440                                 MBX_SUBSYSTEM_LOWLEVEL,
1441                                 OPCODE_LOWLEVEL_TEST_LOOPBACK,
1442                                 MBX_TIMEOUT_SEC,
1443                                 sizeof(struct mbx_lowlevel_test_loopback_mode),
1444                                 OCE_MBX_VER_V0);
1445
1446         fwcmd->params.req.pattern = pattern;
1447         fwcmd->params.req.src_port = port_num;
1448         fwcmd->params.req.dest_port = port_num;
1449         fwcmd->params.req.pkt_size = pkt_size;
1450         fwcmd->params.req.num_pkts = num_pkts;
1451         fwcmd->params.req.loopback_type = loopback_type;
1452
1453         mbx.u0.s.embedded = 1;
1454         mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
1455         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1456
1457         rc = oce_mbox_post(sc, &mbx, NULL);
1458         if (!rc)
1459                 rc = fwcmd->hdr.u0.rsp.status;
1460         if (rc)
1461                 device_printf(sc->dev,
1462                               "%s failed - cmd status: %d addi status: %d\n",
1463                               __FUNCTION__, rc,
1464                               fwcmd->hdr.u0.rsp.additional_status);
1465         
1466         return rc;
1467 }
1468
1469 int
1470 oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
1471                                 POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
1472 {
1473
1474         struct oce_mbx mbx;
1475         struct oce_mq_sge *sgl = NULL;
1476         struct mbx_common_read_write_flashrom *fwcmd = NULL;
1477         int rc = 0, payload_len = 0;
1478
1479         bzero(&mbx, sizeof(struct oce_mbx));
1480         fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
1481         payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
1482
1483         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1484                                 MBX_SUBSYSTEM_COMMON,
1485                                 OPCODE_COMMON_WRITE_FLASHROM,
1486                                 LONG_TIMEOUT,
1487                                 payload_len,
1488                                 OCE_MBX_VER_V0);
1489
1490         fwcmd->flash_op_type = LE_32(optype);
1491         fwcmd->flash_op_code = LE_32(opcode);
1492         fwcmd->data_buffer_size = LE_32(num_bytes);
1493
1494         mbx.u0.s.embedded  = 0; /*Non embeded*/
1495         mbx.payload_length = payload_len;
1496         mbx.u0.s.sge_count = 1;
1497
1498         sgl = &mbx.payload.u0.u1.sgl[0];
1499         sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
1500         sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
1501         sgl->length = payload_len;
1502
1503         /* post the command */
1504         rc = oce_mbox_post(sc, &mbx, NULL);
1505         if (!rc)
1506                 rc = fwcmd->hdr.u0.rsp.status;
1507         if (rc)
1508                 device_printf(sc->dev,
1509                               "%s failed - cmd status: %d addi status: %d\n",
1510                               __FUNCTION__, rc,
1511                               fwcmd->hdr.u0.rsp.additional_status);
1512         
1513         return rc;
1514
1515 }
1516
1517 int
1518 oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
1519                                 uint32_t offset, uint32_t optype)
1520 {
1521
1522         int rc = 0, payload_len = 0;
1523         struct oce_mbx mbx;
1524         struct mbx_common_read_write_flashrom *fwcmd;
1525
1526         bzero(&mbx, sizeof(struct oce_mbx));
1527
1528         fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
1529
1530         /* Firmware requires extra 4 bytes with this ioctl. Since there
1531            is enough room in the mbx payload it should be good enough
1532            Reference: Bug 14853
1533         */
1534         payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
1535
1536         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1537                                 MBX_SUBSYSTEM_COMMON,
1538                                 OPCODE_COMMON_READ_FLASHROM,
1539                                 MBX_TIMEOUT_SEC,
1540                                 payload_len,
1541                                 OCE_MBX_VER_V0);
1542
1543         fwcmd->flash_op_type = optype;
1544         fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
1545         fwcmd->data_offset = offset;
1546         fwcmd->data_buffer_size = 0x4;
1547
1548         mbx.u0.s.embedded  = 1;
1549         mbx.payload_length = payload_len;
1550
1551         /* post the command */
1552         rc = oce_mbox_post(sc, &mbx, NULL);
1553         if (!rc)
1554                 rc = fwcmd->hdr.u0.rsp.status;
1555         if (rc) {
1556                 device_printf(sc->dev,
1557                               "%s failed - cmd status: %d addi status: %d\n",
1558                               __FUNCTION__, rc,
1559                               fwcmd->hdr.u0.rsp.additional_status);
1560                 goto error;
1561         }
1562         bcopy(fwcmd->data_buffer, flash_crc, 4);
1563 error:
1564         return rc;
1565 }
1566
1567 int
1568 oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
1569 {
1570
1571         struct oce_mbx mbx;
1572         struct mbx_common_phy_info *fwcmd;
1573         int rc = 0;
1574
1575         bzero(&mbx, sizeof(struct oce_mbx));
1576
1577         fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
1578         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1579                                 MBX_SUBSYSTEM_COMMON,
1580                                 OPCODE_COMMON_GET_PHY_CONFIG,
1581                                 MBX_TIMEOUT_SEC,
1582                                 sizeof(struct mbx_common_phy_info),
1583                                 OCE_MBX_VER_V0);
1584
1585         mbx.u0.s.embedded = 1;
1586         mbx.payload_length = sizeof(struct  mbx_common_phy_info);
1587
1588         /* now post the command */
1589         rc = oce_mbox_post(sc, &mbx, NULL);
1590         if (!rc)
1591                 rc = fwcmd->hdr.u0.rsp.status;
1592         if (rc) {
1593                 device_printf(sc->dev,
1594                               "%s failed - cmd status: %d addi status: %d\n",
1595                               __FUNCTION__, rc,
1596                               fwcmd->hdr.u0.rsp.additional_status);
1597                 goto error;
1598         }
1599         phy_info->phy_type = HOST_16(fwcmd->params.rsp.phy_info.phy_type);
1600         phy_info->interface_type =
1601                         HOST_16(fwcmd->params.rsp.phy_info.interface_type);
1602         phy_info->auto_speeds_supported =
1603                 HOST_16(fwcmd->params.rsp.phy_info.auto_speeds_supported);
1604         phy_info->fixed_speeds_supported =
1605                 HOST_16(fwcmd->params.rsp.phy_info.fixed_speeds_supported);
1606         phy_info->misc_params = HOST_32(fwcmd->params.rsp.phy_info.misc_params);
1607 error:
1608         return rc;
1609
1610 }
1611
1612
1613 int
1614 oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
1615                         uint32_t data_offset, POCE_DMA_MEM pdma_mem,
1616                         uint32_t *written_data, uint32_t *additional_status)
1617 {
1618
1619         struct oce_mbx mbx;
1620         struct mbx_lancer_common_write_object *fwcmd = NULL;
1621         int rc = 0, payload_len = 0;
1622
1623         bzero(&mbx, sizeof(struct oce_mbx));
1624         payload_len = sizeof(struct mbx_lancer_common_write_object);
1625
1626         mbx.u0.s.embedded  = 1;/* Embedded */
1627         mbx.payload_length = payload_len;
1628         fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
1629
1630         /* initialize the ioctl header */
1631         mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
1632                                 MBX_SUBSYSTEM_COMMON,
1633                                 OPCODE_COMMON_WRITE_OBJECT,
1634                                 LONG_TIMEOUT,
1635                                 payload_len,
1636                                 OCE_MBX_VER_V0);
1637
1638         fwcmd->params.req.write_length = data_size;
1639         if (data_size == 0)
1640                 fwcmd->params.req.eof = 1;
1641         else
1642                 fwcmd->params.req.eof = 0;
1643
1644         strcpy(fwcmd->params.req.object_name, "/prg");
1645         fwcmd->params.req.descriptor_count = 1;
1646         fwcmd->params.req.write_offset = data_offset;
1647         fwcmd->params.req.buffer_length = data_size;
1648         fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
1649         fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
1650
1651         /* post the command */
1652         rc = oce_mbox_post(sc, &mbx, NULL);
1653         if (!rc)
1654                 rc = fwcmd->params.rsp.status;
1655         if (rc) {
1656                 device_printf(sc->dev,
1657                               "%s failed - cmd status: %d addi status: %d\n",
1658                               __FUNCTION__, rc,
1659                               fwcmd->params.rsp.additional_status);
1660                 goto error;
1661         }
1662         *written_data = HOST_32(fwcmd->params.rsp.actual_write_length);
1663         *additional_status = fwcmd->params.rsp.additional_status;
1664 error:
1665         return rc;
1666
1667 }
1668
1669
1670
1671 int
1672 oce_mbox_create_rq(struct oce_rq *rq)
1673 {
1674
1675         struct oce_mbx mbx;
1676         struct mbx_create_nic_rq *fwcmd;
1677         POCE_SOFTC sc = rq->parent;
1678         int rc, num_pages = 0;
1679
1680         if (rq->qstate == QCREATED)
1681                 return 0;
1682
1683         bzero(&mbx, sizeof(struct oce_mbx));
1684
1685         fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
1686         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1687                                 MBX_SUBSYSTEM_NIC,
1688                                 NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
1689                                 sizeof(struct mbx_create_nic_rq),
1690                                 OCE_MBX_VER_V0);
1691
1692         /* oce_page_list will also prepare pages */
1693         num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
1694         
1695         if (IS_XE201(sc)) {
1696                 fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
1697                 fwcmd->params.req.page_size = 1;
1698                 fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
1699         } else
1700                 fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
1701         fwcmd->params.req.num_pages = num_pages;
1702         fwcmd->params.req.cq_id = rq->cq->cq_id;
1703         fwcmd->params.req.if_id = sc->if_id;
1704         fwcmd->params.req.max_frame_size = rq->cfg.mtu;
1705         fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
1706         
1707         mbx.u0.s.embedded = 1;
1708         mbx.payload_length = sizeof(struct mbx_create_nic_rq);
1709         
1710         rc = oce_mbox_post(sc, &mbx, NULL);
1711         if (!rc)
1712                 rc = fwcmd->hdr.u0.rsp.status;
1713         if (rc) {
1714                 device_printf(sc->dev,
1715                               "%s failed - cmd status: %d addi status: %d\n",
1716                               __FUNCTION__, rc,
1717                               fwcmd->hdr.u0.rsp.additional_status);
1718                 goto error;
1719         }
1720         rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
1721         rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
1722 error:
1723         return rc;
1724
1725 }
1726
1727
1728
1729 int
1730 oce_mbox_create_wq(struct oce_wq *wq)
1731 {
1732         struct oce_mbx mbx;
1733         struct mbx_create_nic_wq *fwcmd;
1734         POCE_SOFTC sc = wq->parent;
1735         int rc = 0, version, num_pages;
1736
1737         bzero(&mbx, sizeof(struct oce_mbx));
1738
1739         fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
1740         if (IS_XE201(sc))
1741                 version = OCE_MBX_VER_V1;
1742         else if(IS_BE(sc))
1743                 IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2) 
1744                                          : (version = OCE_MBX_VER_V0);
1745         else
1746                 version = OCE_MBX_VER_V2;
1747
1748         if (version > OCE_MBX_VER_V0)
1749                 fwcmd->params.req.if_id = sc->if_id;
1750
1751         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1752                                 MBX_SUBSYSTEM_NIC,
1753                                 NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
1754                                 sizeof(struct mbx_create_nic_wq),
1755                                 version);
1756
1757         num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
1758
1759         fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
1760         fwcmd->params.req.num_pages = num_pages;
1761         fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
1762         fwcmd->params.req.cq_id = wq->cq->cq_id;
1763         fwcmd->params.req.ulp_num = 1;
1764
1765         mbx.u0.s.embedded = 1;
1766         mbx.payload_length = sizeof(struct mbx_create_nic_wq);
1767
1768         rc = oce_mbox_post(sc, &mbx, NULL);
1769         if (!rc)
1770                 rc = fwcmd->hdr.u0.rsp.status;
1771         if (rc) {
1772                 device_printf(sc->dev,
1773                               "%s failed - cmd status: %d addi status: %d\n",
1774                               __FUNCTION__, rc,
1775                               fwcmd->hdr.u0.rsp.additional_status);
1776                 goto error;
1777         }
1778         wq->wq_id = HOST_16(fwcmd->params.rsp.wq_id);
1779         if (version == OCE_MBX_VER_V2)
1780                 wq->db_offset = HOST_32(fwcmd->params.rsp.db_offset);
1781         else
1782                 wq->db_offset = PD_TXULP_DB;
1783 error:
1784         return rc;
1785
1786 }
1787
1788
1789
1790 int
1791 oce_mbox_create_eq(struct oce_eq *eq)
1792 {
1793         struct oce_mbx mbx;
1794         struct mbx_create_common_eq *fwcmd;
1795         POCE_SOFTC sc = eq->parent;
1796         int rc = 0;
1797         uint32_t num_pages;
1798
1799         bzero(&mbx, sizeof(struct oce_mbx));
1800
1801         fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
1802
1803         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1804                                 MBX_SUBSYSTEM_COMMON,
1805                                 OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
1806                                 sizeof(struct mbx_create_common_eq),
1807                                 OCE_MBX_VER_V0);
1808
1809         num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
1810         fwcmd->params.req.ctx.num_pages = num_pages;
1811         fwcmd->params.req.ctx.valid = 1;
1812         fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
1813         fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
1814         fwcmd->params.req.ctx.armed = 0;
1815         fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
1816
1817
1818         mbx.u0.s.embedded = 1;
1819         mbx.payload_length = sizeof(struct mbx_create_common_eq);
1820
1821         rc = oce_mbox_post(sc, &mbx, NULL);
1822         if (!rc)
1823                 rc = fwcmd->hdr.u0.rsp.status;
1824         if (rc) {
1825                 device_printf(sc->dev,
1826                               "%s failed - cmd status: %d addi status: %d\n",
1827                               __FUNCTION__, rc,
1828                               fwcmd->hdr.u0.rsp.additional_status);
1829                 goto error;
1830         }
1831         eq->eq_id = HOST_16(fwcmd->params.rsp.eq_id);
1832 error:
1833         return rc;
1834 }
1835
1836
1837
1838 int
1839 oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
1840 {
1841         struct oce_mbx mbx;
1842         struct mbx_create_common_cq *fwcmd;
1843         POCE_SOFTC sc = cq->parent;
1844         uint8_t version;
1845         oce_cq_ctx_t *ctx;
1846         uint32_t num_pages, page_size;
1847         int rc = 0;
1848
1849         
1850         bzero(&mbx, sizeof(struct oce_mbx));
1851
1852         fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
1853
1854         if (IS_XE201(sc))
1855                 version = OCE_MBX_VER_V2;
1856         else
1857                 version = OCE_MBX_VER_V0;
1858
1859         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1860                                 MBX_SUBSYSTEM_COMMON,
1861                                 OPCODE_COMMON_CREATE_CQ,
1862                                 MBX_TIMEOUT_SEC,
1863                                 sizeof(struct mbx_create_common_cq),
1864                                 version);
1865
1866         ctx = &fwcmd->params.req.cq_ctx;
1867
1868         num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
1869         page_size =  1;  /* 1 for 4K */
1870
1871         if (version == OCE_MBX_VER_V2) {
1872                 ctx->v2.num_pages = LE_16(num_pages);
1873                 ctx->v2.page_size = page_size;
1874                 ctx->v2.eventable = is_eventable;
1875                 ctx->v2.valid = 1;
1876                 ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1877                 ctx->v2.nodelay = cq->cq_cfg.nodelay;
1878                 ctx->v2.coalesce_wm = ncoalesce;
1879                 ctx->v2.armed = 0;
1880                 ctx->v2.eq_id = cq->eq->eq_id;
1881                 if (ctx->v2.count == 3) {
1882                         if ((u_int)cq->cq_cfg.q_len > (4*1024)-1)
1883                                 ctx->v2.cqe_count = (4*1024)-1;
1884                         else
1885                                 ctx->v2.cqe_count = cq->cq_cfg.q_len;
1886                 }
1887         } else {
1888                 ctx->v0.num_pages = LE_16(num_pages);
1889                 ctx->v0.eventable = is_eventable;
1890                 ctx->v0.valid = 1;
1891                 ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1892                 ctx->v0.nodelay = cq->cq_cfg.nodelay;
1893                 ctx->v0.coalesce_wm = ncoalesce;
1894                 ctx->v0.armed = 0;
1895                 ctx->v0.eq_id = cq->eq->eq_id;
1896         }
1897
1898         mbx.u0.s.embedded = 1;
1899         mbx.payload_length = sizeof(struct mbx_create_common_cq);
1900
1901         rc = oce_mbox_post(sc, &mbx, NULL);
1902         if (!rc)
1903                 rc = fwcmd->hdr.u0.rsp.status;
1904         if (rc) {
1905                 device_printf(sc->dev,
1906                               "%s failed - cmd status: %d addi status: %d\n",
1907                               __FUNCTION__, rc,
1908                               fwcmd->hdr.u0.rsp.additional_status);
1909                 goto error;
1910         }
1911         cq->cq_id = HOST_16(fwcmd->params.rsp.cq_id);
1912 error:
1913         return rc;
1914
1915 }
1916
1917 int 
1918 oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
1919 {
1920         int rc = 0;
1921         struct oce_mbx mbx;
1922         struct mbx_read_common_transrecv_data *fwcmd;
1923         struct oce_mq_sge *sgl;
1924         OCE_DMA_MEM dma;
1925
1926         /* Allocate DMA mem*/
1927         if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data),
1928                                 &dma, 0))
1929                 return ENOMEM;
1930
1931         fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data);
1932         bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data));
1933
1934         bzero(&mbx, sizeof(struct oce_mbx));
1935         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1936                         MBX_SUBSYSTEM_COMMON,
1937                         OPCODE_COMMON_READ_TRANSRECEIVER_DATA,
1938                         MBX_TIMEOUT_SEC,
1939                         sizeof(struct mbx_read_common_transrecv_data),
1940                         OCE_MBX_VER_V0);
1941
1942         /* fill rest of mbx */
1943         mbx.u0.s.embedded = 0;
1944         mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data);
1945         mbx.u0.s.sge_count = 1;
1946         sgl = &mbx.payload.u0.u1.sgl[0];
1947         sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
1948         sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
1949         sgl->length = htole32(mbx.payload_length);
1950         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1951
1952         fwcmd->params.req.port = LE_32(sc->port_id);
1953         fwcmd->params.req.page_num = LE_32(page_num);
1954
1955         /* command post */
1956         rc = oce_mbox_post(sc, &mbx, NULL);
1957         if (!rc)
1958                 rc = fwcmd->hdr.u0.rsp.status;
1959         if (rc) {
1960                 device_printf(sc->dev,
1961                               "%s failed - cmd status: %d addi status: %d\n",
1962                               __FUNCTION__, rc,
1963                               fwcmd->hdr.u0.rsp.additional_status);
1964                 goto error;
1965         }
1966         if(fwcmd->params.rsp.page_num == PAGE_NUM_A0)
1967         {
1968                 bcopy((char *)fwcmd->params.rsp.page_data, 
1969                                 (char *)&sfp_vpd_dump_buffer[0], 
1970                                 TRANSCEIVER_A0_SIZE);
1971         }
1972
1973         if(fwcmd->params.rsp.page_num == PAGE_NUM_A2)
1974         {
1975                 bcopy((char *)fwcmd->params.rsp.page_data, 
1976                                 (char *)&sfp_vpd_dump_buffer[32], 
1977                                 TRANSCEIVER_A2_SIZE);
1978         }
1979 error:
1980         oce_dma_free(sc, &dma);
1981         return rc;
1982 }
1983
1984 void
1985 oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
1986                                 int num)
1987 {
1988         struct oce_mbx mbx;
1989         struct mbx_modify_common_eq_delay *fwcmd;
1990         int rc = 0;
1991         int i = 0;
1992
1993         bzero(&mbx, sizeof(struct oce_mbx));
1994
1995         /* Initialize MODIFY_EQ_DELAY ioctl header */
1996         fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
1997         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1998                                 MBX_SUBSYSTEM_COMMON,
1999                                 OPCODE_COMMON_MODIFY_EQ_DELAY,
2000                                 MBX_TIMEOUT_SEC,
2001                                 sizeof(struct mbx_modify_common_eq_delay),
2002                                 OCE_MBX_VER_V0);
2003         /* fill rest of mbx */
2004         mbx.u0.s.embedded = 1;
2005         mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay);
2006         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2007
2008         fwcmd->params.req.num_eq = num;
2009         for (i = 0; i < num; i++) {
2010                 fwcmd->params.req.delay[i].eq_id = 
2011                                         htole32(set_eqd[i].eq_id);
2012                 fwcmd->params.req.delay[i].phase = 0;
2013                 fwcmd->params.req.delay[i].dm =
2014                 htole32(set_eqd[i].delay_multiplier);
2015         }
2016         
2017
2018         /* command post */
2019         rc = oce_mbox_post(sc, &mbx, NULL);
2020
2021         if (!rc)
2022                 rc = fwcmd->hdr.u0.rsp.status;
2023         if (rc)
2024                 device_printf(sc->dev,
2025                               "%s failed - cmd status: %d addi status: %d\n",
2026                               __FUNCTION__, rc,
2027                               fwcmd->hdr.u0.rsp.additional_status);
2028 }
2029
2030 int
2031 oce_get_profile_config(POCE_SOFTC sc, uint32_t max_rss)
2032 {
2033         struct oce_mbx mbx;
2034         struct mbx_common_get_profile_config *fwcmd;
2035         int rc = 0;
2036         int version = 0;
2037         struct oce_mq_sge *sgl;
2038         OCE_DMA_MEM dma;
2039         uint32_t desc_count = 0;
2040         struct oce_nic_resc_desc *nic_desc = NULL;
2041         int i;
2042         boolean_t nic_desc_valid = FALSE;
2043
2044         if (IS_BE2(sc))
2045                 return -1;
2046
2047         /* Allocate DMA mem*/
2048         if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config),
2049                           &dma, 0))
2050                 return ENOMEM;
2051
2052         /* Initialize MODIFY_EQ_DELAY ioctl header */
2053         fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config);
2054         bzero(fwcmd, sizeof(struct mbx_common_get_profile_config));
2055
2056         if (!IS_XE201(sc))
2057                 version = OCE_MBX_VER_V1;
2058         else
2059                 version = OCE_MBX_VER_V0;
2060
2061         bzero(&mbx, sizeof(struct oce_mbx));
2062         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2063                                 MBX_SUBSYSTEM_COMMON,
2064                                 OPCODE_COMMON_GET_PROFILE_CONFIG,
2065                                 MBX_TIMEOUT_SEC,
2066                                 sizeof(struct mbx_common_get_profile_config),
2067                                 version);
2068         /* fill rest of mbx */
2069         mbx.u0.s.embedded = 0;
2070         mbx.payload_length = sizeof(struct mbx_common_get_profile_config);
2071         mbx.u0.s.sge_count = 1;
2072         sgl = &mbx.payload.u0.u1.sgl[0];
2073         sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2074         sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2075         sgl->length = htole32(mbx.payload_length);
2076         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2077
2078         fwcmd->params.req.type = ACTIVE_PROFILE;
2079
2080         /* command post */
2081         rc = oce_mbox_post(sc, &mbx, NULL);
2082         if (!rc)
2083                 rc = fwcmd->hdr.u0.rsp.status;
2084         if (rc) {
2085                 device_printf(sc->dev,
2086                               "%s failed - cmd status: %d addi status: %d\n",
2087                               __FUNCTION__, rc,
2088                               fwcmd->hdr.u0.rsp.additional_status);
2089                 goto error;
2090         }
2091
2092         nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2093         desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2094         for (i = 0; i < desc_count; i++) {
2095                 if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) || 
2096                     (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2097                         nic_desc_valid = TRUE;
2098                         break;
2099                 }
2100                 nic_desc = (struct oce_nic_resc_desc *) \
2101                                 ((char *)nic_desc + nic_desc->desc_len);
2102         }
2103         if (!nic_desc_valid) {
2104                 rc = -1;
2105                 goto error;
2106         }
2107         else { 
2108                 sc->max_vlans = HOST_16(nic_desc->vlan_count);
2109                 sc->nwqs = HOST_16(nic_desc->txq_count);
2110                 if (sc->nwqs)
2111                         sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2112                 else
2113                         sc->nwqs = OCE_MAX_WQ;
2114
2115                 sc->nrssqs = HOST_16(nic_desc->rssq_count);
2116                 if (sc->nrssqs)
2117                         sc->nrssqs = MIN(sc->nrssqs, max_rss);
2118                 else
2119                         sc->nrssqs = max_rss;
2120                 sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
2121
2122         }
2123 error:
2124         oce_dma_free(sc, &dma);
2125         return rc;
2126
2127 }
2128
2129 int
2130 oce_get_func_config(POCE_SOFTC sc)
2131 {
2132         struct oce_mbx mbx;
2133         struct mbx_common_get_func_config *fwcmd;
2134         int rc = 0;
2135         int version = 0;
2136         struct oce_mq_sge *sgl;
2137         OCE_DMA_MEM dma;
2138         uint32_t desc_count = 0;
2139         struct oce_nic_resc_desc *nic_desc = NULL;
2140         int i;
2141         boolean_t nic_desc_valid = FALSE;
2142         uint32_t max_rss = 0;
2143         
2144         if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
2145                 max_rss = OCE_LEGACY_MODE_RSS;
2146         else
2147                 max_rss = OCE_MAX_RSS;
2148
2149         /* Allocate DMA mem*/
2150         if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config),
2151                           &dma, 0))
2152                 return ENOMEM;
2153
2154         /* Initialize MODIFY_EQ_DELAY ioctl header */
2155         fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config);
2156         bzero(fwcmd, sizeof(struct mbx_common_get_func_config));
2157
2158         if (IS_SH(sc))
2159                 version = OCE_MBX_VER_V1;
2160         else
2161                 version = OCE_MBX_VER_V0;
2162
2163         bzero(&mbx, sizeof(struct oce_mbx));
2164         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2165                                 MBX_SUBSYSTEM_COMMON,
2166                                 OPCODE_COMMON_GET_FUNCTION_CONFIG,
2167                                 MBX_TIMEOUT_SEC,
2168                                 sizeof(struct mbx_common_get_func_config),
2169                                 version);
2170         /* fill rest of mbx */
2171         mbx.u0.s.embedded = 0;
2172         mbx.payload_length = sizeof(struct mbx_common_get_func_config);
2173         mbx.u0.s.sge_count = 1;
2174         sgl = &mbx.payload.u0.u1.sgl[0];
2175         sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2176         sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2177         sgl->length = htole32(mbx.payload_length);
2178         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2179
2180         /* command post */
2181         rc = oce_mbox_post(sc, &mbx, NULL);
2182         if (!rc)
2183                 rc = fwcmd->hdr.u0.rsp.status;
2184         if (rc) {
2185                 device_printf(sc->dev,
2186                               "%s failed - cmd status: %d addi status: %d\n",
2187                               __FUNCTION__, rc,
2188                               fwcmd->hdr.u0.rsp.additional_status);
2189                 goto error;
2190         }
2191
2192         nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2193         desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2194         for (i = 0; i < desc_count; i++) {
2195                 if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) || 
2196                     (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2197                         nic_desc_valid = TRUE;
2198                         break;
2199                 }
2200                 nic_desc = (struct oce_nic_resc_desc *) \
2201                                 ((char *)nic_desc + nic_desc->desc_len);
2202         }
2203         if (!nic_desc_valid) {
2204                 rc = -1;
2205                 goto error;
2206         }
2207         else {
2208                 sc->max_vlans = nic_desc->vlan_count;
2209                 sc->nwqs = HOST_32(nic_desc->txq_count);
2210                 if (sc->nwqs)
2211                         sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2212                 else
2213                         sc->nwqs = OCE_MAX_WQ;
2214
2215                 sc->nrssqs = HOST_32(nic_desc->rssq_count);
2216                 if (sc->nrssqs)
2217                         sc->nrssqs = MIN(sc->nrssqs, max_rss);
2218                 else
2219                         sc->nrssqs = max_rss;
2220                 sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
2221         }
2222 error:
2223         oce_dma_free(sc, &dma);
2224         return rc;
2225
2226 }
2227
2228 /* hw lro functions */
2229
2230 int
2231 oce_mbox_nic_query_lro_capabilities(POCE_SOFTC sc, uint32_t *lro_rq_cnt, uint32_t *lro_flags)
2232 {
2233         struct oce_mbx mbx;
2234         struct mbx_nic_query_lro_capabilities *fwcmd;
2235         int rc = 0;
2236
2237         bzero(&mbx, sizeof(struct oce_mbx));
2238
2239         fwcmd = (struct mbx_nic_query_lro_capabilities *)&mbx.payload;
2240         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2241                                 MBX_SUBSYSTEM_NIC,
2242                                 0x20,MBX_TIMEOUT_SEC,
2243                                 sizeof(struct mbx_nic_query_lro_capabilities),
2244                                 OCE_MBX_VER_V0);
2245
2246         mbx.u0.s.embedded = 1;
2247         mbx.payload_length = sizeof(struct mbx_nic_query_lro_capabilities);
2248
2249         rc = oce_mbox_post(sc, &mbx, NULL);
2250         if (!rc)
2251                 rc = fwcmd->hdr.u0.rsp.status;
2252         if (rc) {
2253                 device_printf(sc->dev,
2254                               "%s failed - cmd status: %d addi status: %d\n",
2255                               __FUNCTION__, rc,
2256                               fwcmd->hdr.u0.rsp.additional_status);
2257
2258                 return rc;
2259         }
2260         if(lro_flags)
2261                 *lro_flags = HOST_32(fwcmd->params.rsp.lro_flags);
2262
2263         if(lro_rq_cnt)
2264                 *lro_rq_cnt = HOST_16(fwcmd->params.rsp.lro_rq_cnt);
2265
2266         return rc;
2267 }
2268
2269 int
2270 oce_mbox_nic_set_iface_lro_config(POCE_SOFTC sc, int enable)
2271 {
2272         struct oce_mbx mbx;
2273         struct mbx_nic_set_iface_lro_config *fwcmd;
2274         int rc = 0;
2275
2276         bzero(&mbx, sizeof(struct oce_mbx));
2277
2278         fwcmd = (struct mbx_nic_set_iface_lro_config *)&mbx.payload;
2279         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2280                                 MBX_SUBSYSTEM_NIC,
2281                                 0x26,MBX_TIMEOUT_SEC,
2282                                 sizeof(struct mbx_nic_set_iface_lro_config),
2283                                 OCE_MBX_VER_V0);
2284
2285         mbx.u0.s.embedded = 1;
2286         mbx.payload_length = sizeof(struct mbx_nic_set_iface_lro_config);
2287
2288         fwcmd->params.req.iface_id = sc->if_id;
2289         fwcmd->params.req.lro_flags = 0;
2290
2291         if(enable) {
2292                 fwcmd->params.req.lro_flags = LRO_FLAGS_HASH_MODE | LRO_FLAGS_RSS_MODE;
2293                 fwcmd->params.req.lro_flags |= LRO_FLAGS_CLSC_IPV4 | LRO_FLAGS_CLSC_IPV6;
2294
2295                 fwcmd->params.req.max_clsc_byte_cnt = 64*1024; /* min = 2974, max = 0xfa59 */
2296                 fwcmd->params.req.max_clsc_seg_cnt = 43; /* min = 2, max = 64 */
2297                 fwcmd->params.req.max_clsc_usec_delay = 18; /* min = 1, max = 256 */
2298                 fwcmd->params.req.min_clsc_frame_byte_cnt = 0; /* min = 1, max = 9014 */
2299         }
2300
2301         rc = oce_mbox_post(sc, &mbx, NULL);
2302         if (!rc)
2303                 rc = fwcmd->hdr.u0.rsp.status;
2304         if (rc) {
2305                 device_printf(sc->dev,
2306                               "%s failed - cmd status: %d addi status: %d\n",
2307                               __FUNCTION__, rc,
2308                               fwcmd->hdr.u0.rsp.additional_status);
2309
2310                 return rc;
2311         }
2312         return rc;
2313 }
2314
2315 int
2316 oce_mbox_create_rq_v2(struct oce_rq *rq)
2317 {
2318         struct oce_mbx mbx;
2319         struct mbx_create_nic_rq_v2 *fwcmd;
2320         POCE_SOFTC sc = rq->parent;
2321         int rc = 0, num_pages = 0;
2322
2323         if (rq->qstate == QCREATED)
2324                 return 0;
2325
2326         bzero(&mbx, sizeof(struct oce_mbx));
2327
2328         fwcmd = (struct mbx_create_nic_rq_v2 *)&mbx.payload;
2329         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2330                                 MBX_SUBSYSTEM_NIC,
2331                                 0x08, MBX_TIMEOUT_SEC,
2332                                 sizeof(struct mbx_create_nic_rq_v2),
2333                                 OCE_MBX_VER_V2);
2334
2335         /* oce_page_list will also prepare pages */
2336         num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
2337
2338         fwcmd->params.req.cq_id = rq->cq->cq_id;
2339         fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
2340         fwcmd->params.req.num_pages = num_pages;
2341
2342         fwcmd->params.req.if_id = sc->if_id;
2343
2344         fwcmd->params.req.max_frame_size = rq->cfg.mtu;
2345         fwcmd->params.req.page_size = 1;
2346         if(rq->cfg.is_rss_queue) {
2347                 fwcmd->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO);
2348         }else {
2349                 device_printf(sc->dev,
2350                         "non rss lro queue should not be created \n");
2351                 goto error;
2352         }
2353         mbx.u0.s.embedded = 1;
2354         mbx.payload_length = sizeof(struct mbx_create_nic_rq_v2);
2355
2356         rc = oce_mbox_post(sc, &mbx, NULL);
2357         if (!rc)
2358                 rc = fwcmd->hdr.u0.rsp.status;
2359         if (rc) {
2360                 device_printf(sc->dev,
2361                               "%s failed - cmd status: %d addi status: %d\n",
2362                               __FUNCTION__, rc,
2363                               fwcmd->hdr.u0.rsp.additional_status);
2364                 goto error;
2365         }
2366         rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
2367         rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
2368
2369 error:
2370         return rc;
2371 }
2372