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