1231437Sluigi/*-
2252869Sdelphij * Copyright (C) 2013 Emulex
3231437Sluigi * All rights reserved.
4231437Sluigi *
5231437Sluigi * Redistribution and use in source and binary forms, with or without
6231437Sluigi * modification, are permitted provided that the following conditions are met:
7231437Sluigi *
8231437Sluigi * 1. Redistributions of source code must retain the above copyright notice,
9231437Sluigi *    this list of conditions and the following disclaimer.
10231437Sluigi *
11231437Sluigi * 2. Redistributions in binary form must reproduce the above copyright
12231437Sluigi *    notice, this list of conditions and the following disclaimer in the
13231437Sluigi *    documentation and/or other materials provided with the distribution.
14231437Sluigi *
15231437Sluigi * 3. Neither the name of the Emulex Corporation nor the names of its
16231437Sluigi *    contributors may be used to endorse or promote products derived from
17231437Sluigi *    this software without specific prior written permission.
18231437Sluigi *
19231437Sluigi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20231437Sluigi * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21231437Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22231437Sluigi * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23231437Sluigi * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24231437Sluigi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25231437Sluigi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26231437Sluigi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27231437Sluigi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28231437Sluigi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29231437Sluigi * POSSIBILITY OF SUCH DAMAGE.
30231437Sluigi *
31231437Sluigi * Contact Information:
32231437Sluigi * freebsd-drivers@emulex.com
33231437Sluigi *
34231437Sluigi * Emulex
35231437Sluigi * 3333 Susan Street
36231437Sluigi * Costa Mesa, CA 92626
37231437Sluigi */
38231437Sluigi
39231437Sluigi/* $FreeBSD: releng/11.0/sys/dev/oce/oce_mbox.c 297793 2016-04-10 23:07:00Z pfg $ */
40231437Sluigi
41231437Sluigi#include "oce_if.h"
42247880Sdelphijextern uint32_t sfp_vpd_dump_buffer[TRANSCEIVER_DATA_NUM_ELE];
43231437Sluigi
44231437Sluigi/**
45231437Sluigi * @brief Reset (firmware) common function
46231437Sluigi * @param sc		software handle to the device
47231437Sluigi * @returns		0 on success, ETIMEDOUT on failure
48231437Sluigi */
49231437Sluigiint
50231437Sluigioce_reset_fun(POCE_SOFTC sc)
51231437Sluigi{
52231437Sluigi	struct oce_mbx *mbx;
53231437Sluigi	struct oce_bmbx *mb;
54231437Sluigi	struct ioctl_common_function_reset *fwcmd;
55231437Sluigi	int rc = 0;
56231437Sluigi
57231437Sluigi	if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) {
58231437Sluigi		mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
59231437Sluigi		mbx = &mb->mbx;
60231437Sluigi		bzero(mbx, sizeof(struct oce_mbx));
61231437Sluigi
62231437Sluigi		fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
63231437Sluigi		mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
64231437Sluigi					MBX_SUBSYSTEM_COMMON,
65231437Sluigi					OPCODE_COMMON_FUNCTION_RESET,
66231437Sluigi					10,	/* MBX_TIMEOUT_SEC */
67231437Sluigi					sizeof(struct
68231437Sluigi					    ioctl_common_function_reset),
69231437Sluigi					OCE_MBX_VER_V0);
70231437Sluigi
71231437Sluigi		mbx->u0.s.embedded = 1;
72231437Sluigi		mbx->payload_length =
73231437Sluigi		    sizeof(struct ioctl_common_function_reset);
74231437Sluigi
75231437Sluigi		rc = oce_mbox_dispatch(sc, 2);
76231437Sluigi	}
77231437Sluigi
78231437Sluigi	return rc;
79231437Sluigi}
80231437Sluigi
81231437Sluigi
82231437Sluigi/**
83231437Sluigi * @brief  		This funtions tells firmware we are
84231437Sluigi *			done with commands.
85231437Sluigi * @param sc            software handle to the device
86231437Sluigi * @returns             0 on success, ETIMEDOUT on failure
87231437Sluigi */
88231437Sluigiint
89231437Sluigioce_fw_clean(POCE_SOFTC sc)
90231437Sluigi{
91231437Sluigi	struct oce_bmbx *mbx;
92231437Sluigi	uint8_t *ptr;
93231437Sluigi	int ret = 0;
94231437Sluigi
95231437Sluigi	mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
96231437Sluigi	ptr = (uint8_t *) &mbx->mbx;
97231437Sluigi
98231437Sluigi	/* Endian Signature */
99231437Sluigi	*ptr++ = 0xff;
100231437Sluigi	*ptr++ = 0xaa;
101231437Sluigi	*ptr++ = 0xbb;
102231437Sluigi	*ptr++ = 0xff;
103231437Sluigi	*ptr++ = 0xff;
104231437Sluigi	*ptr++ = 0xcc;
105231437Sluigi	*ptr++ = 0xdd;
106231437Sluigi	*ptr = 0xff;
107231437Sluigi
108231437Sluigi	ret = oce_mbox_dispatch(sc, 2);
109231437Sluigi
110231437Sluigi	return ret;
111231437Sluigi}
112231437Sluigi
113231437Sluigi
114231437Sluigi/**
115231437Sluigi * @brief Mailbox wait
116231437Sluigi * @param sc		software handle to the device
117231437Sluigi * @param tmo_sec	timeout in seconds
118231437Sluigi */
119231437Sluigistatic int
120231437Sluigioce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
121231437Sluigi{
122231437Sluigi	tmo_sec *= 10000;
123231437Sluigi	pd_mpu_mbox_db_t mbox_db;
124231437Sluigi
125231437Sluigi	for (;;) {
126231437Sluigi		if (tmo_sec != 0) {
127231437Sluigi			if (--tmo_sec == 0)
128231437Sluigi				break;
129231437Sluigi		}
130231437Sluigi
131231437Sluigi		mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
132231437Sluigi
133231437Sluigi		if (mbox_db.bits.ready)
134231437Sluigi			return 0;
135231437Sluigi
136231437Sluigi		DELAY(100);
137231437Sluigi	}
138231437Sluigi
139231437Sluigi	device_printf(sc->dev, "Mailbox timed out\n");
140231437Sluigi
141231437Sluigi	return ETIMEDOUT;
142231437Sluigi}
143231437Sluigi
144231437Sluigi
145231437Sluigi/**
146231437Sluigi * @brief Mailbox dispatch
147231437Sluigi * @param sc		software handle to the device
148231437Sluigi * @param tmo_sec	timeout in seconds
149231437Sluigi */
150231437Sluigiint
151231437Sluigioce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
152231437Sluigi{
153231437Sluigi	pd_mpu_mbox_db_t mbox_db;
154231437Sluigi	uint32_t pa;
155231437Sluigi	int rc;
156231437Sluigi
157231437Sluigi	oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
158231437Sluigi	pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
159231437Sluigi	bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
160231437Sluigi	mbox_db.bits.ready = 0;
161231437Sluigi	mbox_db.bits.hi = 1;
162231437Sluigi	mbox_db.bits.address = pa;
163231437Sluigi
164231437Sluigi	rc = oce_mbox_wait(sc, tmo_sec);
165231437Sluigi	if (rc == 0) {
166231437Sluigi		OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
167231437Sluigi
168231437Sluigi		pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
169231437Sluigi		mbox_db.bits.ready = 0;
170231437Sluigi		mbox_db.bits.hi = 0;
171231437Sluigi		mbox_db.bits.address = pa;
172231437Sluigi
173231437Sluigi		rc = oce_mbox_wait(sc, tmo_sec);
174231437Sluigi
175231437Sluigi		if (rc == 0) {
176231437Sluigi			OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
177231437Sluigi
178231437Sluigi			rc = oce_mbox_wait(sc, tmo_sec);
179231437Sluigi
180231437Sluigi			oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
181231437Sluigi		}
182231437Sluigi	}
183231437Sluigi
184231437Sluigi	return rc;
185231437Sluigi}
186231437Sluigi
187231437Sluigi
188231437Sluigi
189231437Sluigi/**
190231437Sluigi * @brief 		Mailbox common request header initialization
191231437Sluigi * @param hdr		mailbox header
192231437Sluigi * @param dom		domain
193231437Sluigi * @param port		port
194231437Sluigi * @param subsys	subsystem
195231437Sluigi * @param opcode	opcode
196231437Sluigi * @param timeout	timeout
197231437Sluigi * @param pyld_len	payload length
198231437Sluigi */
199231437Sluigivoid
200231437Sluigimbx_common_req_hdr_init(struct mbx_hdr *hdr,
201231437Sluigi			uint8_t dom, uint8_t port,
202231437Sluigi			uint8_t subsys, uint8_t opcode,
203231437Sluigi			uint32_t timeout, uint32_t pyld_len,
204231437Sluigi			uint8_t version)
205231437Sluigi{
206231437Sluigi	hdr->u0.req.opcode = opcode;
207231437Sluigi	hdr->u0.req.subsystem = subsys;
208231437Sluigi	hdr->u0.req.port_number = port;
209231437Sluigi	hdr->u0.req.domain = dom;
210231437Sluigi
211231437Sluigi	hdr->u0.req.timeout = timeout;
212231437Sluigi	hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
213231437Sluigi	hdr->u0.req.version = version;
214231437Sluigi}
215231437Sluigi
216231437Sluigi
217231437Sluigi
218231437Sluigi/**
219231437Sluigi * @brief Function to initialize the hw with host endian information
220231437Sluigi * @param sc		software handle to the device
221231437Sluigi * @returns		0 on success, ETIMEDOUT on failure
222231437Sluigi */
223231437Sluigiint
224231437Sluigioce_mbox_init(POCE_SOFTC sc)
225231437Sluigi{
226231437Sluigi	struct oce_bmbx *mbx;
227231437Sluigi	uint8_t *ptr;
228231437Sluigi	int ret = 0;
229231437Sluigi
230231437Sluigi	if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
231231437Sluigi		mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
232231437Sluigi		ptr = (uint8_t *) &mbx->mbx;
233231437Sluigi
234231437Sluigi		/* Endian Signature */
235231437Sluigi		*ptr++ = 0xff;
236231437Sluigi		*ptr++ = 0x12;
237231437Sluigi		*ptr++ = 0x34;
238231437Sluigi		*ptr++ = 0xff;
239231437Sluigi		*ptr++ = 0xff;
240231437Sluigi		*ptr++ = 0x56;
241231437Sluigi		*ptr++ = 0x78;
242231437Sluigi		*ptr = 0xff;
243231437Sluigi
244231437Sluigi		ret = oce_mbox_dispatch(sc, 0);
245231437Sluigi	}
246231437Sluigi
247231437Sluigi	return ret;
248231437Sluigi}
249231437Sluigi
250231437Sluigi
251231437Sluigi/**
252231437Sluigi * @brief 		Function to get the firmware version
253231437Sluigi * @param sc		software handle to the device
254231437Sluigi * @returns		0 on success, EIO on failure
255231437Sluigi */
256231437Sluigiint
257231437Sluigioce_get_fw_version(POCE_SOFTC sc)
258231437Sluigi{
259231437Sluigi	struct oce_mbx mbx;
260231437Sluigi	struct mbx_get_common_fw_version *fwcmd;
261231437Sluigi	int ret = 0;
262231437Sluigi
263231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
264231437Sluigi
265231437Sluigi	fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
266231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
267231437Sluigi				MBX_SUBSYSTEM_COMMON,
268231437Sluigi				OPCODE_COMMON_GET_FW_VERSION,
269231437Sluigi				MBX_TIMEOUT_SEC,
270231437Sluigi				sizeof(struct mbx_get_common_fw_version),
271231437Sluigi				OCE_MBX_VER_V0);
272231437Sluigi
273231437Sluigi	mbx.u0.s.embedded = 1;
274231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
275231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
276231437Sluigi
277231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
278247880Sdelphij	if (!ret)
279247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
280247880Sdelphij	if (ret) {
281257007Sdelphij		device_printf(sc->dev,
282257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
283257007Sdelphij			      __FUNCTION__, ret,
284257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
285247880Sdelphij		goto error;
286247880Sdelphij	}
287231437Sluigi
288231437Sluigi	bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
289247880Sdelphijerror:
290247880Sdelphij	return ret;
291231437Sluigi}
292231437Sluigi
293231437Sluigi
294231437Sluigi/**
295231879Sluigi * @brief	Firmware will send gracious notifications during
296231879Sluigi *		attach only after sending first mcc commnad. We
297231879Sluigi *		use MCC queue only for getting async and mailbox
298231879Sluigi *		for sending cmds. So to get gracious notifications
299231879Sluigi *		atleast send one dummy command on mcc.
300231879Sluigi */
301231879Sluigiint
302231879Sluigioce_first_mcc_cmd(POCE_SOFTC sc)
303231879Sluigi{
304231879Sluigi	struct oce_mbx *mbx;
305231879Sluigi	struct oce_mq *mq = sc->mq;
306231879Sluigi	struct mbx_get_common_fw_version *fwcmd;
307231879Sluigi	uint32_t reg_value;
308231879Sluigi
309231879Sluigi	mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
310231879Sluigi	bzero(mbx, sizeof(struct oce_mbx));
311231879Sluigi
312231879Sluigi	fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload;
313231879Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
314231879Sluigi				MBX_SUBSYSTEM_COMMON,
315231879Sluigi				OPCODE_COMMON_GET_FW_VERSION,
316231879Sluigi				MBX_TIMEOUT_SEC,
317231879Sluigi				sizeof(struct mbx_get_common_fw_version),
318231879Sluigi				OCE_MBX_VER_V0);
319231879Sluigi	mbx->u0.s.embedded = 1;
320231879Sluigi	mbx->payload_length = sizeof(struct mbx_get_common_fw_version);
321231879Sluigi	bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map,
322231879Sluigi				BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
323231879Sluigi	RING_PUT(mq->ring, 1);
324231879Sluigi	reg_value = (1 << 16) | mq->mq_id;
325231879Sluigi	OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value);
326231879Sluigi
327231879Sluigi	return 0;
328231879Sluigi}
329231879Sluigi
330231879Sluigi/**
331231437Sluigi * @brief		Function to post a MBX to the mbox
332231437Sluigi * @param sc		software handle to the device
333231437Sluigi * @param mbx 		pointer to the MBX to send
334231437Sluigi * @param mbxctx	pointer to the mbx context structure
335231437Sluigi * @returns		0 on success, error on failure
336231437Sluigi */
337231437Sluigiint
338231437Sluigioce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
339231437Sluigi{
340231437Sluigi	struct oce_mbx *mb_mbx = NULL;
341231437Sluigi	struct oce_mq_cqe *mb_cqe = NULL;
342231437Sluigi	struct oce_bmbx *mb = NULL;
343231437Sluigi	int rc = 0;
344231437Sluigi	uint32_t tmo = 0;
345231437Sluigi	uint32_t cstatus = 0;
346231437Sluigi	uint32_t xstatus = 0;
347231437Sluigi
348231437Sluigi	LOCK(&sc->bmbx_lock);
349231437Sluigi
350231437Sluigi	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
351231437Sluigi	mb_mbx = &mb->mbx;
352231437Sluigi
353231437Sluigi	/* get the tmo */
354231437Sluigi	tmo = mbx->tag[0];
355231437Sluigi	mbx->tag[0] = 0;
356231437Sluigi
357231437Sluigi	/* copy mbx into mbox */
358231437Sluigi	bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
359231437Sluigi
360231437Sluigi	/* now dispatch */
361231437Sluigi	rc = oce_mbox_dispatch(sc, tmo);
362231437Sluigi	if (rc == 0) {
363231437Sluigi		/*
364231437Sluigi		 * the command completed successfully. Now get the
365231437Sluigi		 * completion queue entry
366231437Sluigi		 */
367231437Sluigi		mb_cqe = &mb->cqe;
368231437Sluigi		DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
369231437Sluigi
370231437Sluigi		/* copy mbox mbx back */
371231437Sluigi		bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
372231437Sluigi
373231437Sluigi		/* pick up the mailbox status */
374231437Sluigi		cstatus = mb_cqe->u0.s.completion_status;
375231437Sluigi		xstatus = mb_cqe->u0.s.extended_status;
376231437Sluigi
377231437Sluigi		/*
378231437Sluigi		 * store the mbx context in the cqe tag section so that
379231437Sluigi		 * the upper layer handling the cqe can associate the mbx
380231437Sluigi		 * with the response
381231437Sluigi		 */
382231437Sluigi		if (cstatus == 0 && mbxctx) {
383231437Sluigi			/* save context */
384231437Sluigi			mbxctx->mbx = mb_mbx;
385231437Sluigi			bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
386231437Sluigi				sizeof(struct oce_mbx_ctx *));
387231437Sluigi		}
388231437Sluigi	}
389231437Sluigi
390231437Sluigi	UNLOCK(&sc->bmbx_lock);
391231437Sluigi
392231437Sluigi	return rc;
393231437Sluigi}
394231437Sluigi
395231437Sluigi/**
396231437Sluigi * @brief Function to read the mac address associated with an interface
397231437Sluigi * @param sc		software handle to the device
398231437Sluigi * @param if_id 	interface id to read the address from
399231437Sluigi * @param perm 		set to 1 if reading the factory mac address.
400231437Sluigi *			In this case if_id is ignored
401231437Sluigi * @param type 		type of the mac address, whether network or storage
402231437Sluigi * @param[out] mac 	[OUTPUT] pointer to a buffer containing the
403231437Sluigi *			mac address when the command succeeds.
404231437Sluigi * @returns		0 on success, EIO on failure
405231437Sluigi */
406231437Sluigiint
407231437Sluigioce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
408231437Sluigi		uint8_t perm, uint8_t type, struct mac_address_format *mac)
409231437Sluigi{
410231437Sluigi	struct oce_mbx mbx;
411231437Sluigi	struct mbx_query_common_iface_mac *fwcmd;
412231437Sluigi	int ret = 0;
413231437Sluigi
414231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
415231437Sluigi
416231437Sluigi	fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
417231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
418231437Sluigi				MBX_SUBSYSTEM_COMMON,
419231437Sluigi				OPCODE_COMMON_QUERY_IFACE_MAC,
420231437Sluigi				MBX_TIMEOUT_SEC,
421231437Sluigi				sizeof(struct mbx_query_common_iface_mac),
422231437Sluigi				OCE_MBX_VER_V0);
423231437Sluigi
424231437Sluigi	fwcmd->params.req.permanent = perm;
425231437Sluigi	if (!perm)
426231437Sluigi		fwcmd->params.req.if_id = (uint16_t) if_id;
427231437Sluigi	else
428231437Sluigi		fwcmd->params.req.if_id = 0;
429231437Sluigi
430231437Sluigi	fwcmd->params.req.type = type;
431231437Sluigi
432231437Sluigi	mbx.u0.s.embedded = 1;
433231437Sluigi	mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
434231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
435231437Sluigi
436231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
437247880Sdelphij	if (!ret)
438247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
439247880Sdelphij	if (ret) {
440257007Sdelphij		device_printf(sc->dev,
441257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
442257007Sdelphij			      __FUNCTION__, ret,
443257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
444247880Sdelphij		goto error;
445247880Sdelphij	}
446231437Sluigi
447231437Sluigi	/* copy the mac addres in the output parameter */
448231437Sluigi	mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
449231437Sluigi	bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
450231437Sluigi		mac->size_of_struct);
451247880Sdelphijerror:
452247880Sdelphij	return ret;
453231437Sluigi}
454231437Sluigi
455231437Sluigi/**
456231437Sluigi * @brief Function to query the fw attributes from the hw
457231437Sluigi * @param sc		software handle to the device
458231437Sluigi * @returns		0 on success, EIO on failure
459231437Sluigi */
460231437Sluigiint
461231437Sluigioce_get_fw_config(POCE_SOFTC sc)
462231437Sluigi{
463231437Sluigi	struct oce_mbx mbx;
464231437Sluigi	struct mbx_common_query_fw_config *fwcmd;
465231437Sluigi	int ret = 0;
466231437Sluigi
467231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
468231437Sluigi
469231437Sluigi	fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
470231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
471231437Sluigi				MBX_SUBSYSTEM_COMMON,
472231437Sluigi				OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
473231437Sluigi				MBX_TIMEOUT_SEC,
474231437Sluigi				sizeof(struct mbx_common_query_fw_config),
475231437Sluigi				OCE_MBX_VER_V0);
476231437Sluigi
477231437Sluigi	mbx.u0.s.embedded = 1;
478231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
479231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
480231437Sluigi
481231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
482247880Sdelphij	if (!ret)
483247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
484247880Sdelphij	if (ret) {
485257007Sdelphij		device_printf(sc->dev,
486257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
487257007Sdelphij			      __FUNCTION__, ret,
488257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
489247880Sdelphij		goto error;
490247880Sdelphij	}
491231437Sluigi
492231437Sluigi	DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
493231437Sluigi
494257007Sdelphij	sc->config_number = HOST_32(fwcmd->params.rsp.config_number);
495257007Sdelphij	sc->asic_revision = HOST_32(fwcmd->params.rsp.asic_revision);
496257007Sdelphij	sc->port_id	  = HOST_32(fwcmd->params.rsp.port_id);
497257007Sdelphij	sc->function_mode = HOST_32(fwcmd->params.rsp.function_mode);
498257007Sdelphij	sc->function_caps = HOST_32(fwcmd->params.rsp.function_caps);
499231437Sluigi
500231437Sluigi	if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
501257007Sdelphij		sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[0].nic_wq_tot);
502257007Sdelphij		sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[0].lro_rqid_tot);
503231437Sluigi	} else {
504257007Sdelphij		sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[1].nic_wq_tot);
505257007Sdelphij		sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[1].lro_rqid_tot);
506231437Sluigi	}
507231437Sluigi
508247880Sdelphijerror:
509247880Sdelphij	return ret;
510231437Sluigi
511231437Sluigi}
512231437Sluigi
513231437Sluigi/**
514231437Sluigi *
515231437Sluigi * @brief function to create a device interface
516231437Sluigi * @param sc		software handle to the device
517231437Sluigi * @param cap_flags	capability flags
518231437Sluigi * @param en_flags	enable capability flags
519231437Sluigi * @param vlan_tag	optional vlan tag to associate with the if
520231437Sluigi * @param mac_addr	pointer to a buffer containing the mac address
521231437Sluigi * @param[out] if_id	[OUTPUT] pointer to an integer to hold the ID of the
522231437Sluigi interface created
523231437Sluigi * @returns		0 on success, EIO on failure
524231437Sluigi */
525231437Sluigiint
526231437Sluigioce_if_create(POCE_SOFTC sc,
527231437Sluigi		uint32_t cap_flags,
528231437Sluigi		uint32_t en_flags,
529231437Sluigi		uint16_t vlan_tag,
530231437Sluigi		uint8_t *mac_addr,
531231437Sluigi		uint32_t *if_id)
532231437Sluigi{
533231437Sluigi	struct oce_mbx mbx;
534231437Sluigi	struct mbx_create_common_iface *fwcmd;
535231437Sluigi	int rc = 0;
536231437Sluigi
537231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
538231437Sluigi
539231437Sluigi	fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
540231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
541231437Sluigi				MBX_SUBSYSTEM_COMMON,
542231437Sluigi				OPCODE_COMMON_CREATE_IFACE,
543231437Sluigi				MBX_TIMEOUT_SEC,
544231437Sluigi				sizeof(struct mbx_create_common_iface),
545231437Sluigi				OCE_MBX_VER_V0);
546231437Sluigi	DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
547231437Sluigi
548231437Sluigi	fwcmd->params.req.version = 0;
549231437Sluigi	fwcmd->params.req.cap_flags = LE_32(cap_flags);
550231437Sluigi	fwcmd->params.req.enable_flags = LE_32(en_flags);
551231437Sluigi	if (mac_addr != NULL) {
552231437Sluigi		bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
553231437Sluigi		fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
554231437Sluigi		fwcmd->params.req.mac_invalid = 0;
555231437Sluigi	} else {
556231437Sluigi		fwcmd->params.req.mac_invalid = 1;
557231437Sluigi	}
558231437Sluigi
559231437Sluigi	mbx.u0.s.embedded = 1;
560231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_iface);
561231437Sluigi	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
562231437Sluigi
563231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
564247880Sdelphij	if (!rc)
565247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
566247880Sdelphij	if (rc) {
567257007Sdelphij		device_printf(sc->dev,
568257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
569257007Sdelphij			      __FUNCTION__, rc,
570257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
571247880Sdelphij		goto error;
572247880Sdelphij	}
573231437Sluigi
574257007Sdelphij	*if_id = HOST_32(fwcmd->params.rsp.if_id);
575231437Sluigi
576231437Sluigi	if (mac_addr != NULL)
577257007Sdelphij		sc->pmac_id = HOST_32(fwcmd->params.rsp.pmac_id);
578247880Sdelphijerror:
579247880Sdelphij	return rc;
580231437Sluigi}
581231437Sluigi
582231437Sluigi/**
583231437Sluigi * @brief		Function to delete an interface
584231437Sluigi * @param sc 		software handle to the device
585231437Sluigi * @param if_id		ID of the interface to delete
586231437Sluigi * @returns		0 on success, EIO on failure
587231437Sluigi */
588231437Sluigiint
589231437Sluigioce_if_del(POCE_SOFTC sc, uint32_t if_id)
590231437Sluigi{
591231437Sluigi	struct oce_mbx mbx;
592231437Sluigi	struct mbx_destroy_common_iface *fwcmd;
593231437Sluigi	int rc = 0;
594231437Sluigi
595231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
596231437Sluigi
597231437Sluigi	fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
598231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
599231437Sluigi				MBX_SUBSYSTEM_COMMON,
600231437Sluigi				OPCODE_COMMON_DESTROY_IFACE,
601231437Sluigi				MBX_TIMEOUT_SEC,
602231437Sluigi				sizeof(struct mbx_destroy_common_iface),
603231437Sluigi				OCE_MBX_VER_V0);
604231437Sluigi
605231437Sluigi	fwcmd->params.req.if_id = if_id;
606231437Sluigi
607231437Sluigi	mbx.u0.s.embedded = 1;
608231437Sluigi	mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
609231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
610231437Sluigi
611231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
612247880Sdelphij	if (!rc)
613247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
614247880Sdelphij	if (rc)
615257007Sdelphij		device_printf(sc->dev,
616257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
617257007Sdelphij			      __FUNCTION__, rc,
618257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
619231437Sluigi	return rc;
620231437Sluigi}
621231437Sluigi
622231437Sluigi/**
623231437Sluigi * @brief Function to send the mbx command to configure vlan
624231437Sluigi * @param sc 		software handle to the device
625231437Sluigi * @param if_id 	interface identifier index
626231437Sluigi * @param vtag_arr	array of vlan tags
627231437Sluigi * @param vtag_cnt	number of elements in array
628231437Sluigi * @param untagged	boolean TRUE/FLASE
629231437Sluigi * @param enable_promisc flag to enable/disable VLAN promiscuous mode
630231437Sluigi * @returns		0 on success, EIO on failure
631231437Sluigi */
632231437Sluigiint
633231437Sluigioce_config_vlan(POCE_SOFTC sc,
634231437Sluigi		uint32_t if_id,
635231437Sluigi		struct normal_vlan *vtag_arr,
636231437Sluigi		uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
637231437Sluigi{
638231437Sluigi	struct oce_mbx mbx;
639231437Sluigi	struct mbx_common_config_vlan *fwcmd;
640257007Sdelphij	int rc = 0;
641231437Sluigi
642257007Sdelphij	if (sc->vlans_added > sc->max_vlans)
643257007Sdelphij		goto vlan_promisc;
644257007Sdelphij
645231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
646231437Sluigi	fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
647231437Sluigi
648231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
649231437Sluigi				MBX_SUBSYSTEM_COMMON,
650231437Sluigi				OPCODE_COMMON_CONFIG_IFACE_VLAN,
651231437Sluigi				MBX_TIMEOUT_SEC,
652231437Sluigi				sizeof(struct mbx_common_config_vlan),
653231437Sluigi				OCE_MBX_VER_V0);
654231437Sluigi
655231437Sluigi	fwcmd->params.req.if_id = (uint8_t) if_id;
656231437Sluigi	fwcmd->params.req.promisc = (uint8_t) enable_promisc;
657231437Sluigi	fwcmd->params.req.untagged = (uint8_t) untagged;
658231437Sluigi	fwcmd->params.req.num_vlans = vtag_cnt;
659231437Sluigi
660231437Sluigi	if (!enable_promisc) {
661231437Sluigi		bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
662231437Sluigi			vtag_cnt * sizeof(struct normal_vlan));
663231437Sluigi	}
664231437Sluigi	mbx.u0.s.embedded = 1;
665231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_config_vlan);
666231437Sluigi	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
667231437Sluigi
668231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
669247880Sdelphij	if (!rc)
670247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
671247880Sdelphij	if (rc)
672257007Sdelphij		device_printf(sc->dev,
673257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
674257007Sdelphij			      __FUNCTION__, rc,
675257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
676231437Sluigi
677257007Sdelphij	goto done;
678257007Sdelphij
679257007Sdelphijvlan_promisc:
680257007Sdelphij	/* Enable Vlan Promis */
681257007Sdelphij	oce_rxf_set_promiscuous(sc, (1 << 1));
682257007Sdelphij	device_printf(sc->dev,"Enabling Vlan Promisc Mode\n");
683257007Sdelphijdone:
684257007Sdelphij	return rc;
685257007Sdelphij
686231437Sluigi}
687231437Sluigi
688231437Sluigi/**
689231437Sluigi * @brief Function to set flow control capability in the hardware
690231437Sluigi * @param sc 		software handle to the device
691231437Sluigi * @param flow_control	flow control flags to set
692231437Sluigi * @returns		0 on success, EIO on failure
693231437Sluigi */
694231437Sluigiint
695231437Sluigioce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
696231437Sluigi{
697231437Sluigi	struct oce_mbx mbx;
698231437Sluigi	struct mbx_common_get_set_flow_control *fwcmd =
699231437Sluigi		(struct mbx_common_get_set_flow_control *)&mbx.payload;
700231437Sluigi	int rc;
701231437Sluigi
702231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
703231437Sluigi
704231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
705231437Sluigi				MBX_SUBSYSTEM_COMMON,
706231437Sluigi				OPCODE_COMMON_SET_FLOW_CONTROL,
707231437Sluigi				MBX_TIMEOUT_SEC,
708231437Sluigi				sizeof(struct mbx_common_get_set_flow_control),
709231437Sluigi				OCE_MBX_VER_V0);
710231437Sluigi
711231437Sluigi	if (flow_control & OCE_FC_TX)
712231437Sluigi		fwcmd->tx_flow_control = 1;
713231437Sluigi
714231437Sluigi	if (flow_control & OCE_FC_RX)
715231437Sluigi		fwcmd->rx_flow_control = 1;
716231437Sluigi
717231437Sluigi	mbx.u0.s.embedded = 1;
718231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
719231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
720231437Sluigi
721231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
722247880Sdelphij	if (!rc)
723247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
724247880Sdelphij	if (rc)
725257007Sdelphij		device_printf(sc->dev,
726257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
727257007Sdelphij			      __FUNCTION__, rc,
728257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
729231437Sluigi	return rc;
730231437Sluigi}
731231437Sluigi
732231437Sluigi/**
733231437Sluigi * @brief Initialize the RSS CPU indirection table
734231437Sluigi *
735231437Sluigi * The table is used to choose the queue to place the incomming packets.
736231437Sluigi * Incomming packets are hashed.  The lowest bits in the hash result
737231437Sluigi * are used as the index into the CPU indirection table.
738231437Sluigi * Each entry in the table contains the RSS CPU-ID returned by the NIC
739231437Sluigi * create.  Based on the CPU ID, the receive completion is routed to
740231437Sluigi * the corresponding RSS CQs.  (Non-RSS packets are always completed
741231437Sluigi * on the default (0) CQ).
742231437Sluigi *
743231437Sluigi * @param sc 		software handle to the device
744231437Sluigi * @param *fwcmd	pointer to the rss mbox command
745231437Sluigi * @returns		none
746231437Sluigi */
747231437Sluigistatic int
748231437Sluigioce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
749231437Sluigi{
750231437Sluigi	int i = 0, j = 0, rc = 0;
751231437Sluigi	uint8_t *tbl = fwcmd->params.req.cputable;
752252869Sdelphij	struct oce_rq *rq = NULL;
753231437Sluigi
754231437Sluigi
755252869Sdelphij	for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) {
756252869Sdelphij		for_all_rss_queues(sc, rq, i) {
757252869Sdelphij			if ((j + i) >= INDIRECTION_TABLE_ENTRIES)
758252869Sdelphij				break;
759252869Sdelphij			tbl[j + i] = rq->rss_cpuid;
760231437Sluigi		}
761231437Sluigi	}
762231437Sluigi	if (i == 0) {
763231437Sluigi		device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
764231437Sluigi		rc = ENXIO;
765231437Sluigi
766231437Sluigi	}
767231437Sluigi
768231437Sluigi	/* fill log2 value indicating the size of the CPU table */
769231437Sluigi	if (rc == 0)
770231437Sluigi		fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(i));
771231437Sluigi
772231437Sluigi	return rc;
773231437Sluigi}
774231437Sluigi
775231437Sluigi/**
776231437Sluigi * @brief Function to set flow control capability in the hardware
777231437Sluigi * @param sc 		software handle to the device
778231437Sluigi * @param if_id 	interface id to read the address from
779231437Sluigi * @param enable_rss	0=disable, RSS_ENABLE_xxx flags otherwise
780231437Sluigi * @returns		0 on success, EIO on failure
781231437Sluigi */
782231437Sluigiint
783231437Sluigioce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
784231437Sluigi{
785231437Sluigi	int rc;
786231437Sluigi	struct oce_mbx mbx;
787231437Sluigi	struct mbx_config_nic_rss *fwcmd =
788231437Sluigi				(struct mbx_config_nic_rss *)&mbx.payload;
789247880Sdelphij	int version;
790231437Sluigi
791231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
792231437Sluigi
793252869Sdelphij	if (IS_XE201(sc) || IS_SH(sc)) {
794247880Sdelphij		version = OCE_MBX_VER_V1;
795247880Sdelphij		fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
796247880Sdelphij					       RSS_ENABLE_UDP_IPV6;
797247880Sdelphij	} else
798247880Sdelphij		version = OCE_MBX_VER_V0;
799247880Sdelphij
800231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
801231437Sluigi				MBX_SUBSYSTEM_NIC,
802231437Sluigi				NIC_CONFIG_RSS,
803231437Sluigi				MBX_TIMEOUT_SEC,
804231437Sluigi				sizeof(struct mbx_config_nic_rss),
805247880Sdelphij				version);
806231437Sluigi	if (enable_rss)
807247880Sdelphij		fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 |
808247880Sdelphij					         RSS_ENABLE_TCP_IPV4 |
809247880Sdelphij						 RSS_ENABLE_IPV6 |
810247880Sdelphij						 RSS_ENABLE_TCP_IPV6);
811231437Sluigi	fwcmd->params.req.flush = OCE_FLUSH;
812231437Sluigi	fwcmd->params.req.if_id = LE_32(if_id);
813231437Sluigi
814231437Sluigi	read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
815231437Sluigi
816231437Sluigi	rc = oce_rss_itbl_init(sc, fwcmd);
817231437Sluigi	if (rc == 0) {
818231437Sluigi		mbx.u0.s.embedded = 1;
819231437Sluigi		mbx.payload_length = sizeof(struct mbx_config_nic_rss);
820231437Sluigi		DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
821231437Sluigi
822231437Sluigi		rc = oce_mbox_post(sc, &mbx, NULL);
823247880Sdelphij		if (!rc)
824247880Sdelphij                	rc = fwcmd->hdr.u0.rsp.status;
825247880Sdelphij		if (rc)
826257007Sdelphij		device_printf(sc->dev,
827257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
828257007Sdelphij			      __FUNCTION__, rc,
829257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
830231437Sluigi	}
831231437Sluigi	return rc;
832231437Sluigi}
833231437Sluigi
834231437Sluigi/**
835231437Sluigi * @brief 		RXF function to enable/disable device promiscuous mode
836231437Sluigi * @param sc		software handle to the device
837231437Sluigi * @param enable	enable/disable flag
838231437Sluigi * @returns		0 on success, EIO on failure
839231437Sluigi * @note
840231437Sluigi *	The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
841231437Sluigi *	This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
842231437Sluigi */
843231437Sluigiint
844257007Sdelphijoce_rxf_set_promiscuous(POCE_SOFTC sc, uint8_t enable)
845231437Sluigi{
846231437Sluigi	struct mbx_set_common_iface_rx_filter *fwcmd;
847231437Sluigi	int sz = sizeof(struct mbx_set_common_iface_rx_filter);
848231437Sluigi	iface_rx_filter_ctx_t *req;
849231437Sluigi	OCE_DMA_MEM sgl;
850231437Sluigi	int rc;
851231437Sluigi
852231437Sluigi	/* allocate mbx payload's dma scatter/gather memory */
853231437Sluigi	rc = oce_dma_alloc(sc, sz, &sgl, 0);
854231437Sluigi	if (rc)
855231437Sluigi		return rc;
856231437Sluigi
857231437Sluigi	fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
858231437Sluigi
859231437Sluigi	req =  &fwcmd->params.req;
860231437Sluigi	req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
861231437Sluigi				MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
862257007Sdelphij	/* Bit 0 Mac promisc, Bit 1 Vlan promisc */
863257007Sdelphij	if (enable & 0x01)
864257007Sdelphij		req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS;
865257007Sdelphij
866257007Sdelphij	if (enable & 0x02)
867257007Sdelphij		req->iface_flags = MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
868257007Sdelphij
869231437Sluigi	req->if_id = sc->if_id;
870231437Sluigi
871231437Sluigi	rc = oce_set_common_iface_rx_filter(sc, &sgl);
872231437Sluigi	oce_dma_free(sc, &sgl);
873231437Sluigi
874231437Sluigi	return rc;
875231437Sluigi}
876231437Sluigi
877231437Sluigi
878231437Sluigi/**
879231437Sluigi * @brief 			Function modify and select rx filter options
880231437Sluigi * @param sc			software handle to the device
881231437Sluigi * @param sgl			scatter/gather request/response
882231437Sluigi * @returns			0 on success, error code on failure
883231437Sluigi */
884231437Sluigiint
885231437Sluigioce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
886231437Sluigi{
887231437Sluigi	struct oce_mbx mbx;
888231437Sluigi	int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
889231437Sluigi	struct mbx_set_common_iface_rx_filter *fwcmd;
890231437Sluigi	int rc;
891231437Sluigi
892231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
893231437Sluigi	fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
894231437Sluigi
895231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
896231437Sluigi				MBX_SUBSYSTEM_COMMON,
897231437Sluigi				OPCODE_COMMON_SET_IFACE_RX_FILTER,
898231437Sluigi				MBX_TIMEOUT_SEC,
899231437Sluigi				mbx_sz,
900231437Sluigi				OCE_MBX_VER_V0);
901231437Sluigi
902231437Sluigi	oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
903231437Sluigi	mbx.u0.s.embedded = 0;
904231437Sluigi	mbx.u0.s.sge_count = 1;
905231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
906231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
907231437Sluigi	mbx.payload.u0.u1.sgl[0].length = mbx_sz;
908231437Sluigi	mbx.payload_length = mbx_sz;
909231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
910231437Sluigi
911231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
912247880Sdelphij	if (!rc)
913247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
914247880Sdelphij	if (rc)
915257007Sdelphij		device_printf(sc->dev,
916257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
917257007Sdelphij			      __FUNCTION__, rc,
918257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
919257007Sdelphij	return rc;
920231437Sluigi}
921231437Sluigi
922231437Sluigi/**
923231437Sluigi * @brief Function to query the link status from the hardware
924231437Sluigi * @param sc 		software handle to the device
925231437Sluigi * @param[out] link	pointer to the structure returning link attributes
926231437Sluigi * @returns		0 on success, EIO on failure
927231437Sluigi */
928231437Sluigiint
929231437Sluigioce_get_link_status(POCE_SOFTC sc, struct link_status *link)
930231437Sluigi{
931231437Sluigi	struct oce_mbx mbx;
932231437Sluigi	struct mbx_query_common_link_config *fwcmd;
933247880Sdelphij	int rc = 0, version;
934231437Sluigi
935231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
936231437Sluigi
937258941Sdelphij	IS_BE2(sc) ? (version = OCE_MBX_VER_V0) : (version = OCE_MBX_VER_V1);
938247880Sdelphij
939231437Sluigi	fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
940231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
941231437Sluigi				MBX_SUBSYSTEM_COMMON,
942231437Sluigi				OPCODE_COMMON_QUERY_LINK_CONFIG,
943231437Sluigi				MBX_TIMEOUT_SEC,
944231437Sluigi				sizeof(struct mbx_query_common_link_config),
945247880Sdelphij				version);
946231437Sluigi
947231437Sluigi	mbx.u0.s.embedded = 1;
948231437Sluigi	mbx.payload_length = sizeof(struct mbx_query_common_link_config);
949231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
950231437Sluigi
951231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
952231437Sluigi
953247880Sdelphij	if (!rc)
954247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
955231437Sluigi	if (rc) {
956257007Sdelphij		device_printf(sc->dev,
957257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
958257007Sdelphij			      __FUNCTION__, rc,
959257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
960247880Sdelphij		goto error;
961231437Sluigi	}
962247880Sdelphij	/* interpret response */
963267839Sdelphij	link->qos_link_speed = HOST_16(fwcmd->params.rsp.qos_link_speed);
964267839Sdelphij	link->phys_port_speed = fwcmd->params.rsp.physical_port_speed;
965267839Sdelphij	link->logical_link_status = fwcmd->params.rsp.logical_link_status;
966247880Sdelphijerror:
967231437Sluigi	return rc;
968231437Sluigi}
969231437Sluigi
970231437Sluigi
971231437Sluigi
972231437Sluigiint
973231437Sluigioce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
974231437Sluigi{
975231437Sluigi	struct oce_mbx mbx;
976231437Sluigi	struct mbx_get_nic_stats_v0 *fwcmd;
977231437Sluigi	int rc = 0;
978231437Sluigi
979231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
980231437Sluigi
981231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v0);
982231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_nic_stats_v0));
983231437Sluigi
984231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
985231437Sluigi				MBX_SUBSYSTEM_NIC,
986231437Sluigi				NIC_GET_STATS,
987231437Sluigi				MBX_TIMEOUT_SEC,
988231437Sluigi				sizeof(struct mbx_get_nic_stats_v0),
989231437Sluigi				OCE_MBX_VER_V0);
990231437Sluigi
991231437Sluigi	mbx.u0.s.embedded = 0;
992231437Sluigi	mbx.u0.s.sge_count = 1;
993231437Sluigi
994231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
995231437Sluigi
996231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
997231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
998231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats_v0);
999231437Sluigi
1000231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_nic_stats_v0);
1001231437Sluigi
1002231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1003231437Sluigi
1004231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1005231437Sluigi
1006231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1007231437Sluigi
1008247880Sdelphij	if (!rc)
1009247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1010247880Sdelphij	if (rc)
1011257007Sdelphij		device_printf(sc->dev,
1012257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1013257007Sdelphij			      __FUNCTION__, rc,
1014257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1015231437Sluigi	return rc;
1016231437Sluigi}
1017231437Sluigi
1018231437Sluigi
1019231437Sluigi
1020231437Sluigi/**
1021231437Sluigi * @brief Function to get NIC statistics
1022231437Sluigi * @param sc 		software handle to the device
1023231437Sluigi * @param *stats	pointer to where to store statistics
1024231437Sluigi * @param reset_stats	resets statistics of set
1025231437Sluigi * @returns		0 on success, EIO on failure
1026231437Sluigi * @note		command depricated in Lancer
1027231437Sluigi */
1028231437Sluigiint
1029231437Sluigioce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
1030231437Sluigi{
1031231437Sluigi	struct oce_mbx mbx;
1032231437Sluigi	struct mbx_get_nic_stats *fwcmd;
1033231437Sluigi	int rc = 0;
1034231437Sluigi
1035231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1036231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats);
1037231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_nic_stats));
1038231437Sluigi
1039231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1040231437Sluigi				MBX_SUBSYSTEM_NIC,
1041231437Sluigi				NIC_GET_STATS,
1042231437Sluigi				MBX_TIMEOUT_SEC,
1043231437Sluigi				sizeof(struct mbx_get_nic_stats),
1044231437Sluigi				OCE_MBX_VER_V1);
1045231437Sluigi
1046231437Sluigi
1047231437Sluigi	mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
1048231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1049231437Sluigi
1050231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1051231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1052231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1053231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats);
1054231437Sluigi
1055231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_nic_stats);
1056231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1057231437Sluigi
1058231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1059231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1060247880Sdelphij	if (!rc)
1061247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1062247880Sdelphij	if (rc)
1063257007Sdelphij		device_printf(sc->dev,
1064257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1065257007Sdelphij			      __FUNCTION__, rc,
1066257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1067231437Sluigi	return rc;
1068231437Sluigi}
1069231437Sluigi
1070231437Sluigi
1071231437Sluigi/**
1072231437Sluigi * @brief Function to get pport (physical port) statistics
1073231437Sluigi * @param sc 		software handle to the device
1074231437Sluigi * @param *stats	pointer to where to store statistics
1075231437Sluigi * @param reset_stats	resets statistics of set
1076231437Sluigi * @returns		0 on success, EIO on failure
1077231437Sluigi */
1078231437Sluigiint
1079231437Sluigioce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1080231437Sluigi				uint32_t reset_stats)
1081231437Sluigi{
1082231437Sluigi	struct oce_mbx mbx;
1083231437Sluigi	struct mbx_get_pport_stats *fwcmd;
1084231437Sluigi	int rc = 0;
1085231437Sluigi
1086231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1087231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
1088231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
1089231437Sluigi
1090231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1091231437Sluigi				MBX_SUBSYSTEM_NIC,
1092231437Sluigi				NIC_GET_PPORT_STATS,
1093231437Sluigi				MBX_TIMEOUT_SEC,
1094231437Sluigi				sizeof(struct mbx_get_pport_stats),
1095231437Sluigi				OCE_MBX_VER_V0);
1096231437Sluigi
1097231437Sluigi	fwcmd->params.req.reset_stats = reset_stats;
1098247880Sdelphij	fwcmd->params.req.port_number = sc->port_id;
1099231437Sluigi
1100231437Sluigi	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1101231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1102231437Sluigi
1103231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1104231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1105231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1106231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
1107231437Sluigi
1108231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_pport_stats);
1109231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1110231437Sluigi
1111231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1112231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1113231437Sluigi
1114247880Sdelphij	if (!rc)
1115247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1116247880Sdelphij	if (rc)
1117257007Sdelphij		device_printf(sc->dev,
1118257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1119257007Sdelphij			      __FUNCTION__, rc,
1120257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1121231437Sluigi	return rc;
1122231437Sluigi}
1123231437Sluigi
1124231437Sluigi
1125231437Sluigi/**
1126231437Sluigi * @brief Function to get vport (virtual port) statistics
1127231437Sluigi * @param sc 		software handle to the device
1128231437Sluigi * @param *stats	pointer to where to store statistics
1129231437Sluigi * @param reset_stats	resets statistics of set
1130231437Sluigi * @returns		0 on success, EIO on failure
1131231437Sluigi */
1132231437Sluigiint
1133231437Sluigioce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1134231437Sluigi				uint32_t req_size, uint32_t reset_stats)
1135231437Sluigi{
1136231437Sluigi	struct oce_mbx mbx;
1137231437Sluigi	struct mbx_get_vport_stats *fwcmd;
1138231437Sluigi	int rc = 0;
1139231437Sluigi
1140231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1141231437Sluigi
1142231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
1143231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
1144231437Sluigi
1145231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1146231437Sluigi				MBX_SUBSYSTEM_NIC,
1147231437Sluigi				NIC_GET_VPORT_STATS,
1148231437Sluigi				MBX_TIMEOUT_SEC,
1149231437Sluigi				sizeof(struct mbx_get_vport_stats),
1150231437Sluigi				OCE_MBX_VER_V0);
1151231437Sluigi
1152231437Sluigi	fwcmd->params.req.reset_stats = reset_stats;
1153231437Sluigi	fwcmd->params.req.vport_number = sc->if_id;
1154231437Sluigi
1155231437Sluigi	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1156231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1157231437Sluigi
1158231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1159231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1160231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1161231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
1162231437Sluigi
1163231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_vport_stats);
1164231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1165231437Sluigi
1166231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1167231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1168231437Sluigi
1169247880Sdelphij	if (!rc)
1170247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1171247880Sdelphij	if (rc)
1172257007Sdelphij		device_printf(sc->dev,
1173257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1174257007Sdelphij			      __FUNCTION__, rc,
1175257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1176231437Sluigi	return rc;
1177231437Sluigi}
1178231437Sluigi
1179231437Sluigi
1180231437Sluigi/**
1181231437Sluigi * @brief               Function to update the muticast filter with
1182231437Sluigi *                      values in dma_mem
1183231437Sluigi * @param sc            software handle to the device
1184231437Sluigi * @param dma_mem       pointer to dma memory region
1185231437Sluigi * @returns             0 on success, EIO on failure
1186231437Sluigi */
1187231437Sluigiint
1188231437Sluigioce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
1189231437Sluigi{
1190231437Sluigi	struct oce_mbx mbx;
1191231437Sluigi	struct oce_mq_sge *sgl;
1192231437Sluigi	struct mbx_set_common_iface_multicast *req = NULL;
1193231437Sluigi	int rc = 0;
1194231437Sluigi
1195231437Sluigi	req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
1196231437Sluigi	mbx_common_req_hdr_init(&req->hdr, 0, 0,
1197231437Sluigi				MBX_SUBSYSTEM_COMMON,
1198231437Sluigi				OPCODE_COMMON_SET_IFACE_MULTICAST,
1199231437Sluigi				MBX_TIMEOUT_SEC,
1200231437Sluigi				sizeof(struct mbx_set_common_iface_multicast),
1201231437Sluigi				OCE_MBX_VER_V0);
1202231437Sluigi
1203231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1204231437Sluigi
1205231437Sluigi	mbx.u0.s.embedded = 0; /*Non embeded*/
1206231437Sluigi	mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
1207231437Sluigi	mbx.u0.s.sge_count = 1;
1208231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1209231437Sluigi	sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
1210231437Sluigi	sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
1211231437Sluigi	sgl->length = htole32(mbx.payload_length);
1212231437Sluigi
1213231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1214231437Sluigi
1215231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1216247880Sdelphij	if (!rc)
1217247880Sdelphij                rc = req->hdr.u0.rsp.status;
1218247880Sdelphij	if (rc)
1219257007Sdelphij		device_printf(sc->dev,
1220257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1221257007Sdelphij			      __FUNCTION__, rc,
1222257007Sdelphij			      req->hdr.u0.rsp.additional_status);
1223231437Sluigi	return rc;
1224231437Sluigi}
1225231437Sluigi
1226231437Sluigi
1227231437Sluigi/**
1228231437Sluigi * @brief               Function to send passthrough Ioctls
1229231437Sluigi * @param sc            software handle to the device
1230231437Sluigi * @param dma_mem       pointer to dma memory region
1231231437Sluigi * @param req_size      size of dma_mem
1232231437Sluigi * @returns             0 on success, EIO on failure
1233231437Sluigi */
1234231437Sluigiint
1235231437Sluigioce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
1236231437Sluigi{
1237231437Sluigi	struct oce_mbx mbx;
1238231437Sluigi	struct oce_mq_sge *sgl;
1239231437Sluigi	int rc = 0;
1240231437Sluigi
1241231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1242231437Sluigi
1243231437Sluigi	mbx.u0.s.embedded  = 0; /*Non embeded*/
1244231437Sluigi	mbx.payload_length = req_size;
1245231437Sluigi	mbx.u0.s.sge_count = 1;
1246231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1247231437Sluigi	sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
1248231437Sluigi	sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
1249231437Sluigi	sgl->length = htole32(req_size);
1250231437Sluigi
1251231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1252231437Sluigi
1253231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1254231437Sluigi	return rc;
1255231437Sluigi}
1256231437Sluigi
1257231437Sluigi
1258231437Sluigiint
1259231437Sluigioce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
1260231437Sluigi		 uint32_t if_id, uint32_t *pmac_id)
1261231437Sluigi{
1262231437Sluigi	struct oce_mbx mbx;
1263231437Sluigi	struct mbx_add_common_iface_mac *fwcmd;
1264231437Sluigi	int rc = 0;
1265231437Sluigi
1266231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1267231437Sluigi
1268231437Sluigi	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1269231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1270231437Sluigi				MBX_SUBSYSTEM_COMMON,
1271231437Sluigi				OPCODE_COMMON_ADD_IFACE_MAC,
1272231437Sluigi				MBX_TIMEOUT_SEC,
1273231437Sluigi				sizeof(struct mbx_add_common_iface_mac),
1274231437Sluigi				OCE_MBX_VER_V0);
1275231437Sluigi
1276231437Sluigi	fwcmd->params.req.if_id = (uint16_t) if_id;
1277231437Sluigi	bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
1278231437Sluigi
1279231437Sluigi	mbx.u0.s.embedded = 1;
1280231437Sluigi	mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
1281231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1282231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1283247880Sdelphij	if (!rc)
1284247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1285247880Sdelphij	if (rc) {
1286257007Sdelphij		device_printf(sc->dev,
1287257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1288257007Sdelphij			      __FUNCTION__, rc,
1289257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1290247880Sdelphij		goto error;
1291247880Sdelphij	}
1292231437Sluigi	*pmac_id = fwcmd->params.rsp.pmac_id;
1293247880Sdelphijerror:
1294231437Sluigi	return rc;
1295231437Sluigi}
1296231437Sluigi
1297231437Sluigi
1298231437Sluigiint
1299231437Sluigioce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
1300231437Sluigi{
1301231437Sluigi	struct oce_mbx mbx;
1302231437Sluigi	struct mbx_del_common_iface_mac *fwcmd;
1303231437Sluigi	int rc = 0;
1304231437Sluigi
1305231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1306231437Sluigi
1307231437Sluigi	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1308231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1309231437Sluigi				MBX_SUBSYSTEM_COMMON,
1310231437Sluigi				OPCODE_COMMON_DEL_IFACE_MAC,
1311231437Sluigi				MBX_TIMEOUT_SEC,
1312231437Sluigi				sizeof(struct mbx_del_common_iface_mac),
1313231437Sluigi				OCE_MBX_VER_V0);
1314231437Sluigi
1315231437Sluigi	fwcmd->params.req.if_id = (uint16_t)if_id;
1316231437Sluigi	fwcmd->params.req.pmac_id = pmac_id;
1317231437Sluigi
1318231437Sluigi	mbx.u0.s.embedded = 1;
1319231437Sluigi	mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
1320231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1321231437Sluigi
1322231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1323247880Sdelphij	if (!rc)
1324247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1325247880Sdelphij	if (rc)
1326257007Sdelphij		device_printf(sc->dev,
1327257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1328257007Sdelphij			      __FUNCTION__, rc,
1329257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1330231437Sluigi	return rc;
1331231437Sluigi}
1332231437Sluigi
1333231437Sluigi
1334231437Sluigi
1335231437Sluigiint
1336231437Sluigioce_mbox_check_native_mode(POCE_SOFTC sc)
1337231437Sluigi{
1338231437Sluigi	struct oce_mbx mbx;
1339231437Sluigi	struct mbx_common_set_function_cap *fwcmd;
1340231437Sluigi	int rc = 0;
1341231437Sluigi
1342231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1343231437Sluigi
1344231437Sluigi	fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
1345231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1346231437Sluigi				MBX_SUBSYSTEM_COMMON,
1347231437Sluigi				OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
1348231437Sluigi				MBX_TIMEOUT_SEC,
1349231437Sluigi				sizeof(struct mbx_common_set_function_cap),
1350231437Sluigi				OCE_MBX_VER_V0);
1351231437Sluigi
1352231437Sluigi	fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS |
1353231437Sluigi							CAP_BE3_NATIVE_ERX_API;
1354231437Sluigi
1355231437Sluigi	fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
1356231437Sluigi
1357231437Sluigi	mbx.u0.s.embedded = 1;
1358231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
1359231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1360231437Sluigi
1361231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1362247880Sdelphij	if (!rc)
1363247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1364247880Sdelphij	if (rc) {
1365257007Sdelphij		device_printf(sc->dev,
1366257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1367257007Sdelphij			      __FUNCTION__, rc,
1368257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1369247880Sdelphij		goto error;
1370247880Sdelphij	}
1371257007Sdelphij	sc->be3_native = HOST_32(fwcmd->params.rsp.capability_flags)
1372231437Sluigi			& CAP_BE3_NATIVE_ERX_API;
1373231437Sluigi
1374247880Sdelphijerror:
1375231437Sluigi	return 0;
1376231437Sluigi}
1377231437Sluigi
1378231437Sluigi
1379231437Sluigi
1380231437Sluigiint
1381231437Sluigioce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
1382231437Sluigi		uint8_t loopback_type, uint8_t enable)
1383231437Sluigi{
1384231437Sluigi	struct oce_mbx mbx;
1385231437Sluigi	struct mbx_lowlevel_set_loopback_mode *fwcmd;
1386231437Sluigi	int rc = 0;
1387231437Sluigi
1388231437Sluigi
1389231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1390231437Sluigi
1391231437Sluigi	fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
1392231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1393231437Sluigi				MBX_SUBSYSTEM_LOWLEVEL,
1394231437Sluigi				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
1395231437Sluigi				MBX_TIMEOUT_SEC,
1396231437Sluigi				sizeof(struct mbx_lowlevel_set_loopback_mode),
1397231437Sluigi				OCE_MBX_VER_V0);
1398231437Sluigi
1399231437Sluigi	fwcmd->params.req.src_port = port_num;
1400231437Sluigi	fwcmd->params.req.dest_port = port_num;
1401231437Sluigi	fwcmd->params.req.loopback_type = loopback_type;
1402231437Sluigi	fwcmd->params.req.loopback_state = enable;
1403231437Sluigi
1404231437Sluigi	mbx.u0.s.embedded = 1;
1405231437Sluigi	mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
1406231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1407231437Sluigi
1408231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1409247880Sdelphij	if (!rc)
1410247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1411247880Sdelphij	if (rc)
1412257007Sdelphij		device_printf(sc->dev,
1413257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1414257007Sdelphij			      __FUNCTION__, rc,
1415257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1416231437Sluigi
1417231437Sluigi	return rc;
1418231437Sluigi
1419231437Sluigi}
1420231437Sluigi
1421231437Sluigiint
1422231437Sluigioce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
1423231437Sluigi	uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
1424231437Sluigi	uint64_t pattern)
1425231437Sluigi{
1426231437Sluigi
1427231437Sluigi	struct oce_mbx mbx;
1428231437Sluigi	struct mbx_lowlevel_test_loopback_mode *fwcmd;
1429231437Sluigi	int rc = 0;
1430231437Sluigi
1431231437Sluigi
1432231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1433231437Sluigi
1434231437Sluigi	fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
1435231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1436231437Sluigi				MBX_SUBSYSTEM_LOWLEVEL,
1437231437Sluigi				OPCODE_LOWLEVEL_TEST_LOOPBACK,
1438231437Sluigi				MBX_TIMEOUT_SEC,
1439231437Sluigi				sizeof(struct mbx_lowlevel_test_loopback_mode),
1440231437Sluigi				OCE_MBX_VER_V0);
1441231437Sluigi
1442231437Sluigi	fwcmd->params.req.pattern = pattern;
1443231437Sluigi	fwcmd->params.req.src_port = port_num;
1444231437Sluigi	fwcmd->params.req.dest_port = port_num;
1445231437Sluigi	fwcmd->params.req.pkt_size = pkt_size;
1446231437Sluigi	fwcmd->params.req.num_pkts = num_pkts;
1447231437Sluigi	fwcmd->params.req.loopback_type = loopback_type;
1448231437Sluigi
1449231437Sluigi	mbx.u0.s.embedded = 1;
1450231437Sluigi	mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
1451231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1452231437Sluigi
1453231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1454247880Sdelphij	if (!rc)
1455247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1456231437Sluigi	if (rc)
1457257007Sdelphij		device_printf(sc->dev,
1458257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1459257007Sdelphij			      __FUNCTION__, rc,
1460257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1461231437Sluigi
1462247880Sdelphij	return rc;
1463231437Sluigi}
1464231437Sluigi
1465231437Sluigiint
1466231437Sluigioce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
1467231437Sluigi				POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
1468231437Sluigi{
1469231437Sluigi
1470231437Sluigi	struct oce_mbx mbx;
1471231437Sluigi	struct oce_mq_sge *sgl = NULL;
1472231437Sluigi	struct mbx_common_read_write_flashrom *fwcmd = NULL;
1473231437Sluigi	int rc = 0, payload_len = 0;
1474231437Sluigi
1475231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1476231437Sluigi	fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
1477231437Sluigi	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
1478231437Sluigi
1479231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1480231437Sluigi				MBX_SUBSYSTEM_COMMON,
1481231437Sluigi				OPCODE_COMMON_WRITE_FLASHROM,
1482231437Sluigi				LONG_TIMEOUT,
1483231437Sluigi				payload_len,
1484231437Sluigi				OCE_MBX_VER_V0);
1485231437Sluigi
1486257007Sdelphij	fwcmd->flash_op_type = LE_32(optype);
1487257007Sdelphij	fwcmd->flash_op_code = LE_32(opcode);
1488257007Sdelphij	fwcmd->data_buffer_size = LE_32(num_bytes);
1489231437Sluigi
1490231437Sluigi	mbx.u0.s.embedded  = 0; /*Non embeded*/
1491231437Sluigi	mbx.payload_length = payload_len;
1492231437Sluigi	mbx.u0.s.sge_count = 1;
1493231437Sluigi
1494231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1495231437Sluigi	sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
1496231437Sluigi	sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
1497231437Sluigi	sgl->length = payload_len;
1498231437Sluigi
1499231437Sluigi	/* post the command */
1500231879Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1501247880Sdelphij	if (!rc)
1502247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1503247880Sdelphij	if (rc)
1504257007Sdelphij		device_printf(sc->dev,
1505257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1506257007Sdelphij			      __FUNCTION__, rc,
1507257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1508231437Sluigi
1509231437Sluigi	return rc;
1510231437Sluigi
1511231437Sluigi}
1512231437Sluigi
1513231437Sluigiint
1514231437Sluigioce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
1515231437Sluigi				uint32_t offset, uint32_t optype)
1516231437Sluigi{
1517231437Sluigi
1518231437Sluigi	int rc = 0, payload_len = 0;
1519231437Sluigi	struct oce_mbx mbx;
1520231437Sluigi	struct mbx_common_read_write_flashrom *fwcmd;
1521231437Sluigi
1522231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1523231437Sluigi
1524231437Sluigi	fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
1525231437Sluigi
1526231437Sluigi	/* Firmware requires extra 4 bytes with this ioctl. Since there
1527231437Sluigi	   is enough room in the mbx payload it should be good enough
1528231437Sluigi	   Reference: Bug 14853
1529231437Sluigi	*/
1530231437Sluigi	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
1531231437Sluigi
1532231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1533231437Sluigi				MBX_SUBSYSTEM_COMMON,
1534231437Sluigi				OPCODE_COMMON_READ_FLASHROM,
1535231437Sluigi				MBX_TIMEOUT_SEC,
1536231437Sluigi				payload_len,
1537231437Sluigi				OCE_MBX_VER_V0);
1538231437Sluigi
1539231437Sluigi	fwcmd->flash_op_type = optype;
1540231437Sluigi	fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
1541231437Sluigi	fwcmd->data_offset = offset;
1542231437Sluigi	fwcmd->data_buffer_size = 0x4;
1543231437Sluigi
1544231437Sluigi	mbx.u0.s.embedded  = 1;
1545231437Sluigi	mbx.payload_length = payload_len;
1546231437Sluigi
1547231437Sluigi	/* post the command */
1548231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1549247880Sdelphij	if (!rc)
1550247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1551231437Sluigi	if (rc) {
1552257007Sdelphij		device_printf(sc->dev,
1553257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1554257007Sdelphij			      __FUNCTION__, rc,
1555257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1556247880Sdelphij		goto error;
1557231437Sluigi	}
1558247880Sdelphij	bcopy(fwcmd->data_buffer, flash_crc, 4);
1559247880Sdelphijerror:
1560231437Sluigi	return rc;
1561231437Sluigi}
1562231437Sluigi
1563231437Sluigiint
1564231437Sluigioce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
1565231437Sluigi{
1566231437Sluigi
1567231437Sluigi	struct oce_mbx mbx;
1568231437Sluigi	struct mbx_common_phy_info *fwcmd;
1569231437Sluigi	int rc = 0;
1570231437Sluigi
1571231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1572231437Sluigi
1573231437Sluigi	fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
1574231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1575231437Sluigi				MBX_SUBSYSTEM_COMMON,
1576231437Sluigi				OPCODE_COMMON_GET_PHY_CONFIG,
1577231437Sluigi				MBX_TIMEOUT_SEC,
1578231437Sluigi				sizeof(struct mbx_common_phy_info),
1579231437Sluigi				OCE_MBX_VER_V0);
1580231437Sluigi
1581231437Sluigi	mbx.u0.s.embedded = 1;
1582231437Sluigi	mbx.payload_length = sizeof(struct  mbx_common_phy_info);
1583231437Sluigi
1584231437Sluigi	/* now post the command */
1585231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1586247880Sdelphij	if (!rc)
1587247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1588231437Sluigi	if (rc) {
1589257007Sdelphij		device_printf(sc->dev,
1590257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1591257007Sdelphij			      __FUNCTION__, rc,
1592257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1593247880Sdelphij		goto error;
1594231437Sluigi	}
1595257007Sdelphij	phy_info->phy_type = HOST_16(fwcmd->params.rsp.phy_info.phy_type);
1596247880Sdelphij	phy_info->interface_type =
1597257007Sdelphij			HOST_16(fwcmd->params.rsp.phy_info.interface_type);
1598247880Sdelphij	phy_info->auto_speeds_supported =
1599257007Sdelphij		HOST_16(fwcmd->params.rsp.phy_info.auto_speeds_supported);
1600247880Sdelphij	phy_info->fixed_speeds_supported =
1601257007Sdelphij		HOST_16(fwcmd->params.rsp.phy_info.fixed_speeds_supported);
1602257007Sdelphij	phy_info->misc_params = HOST_32(fwcmd->params.rsp.phy_info.misc_params);
1603247880Sdelphijerror:
1604231437Sluigi	return rc;
1605231437Sluigi
1606231437Sluigi}
1607231437Sluigi
1608231437Sluigi
1609231437Sluigiint
1610231437Sluigioce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
1611231437Sluigi			uint32_t data_offset, POCE_DMA_MEM pdma_mem,
1612231437Sluigi			uint32_t *written_data, uint32_t *additional_status)
1613231437Sluigi{
1614231437Sluigi
1615231437Sluigi	struct oce_mbx mbx;
1616231437Sluigi	struct mbx_lancer_common_write_object *fwcmd = NULL;
1617231437Sluigi	int rc = 0, payload_len = 0;
1618231437Sluigi
1619231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1620231437Sluigi	payload_len = sizeof(struct mbx_lancer_common_write_object);
1621231437Sluigi
1622231437Sluigi	mbx.u0.s.embedded  = 1;/* Embedded */
1623231437Sluigi	mbx.payload_length = payload_len;
1624231437Sluigi	fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
1625231437Sluigi
1626231437Sluigi	/* initialize the ioctl header */
1627231437Sluigi	mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
1628231437Sluigi				MBX_SUBSYSTEM_COMMON,
1629231437Sluigi				OPCODE_COMMON_WRITE_OBJECT,
1630231437Sluigi				LONG_TIMEOUT,
1631231437Sluigi				payload_len,
1632231437Sluigi				OCE_MBX_VER_V0);
1633231437Sluigi
1634231437Sluigi	fwcmd->params.req.write_length = data_size;
1635231437Sluigi	if (data_size == 0)
1636231437Sluigi		fwcmd->params.req.eof = 1;
1637231437Sluigi	else
1638231437Sluigi		fwcmd->params.req.eof = 0;
1639231437Sluigi
1640231437Sluigi	strcpy(fwcmd->params.req.object_name, "/prg");
1641231437Sluigi	fwcmd->params.req.descriptor_count = 1;
1642231437Sluigi	fwcmd->params.req.write_offset = data_offset;
1643231437Sluigi	fwcmd->params.req.buffer_length = data_size;
1644231437Sluigi	fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
1645231437Sluigi	fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
1646231437Sluigi
1647231437Sluigi	/* post the command */
1648231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1649247880Sdelphij	if (!rc)
1650247880Sdelphij                rc = fwcmd->params.rsp.status;
1651231437Sluigi	if (rc) {
1652257007Sdelphij		device_printf(sc->dev,
1653257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1654257007Sdelphij			      __FUNCTION__, rc,
1655257007Sdelphij			      fwcmd->params.rsp.additional_status);
1656247880Sdelphij		goto error;
1657231437Sluigi	}
1658257007Sdelphij	*written_data = HOST_32(fwcmd->params.rsp.actual_write_length);
1659247880Sdelphij	*additional_status = fwcmd->params.rsp.additional_status;
1660247880Sdelphijerror:
1661231437Sluigi	return rc;
1662231437Sluigi
1663231437Sluigi}
1664231437Sluigi
1665231437Sluigi
1666231437Sluigi
1667231437Sluigiint
1668231437Sluigioce_mbox_create_rq(struct oce_rq *rq)
1669231437Sluigi{
1670231437Sluigi
1671231437Sluigi	struct oce_mbx mbx;
1672231437Sluigi	struct mbx_create_nic_rq *fwcmd;
1673231437Sluigi	POCE_SOFTC sc = rq->parent;
1674231437Sluigi	int rc, num_pages = 0;
1675231437Sluigi
1676231437Sluigi	if (rq->qstate == QCREATED)
1677231437Sluigi		return 0;
1678231437Sluigi
1679231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1680231437Sluigi
1681231437Sluigi	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
1682231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1683231437Sluigi				MBX_SUBSYSTEM_NIC,
1684231437Sluigi				NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
1685231437Sluigi				sizeof(struct mbx_create_nic_rq),
1686231437Sluigi				OCE_MBX_VER_V0);
1687231437Sluigi
1688231437Sluigi	/* oce_page_list will also prepare pages */
1689231437Sluigi	num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
1690231437Sluigi
1691231437Sluigi	if (IS_XE201(sc)) {
1692231437Sluigi		fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
1693231437Sluigi		fwcmd->params.req.page_size = 1;
1694231437Sluigi		fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
1695231437Sluigi	} else
1696231437Sluigi		fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
1697231437Sluigi	fwcmd->params.req.num_pages = num_pages;
1698231437Sluigi	fwcmd->params.req.cq_id = rq->cq->cq_id;
1699231437Sluigi	fwcmd->params.req.if_id = sc->if_id;
1700231437Sluigi	fwcmd->params.req.max_frame_size = rq->cfg.mtu;
1701231437Sluigi	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
1702231437Sluigi
1703231437Sluigi	mbx.u0.s.embedded = 1;
1704231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_nic_rq);
1705231437Sluigi
1706231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1707247880Sdelphij	if (!rc)
1708247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1709247880Sdelphij	if (rc) {
1710257007Sdelphij		device_printf(sc->dev,
1711257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1712257007Sdelphij			      __FUNCTION__, rc,
1713257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1714231437Sluigi		goto error;
1715247880Sdelphij	}
1716257007Sdelphij	rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
1717231437Sluigi	rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
1718231437Sluigierror:
1719231437Sluigi	return rc;
1720231437Sluigi
1721231437Sluigi}
1722231437Sluigi
1723231437Sluigi
1724231437Sluigi
1725231437Sluigiint
1726231437Sluigioce_mbox_create_wq(struct oce_wq *wq)
1727231437Sluigi{
1728231437Sluigi	struct oce_mbx mbx;
1729231437Sluigi	struct mbx_create_nic_wq *fwcmd;
1730231437Sluigi	POCE_SOFTC sc = wq->parent;
1731231437Sluigi	int rc = 0, version, num_pages;
1732231437Sluigi
1733231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1734231437Sluigi
1735231437Sluigi	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
1736257007Sdelphij	if (IS_XE201(sc))
1737231437Sluigi		version = OCE_MBX_VER_V1;
1738257007Sdelphij	else if(IS_BE(sc))
1739252869Sdelphij		IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2)
1740252869Sdelphij					 : (version = OCE_MBX_VER_V0);
1741252869Sdelphij	else
1742252869Sdelphij		version = OCE_MBX_VER_V2;
1743231437Sluigi
1744257007Sdelphij	if (version > OCE_MBX_VER_V0)
1745257007Sdelphij		fwcmd->params.req.if_id = sc->if_id;
1746257007Sdelphij
1747231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1748231437Sluigi				MBX_SUBSYSTEM_NIC,
1749231437Sluigi				NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
1750231437Sluigi				sizeof(struct mbx_create_nic_wq),
1751231437Sluigi				version);
1752231437Sluigi
1753231437Sluigi	num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
1754231437Sluigi
1755231437Sluigi	fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
1756231437Sluigi	fwcmd->params.req.num_pages = num_pages;
1757231437Sluigi	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
1758231437Sluigi	fwcmd->params.req.cq_id = wq->cq->cq_id;
1759231437Sluigi	fwcmd->params.req.ulp_num = 1;
1760231437Sluigi
1761231437Sluigi	mbx.u0.s.embedded = 1;
1762231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_nic_wq);
1763231437Sluigi
1764231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1765247880Sdelphij	if (!rc)
1766247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1767247880Sdelphij	if (rc) {
1768257007Sdelphij		device_printf(sc->dev,
1769257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1770257007Sdelphij			      __FUNCTION__, rc,
1771257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1772231437Sluigi		goto error;
1773247880Sdelphij	}
1774257007Sdelphij	wq->wq_id = HOST_16(fwcmd->params.rsp.wq_id);
1775252869Sdelphij	if (version == OCE_MBX_VER_V2)
1776257007Sdelphij		wq->db_offset = HOST_32(fwcmd->params.rsp.db_offset);
1777252869Sdelphij	else
1778252869Sdelphij		wq->db_offset = PD_TXULP_DB;
1779231437Sluigierror:
1780231437Sluigi	return rc;
1781231437Sluigi
1782231437Sluigi}
1783231437Sluigi
1784231437Sluigi
1785231437Sluigi
1786231437Sluigiint
1787231437Sluigioce_mbox_create_eq(struct oce_eq *eq)
1788231437Sluigi{
1789231437Sluigi	struct oce_mbx mbx;
1790231437Sluigi	struct mbx_create_common_eq *fwcmd;
1791231437Sluigi	POCE_SOFTC sc = eq->parent;
1792231437Sluigi	int rc = 0;
1793231437Sluigi	uint32_t num_pages;
1794231437Sluigi
1795231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1796231437Sluigi
1797231437Sluigi	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
1798231437Sluigi
1799231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1800231437Sluigi				MBX_SUBSYSTEM_COMMON,
1801231437Sluigi				OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
1802231437Sluigi				sizeof(struct mbx_create_common_eq),
1803231437Sluigi				OCE_MBX_VER_V0);
1804231437Sluigi
1805231437Sluigi	num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
1806231437Sluigi	fwcmd->params.req.ctx.num_pages = num_pages;
1807231437Sluigi	fwcmd->params.req.ctx.valid = 1;
1808231437Sluigi	fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
1809231437Sluigi	fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
1810231437Sluigi	fwcmd->params.req.ctx.armed = 0;
1811231437Sluigi	fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
1812231437Sluigi
1813231437Sluigi
1814231437Sluigi	mbx.u0.s.embedded = 1;
1815231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_eq);
1816231437Sluigi
1817231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1818247880Sdelphij	if (!rc)
1819247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1820247880Sdelphij	if (rc) {
1821257007Sdelphij		device_printf(sc->dev,
1822257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1823257007Sdelphij			      __FUNCTION__, rc,
1824257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1825231437Sluigi		goto error;
1826247880Sdelphij	}
1827257007Sdelphij	eq->eq_id = HOST_16(fwcmd->params.rsp.eq_id);
1828231437Sluigierror:
1829231437Sluigi	return rc;
1830231437Sluigi}
1831231437Sluigi
1832231437Sluigi
1833231437Sluigi
1834231437Sluigiint
1835231437Sluigioce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
1836231437Sluigi{
1837231437Sluigi	struct oce_mbx mbx;
1838231437Sluigi	struct mbx_create_common_cq *fwcmd;
1839231437Sluigi	POCE_SOFTC sc = cq->parent;
1840231437Sluigi	uint8_t version;
1841231437Sluigi	oce_cq_ctx_t *ctx;
1842231437Sluigi	uint32_t num_pages, page_size;
1843231437Sluigi	int rc = 0;
1844231437Sluigi
1845231437Sluigi
1846231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1847231437Sluigi
1848231437Sluigi	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
1849231437Sluigi
1850231437Sluigi	if (IS_XE201(sc))
1851231437Sluigi		version = OCE_MBX_VER_V2;
1852231437Sluigi	else
1853231437Sluigi		version = OCE_MBX_VER_V0;
1854231437Sluigi
1855231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1856231437Sluigi				MBX_SUBSYSTEM_COMMON,
1857231437Sluigi				OPCODE_COMMON_CREATE_CQ,
1858231437Sluigi				MBX_TIMEOUT_SEC,
1859231437Sluigi				sizeof(struct mbx_create_common_cq),
1860231437Sluigi				version);
1861231437Sluigi
1862231437Sluigi	ctx = &fwcmd->params.req.cq_ctx;
1863231437Sluigi
1864231437Sluigi	num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
1865231437Sluigi	page_size =  1;  /* 1 for 4K */
1866231437Sluigi
1867231437Sluigi	if (version == OCE_MBX_VER_V2) {
1868231437Sluigi		ctx->v2.num_pages = LE_16(num_pages);
1869231437Sluigi		ctx->v2.page_size = page_size;
1870231437Sluigi		ctx->v2.eventable = is_eventable;
1871231437Sluigi		ctx->v2.valid = 1;
1872231437Sluigi		ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1873231437Sluigi		ctx->v2.nodelay = cq->cq_cfg.nodelay;
1874231437Sluigi		ctx->v2.coalesce_wm = ncoalesce;
1875231437Sluigi		ctx->v2.armed = 0;
1876231437Sluigi		ctx->v2.eq_id = cq->eq->eq_id;
1877231437Sluigi		if (ctx->v2.count == 3) {
1878269693Simp			if ((u_int)cq->cq_cfg.q_len > (4*1024)-1)
1879231437Sluigi				ctx->v2.cqe_count = (4*1024)-1;
1880231437Sluigi			else
1881231437Sluigi				ctx->v2.cqe_count = cq->cq_cfg.q_len;
1882231437Sluigi		}
1883231437Sluigi	} else {
1884231437Sluigi		ctx->v0.num_pages = LE_16(num_pages);
1885231437Sluigi		ctx->v0.eventable = is_eventable;
1886231437Sluigi		ctx->v0.valid = 1;
1887231437Sluigi		ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1888231437Sluigi		ctx->v0.nodelay = cq->cq_cfg.nodelay;
1889231437Sluigi		ctx->v0.coalesce_wm = ncoalesce;
1890231437Sluigi		ctx->v0.armed = 0;
1891231437Sluigi		ctx->v0.eq_id = cq->eq->eq_id;
1892231437Sluigi	}
1893231437Sluigi
1894231437Sluigi	mbx.u0.s.embedded = 1;
1895231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_cq);
1896231437Sluigi
1897231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1898247880Sdelphij	if (!rc)
1899247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1900247880Sdelphij	if (rc) {
1901257007Sdelphij		device_printf(sc->dev,
1902257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1903257007Sdelphij			      __FUNCTION__, rc,
1904257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1905231437Sluigi		goto error;
1906247880Sdelphij	}
1907257007Sdelphij	cq->cq_id = HOST_16(fwcmd->params.rsp.cq_id);
1908247880Sdelphijerror:
1909247880Sdelphij	return rc;
1910231437Sluigi
1911247880Sdelphij}
1912247880Sdelphij
1913247880Sdelphijint
1914247880Sdelphijoce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
1915247880Sdelphij{
1916247880Sdelphij	int rc = 0;
1917247880Sdelphij	struct oce_mbx mbx;
1918247880Sdelphij	struct mbx_read_common_transrecv_data *fwcmd;
1919247880Sdelphij	struct oce_mq_sge *sgl;
1920247880Sdelphij	OCE_DMA_MEM dma;
1921247880Sdelphij
1922247880Sdelphij	/* Allocate DMA mem*/
1923247880Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data),
1924247880Sdelphij				&dma, 0))
1925247880Sdelphij		return ENOMEM;
1926247880Sdelphij
1927247880Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data);
1928247880Sdelphij	bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data));
1929247880Sdelphij
1930247880Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
1931247880Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1932247880Sdelphij			MBX_SUBSYSTEM_COMMON,
1933247880Sdelphij			OPCODE_COMMON_READ_TRANSRECEIVER_DATA,
1934247880Sdelphij			MBX_TIMEOUT_SEC,
1935247880Sdelphij			sizeof(struct mbx_read_common_transrecv_data),
1936247880Sdelphij			OCE_MBX_VER_V0);
1937247880Sdelphij
1938247880Sdelphij	/* fill rest of mbx */
1939247880Sdelphij	mbx.u0.s.embedded = 0;
1940247880Sdelphij	mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data);
1941247880Sdelphij	mbx.u0.s.sge_count = 1;
1942247880Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
1943247880Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
1944247880Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
1945247880Sdelphij	sgl->length = htole32(mbx.payload_length);
1946247880Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1947247880Sdelphij
1948247880Sdelphij	fwcmd->params.req.port = LE_32(sc->port_id);
1949247880Sdelphij	fwcmd->params.req.page_num = LE_32(page_num);
1950247880Sdelphij
1951247880Sdelphij	/* command post */
1952247880Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
1953247880Sdelphij	if (!rc)
1954252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
1955247880Sdelphij	if (rc) {
1956257007Sdelphij		device_printf(sc->dev,
1957257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1958257007Sdelphij			      __FUNCTION__, rc,
1959257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1960247880Sdelphij		goto error;
1961247880Sdelphij	}
1962247880Sdelphij	if(fwcmd->params.rsp.page_num == PAGE_NUM_A0)
1963247880Sdelphij	{
1964247880Sdelphij		bcopy((char *)fwcmd->params.rsp.page_data,
1965247880Sdelphij				(char *)&sfp_vpd_dump_buffer[0],
1966247880Sdelphij				TRANSCEIVER_A0_SIZE);
1967247880Sdelphij	}
1968247880Sdelphij
1969247880Sdelphij	if(fwcmd->params.rsp.page_num == PAGE_NUM_A2)
1970247880Sdelphij	{
1971247880Sdelphij		bcopy((char *)fwcmd->params.rsp.page_data,
1972247880Sdelphij				(char *)&sfp_vpd_dump_buffer[32],
1973247880Sdelphij				TRANSCEIVER_A2_SIZE);
1974247880Sdelphij	}
1975231437Sluigierror:
1976252869Sdelphij	oce_dma_free(sc, &dma);
1977231437Sluigi	return rc;
1978247880Sdelphij}
1979231437Sluigi
1980247880Sdelphijvoid
1981247880Sdelphijoce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
1982247880Sdelphij				int num)
1983247880Sdelphij{
1984247880Sdelphij	struct oce_mbx mbx;
1985247880Sdelphij	struct mbx_modify_common_eq_delay *fwcmd;
1986247880Sdelphij	int rc = 0;
1987247880Sdelphij	int i = 0;
1988247880Sdelphij
1989247880Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
1990247880Sdelphij
1991247880Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
1992247880Sdelphij	fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
1993247880Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1994247880Sdelphij				MBX_SUBSYSTEM_COMMON,
1995247880Sdelphij				OPCODE_COMMON_MODIFY_EQ_DELAY,
1996247880Sdelphij				MBX_TIMEOUT_SEC,
1997247880Sdelphij				sizeof(struct mbx_modify_common_eq_delay),
1998247880Sdelphij				OCE_MBX_VER_V0);
1999247880Sdelphij	/* fill rest of mbx */
2000247880Sdelphij	mbx.u0.s.embedded = 1;
2001247880Sdelphij	mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay);
2002247880Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2003247880Sdelphij
2004247880Sdelphij	fwcmd->params.req.num_eq = num;
2005247880Sdelphij	for (i = 0; i < num; i++) {
2006247880Sdelphij		fwcmd->params.req.delay[i].eq_id =
2007247880Sdelphij					htole32(set_eqd[i].eq_id);
2008247880Sdelphij		fwcmd->params.req.delay[i].phase = 0;
2009247880Sdelphij		fwcmd->params.req.delay[i].dm =
2010247880Sdelphij		htole32(set_eqd[i].delay_multiplier);
2011247880Sdelphij	}
2012247880Sdelphij
2013247880Sdelphij
2014247880Sdelphij	/* command post */
2015247880Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
2016247880Sdelphij
2017247880Sdelphij	if (!rc)
2018252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
2019247880Sdelphij	if (rc)
2020257007Sdelphij		device_printf(sc->dev,
2021257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
2022257007Sdelphij			      __FUNCTION__, rc,
2023257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
2024231437Sluigi}
2025247880Sdelphij
2026252869Sdelphijint
2027258941Sdelphijoce_get_profile_config(POCE_SOFTC sc, uint32_t max_rss)
2028252869Sdelphij{
2029252869Sdelphij	struct oce_mbx mbx;
2030252869Sdelphij	struct mbx_common_get_profile_config *fwcmd;
2031252869Sdelphij	int rc = 0;
2032252869Sdelphij	int version = 0;
2033252869Sdelphij	struct oce_mq_sge *sgl;
2034252869Sdelphij	OCE_DMA_MEM dma;
2035252869Sdelphij	uint32_t desc_count = 0;
2036252869Sdelphij	struct oce_nic_resc_desc *nic_desc = NULL;
2037252869Sdelphij	int i;
2038252869Sdelphij	boolean_t nic_desc_valid = FALSE;
2039247880Sdelphij
2040252869Sdelphij	if (IS_BE2(sc))
2041252869Sdelphij		return -1;
2042252869Sdelphij
2043252869Sdelphij	/* Allocate DMA mem*/
2044252869Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config),
2045252869Sdelphij			  &dma, 0))
2046252869Sdelphij		return ENOMEM;
2047252869Sdelphij
2048252869Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
2049252869Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config);
2050252869Sdelphij	bzero(fwcmd, sizeof(struct mbx_common_get_profile_config));
2051252869Sdelphij
2052258941Sdelphij	if (!IS_XE201(sc))
2053252869Sdelphij		version = OCE_MBX_VER_V1;
2054252869Sdelphij	else
2055252869Sdelphij		version = OCE_MBX_VER_V0;
2056252869Sdelphij
2057252869Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
2058252869Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2059252869Sdelphij				MBX_SUBSYSTEM_COMMON,
2060252869Sdelphij				OPCODE_COMMON_GET_PROFILE_CONFIG,
2061252869Sdelphij				MBX_TIMEOUT_SEC,
2062252869Sdelphij				sizeof(struct mbx_common_get_profile_config),
2063252869Sdelphij				version);
2064252869Sdelphij	/* fill rest of mbx */
2065252869Sdelphij	mbx.u0.s.embedded = 0;
2066252869Sdelphij	mbx.payload_length = sizeof(struct mbx_common_get_profile_config);
2067252869Sdelphij	mbx.u0.s.sge_count = 1;
2068252869Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
2069252869Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2070252869Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2071252869Sdelphij	sgl->length = htole32(mbx.payload_length);
2072252869Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2073252869Sdelphij
2074252869Sdelphij	fwcmd->params.req.type = ACTIVE_PROFILE;
2075252869Sdelphij
2076252869Sdelphij	/* command post */
2077252869Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
2078252869Sdelphij	if (!rc)
2079252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
2080252869Sdelphij	if (rc) {
2081257007Sdelphij		device_printf(sc->dev,
2082257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
2083257007Sdelphij			      __FUNCTION__, rc,
2084257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
2085252869Sdelphij		goto error;
2086252869Sdelphij	}
2087252869Sdelphij
2088252869Sdelphij	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2089252869Sdelphij	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2090252869Sdelphij	for (i = 0; i < desc_count; i++) {
2091252869Sdelphij		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2092252869Sdelphij		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2093252869Sdelphij			nic_desc_valid = TRUE;
2094252869Sdelphij			break;
2095252869Sdelphij		}
2096252869Sdelphij		nic_desc = (struct oce_nic_resc_desc *) \
2097252869Sdelphij				((char *)nic_desc + nic_desc->desc_len);
2098252869Sdelphij	}
2099252869Sdelphij	if (!nic_desc_valid) {
2100252869Sdelphij		rc = -1;
2101252869Sdelphij		goto error;
2102252869Sdelphij	}
2103252869Sdelphij	else {
2104258941Sdelphij		sc->max_vlans = HOST_16(nic_desc->vlan_count);
2105258941Sdelphij		sc->nwqs = HOST_16(nic_desc->txq_count);
2106252869Sdelphij		if (sc->nwqs)
2107252869Sdelphij			sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2108252869Sdelphij		else
2109252869Sdelphij			sc->nwqs = OCE_MAX_WQ;
2110252869Sdelphij
2111258941Sdelphij		sc->nrssqs = HOST_16(nic_desc->rssq_count);
2112258941Sdelphij		if (sc->nrssqs)
2113258941Sdelphij			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2114258941Sdelphij		else
2115258941Sdelphij			sc->nrssqs = max_rss;
2116297793Spfg		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
2117258941Sdelphij
2118252869Sdelphij	}
2119252869Sdelphijerror:
2120252869Sdelphij	oce_dma_free(sc, &dma);
2121252869Sdelphij	return rc;
2122252869Sdelphij
2123252869Sdelphij}
2124252869Sdelphij
2125252869Sdelphijint
2126252869Sdelphijoce_get_func_config(POCE_SOFTC sc)
2127252869Sdelphij{
2128252869Sdelphij	struct oce_mbx mbx;
2129252869Sdelphij	struct mbx_common_get_func_config *fwcmd;
2130252869Sdelphij	int rc = 0;
2131252869Sdelphij	int version = 0;
2132252869Sdelphij	struct oce_mq_sge *sgl;
2133252869Sdelphij	OCE_DMA_MEM dma;
2134252869Sdelphij	uint32_t desc_count = 0;
2135252869Sdelphij	struct oce_nic_resc_desc *nic_desc = NULL;
2136252869Sdelphij	int i;
2137252869Sdelphij	boolean_t nic_desc_valid = FALSE;
2138252869Sdelphij	uint32_t max_rss = 0;
2139252869Sdelphij
2140252869Sdelphij	if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
2141252869Sdelphij		max_rss = OCE_LEGACY_MODE_RSS;
2142252869Sdelphij	else
2143252869Sdelphij		max_rss = OCE_MAX_RSS;
2144252869Sdelphij
2145252869Sdelphij	/* Allocate DMA mem*/
2146252869Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config),
2147252869Sdelphij			  &dma, 0))
2148252869Sdelphij		return ENOMEM;
2149252869Sdelphij
2150252869Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
2151252869Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config);
2152252869Sdelphij	bzero(fwcmd, sizeof(struct mbx_common_get_func_config));
2153252869Sdelphij
2154252869Sdelphij	if (IS_SH(sc))
2155252869Sdelphij		version = OCE_MBX_VER_V1;
2156252869Sdelphij	else
2157252869Sdelphij		version = OCE_MBX_VER_V0;
2158252869Sdelphij
2159252869Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
2160252869Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2161252869Sdelphij				MBX_SUBSYSTEM_COMMON,
2162252869Sdelphij				OPCODE_COMMON_GET_FUNCTION_CONFIG,
2163252869Sdelphij				MBX_TIMEOUT_SEC,
2164252869Sdelphij				sizeof(struct mbx_common_get_func_config),
2165252869Sdelphij				version);
2166252869Sdelphij	/* fill rest of mbx */
2167252869Sdelphij	mbx.u0.s.embedded = 0;
2168252869Sdelphij	mbx.payload_length = sizeof(struct mbx_common_get_func_config);
2169252869Sdelphij	mbx.u0.s.sge_count = 1;
2170252869Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
2171252869Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2172252869Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2173252869Sdelphij	sgl->length = htole32(mbx.payload_length);
2174252869Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2175252869Sdelphij
2176252869Sdelphij	/* command post */
2177252869Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
2178252869Sdelphij	if (!rc)
2179252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
2180252869Sdelphij	if (rc) {
2181257007Sdelphij		device_printf(sc->dev,
2182257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
2183257007Sdelphij			      __FUNCTION__, rc,
2184257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
2185252869Sdelphij		goto error;
2186252869Sdelphij	}
2187252869Sdelphij
2188252869Sdelphij	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2189252869Sdelphij	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2190252869Sdelphij	for (i = 0; i < desc_count; i++) {
2191252869Sdelphij		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2192252869Sdelphij		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2193252869Sdelphij			nic_desc_valid = TRUE;
2194252869Sdelphij			break;
2195252869Sdelphij		}
2196252869Sdelphij		nic_desc = (struct oce_nic_resc_desc *) \
2197252869Sdelphij				((char *)nic_desc + nic_desc->desc_len);
2198252869Sdelphij	}
2199252869Sdelphij	if (!nic_desc_valid) {
2200252869Sdelphij		rc = -1;
2201252869Sdelphij		goto error;
2202252869Sdelphij	}
2203252869Sdelphij	else {
2204257007Sdelphij		sc->max_vlans = nic_desc->vlan_count;
2205252869Sdelphij		sc->nwqs = HOST_32(nic_desc->txq_count);
2206252869Sdelphij                if (sc->nwqs)
2207252869Sdelphij                        sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2208252869Sdelphij                else
2209252869Sdelphij                        sc->nwqs = OCE_MAX_WQ;
2210252869Sdelphij
2211252869Sdelphij		sc->nrssqs = HOST_32(nic_desc->rssq_count);
2212252869Sdelphij		if (sc->nrssqs)
2213252869Sdelphij			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2214252869Sdelphij		else
2215252869Sdelphij			sc->nrssqs = max_rss;
2216297793Spfg		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
2217252869Sdelphij	}
2218252869Sdelphijerror:
2219252869Sdelphij	oce_dma_free(sc, &dma);
2220252869Sdelphij	return rc;
2221252869Sdelphij
2222252869Sdelphij}
2223