oce_mbox.c revision 231437
1231437Sluigi/*-
2231437Sluigi * Copyright (C) 2012 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
40231437Sluigi
41231437Sluigi/* $FreeBSD: head/sys/dev/oce/oce_mbox.c 231437 2012-02-10 21:03:04Z luigi $ */
42231437Sluigi
43231437Sluigi
44231437Sluigi#include "oce_if.h"
45231437Sluigi
46231437Sluigi
47231437Sluigi/**
48231437Sluigi * @brief Reset (firmware) common function
49231437Sluigi * @param sc		software handle to the device
50231437Sluigi * @returns		0 on success, ETIMEDOUT on failure
51231437Sluigi */
52231437Sluigiint
53231437Sluigioce_reset_fun(POCE_SOFTC sc)
54231437Sluigi{
55231437Sluigi	struct oce_mbx *mbx;
56231437Sluigi	struct oce_bmbx *mb;
57231437Sluigi	struct ioctl_common_function_reset *fwcmd;
58231437Sluigi	int rc = 0;
59231437Sluigi
60231437Sluigi	if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) {
61231437Sluigi		mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
62231437Sluigi		mbx = &mb->mbx;
63231437Sluigi		bzero(mbx, sizeof(struct oce_mbx));
64231437Sluigi
65231437Sluigi		fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
66231437Sluigi		mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
67231437Sluigi					MBX_SUBSYSTEM_COMMON,
68231437Sluigi					OPCODE_COMMON_FUNCTION_RESET,
69231437Sluigi					10,	/* MBX_TIMEOUT_SEC */
70231437Sluigi					sizeof(struct
71231437Sluigi					    ioctl_common_function_reset),
72231437Sluigi					OCE_MBX_VER_V0);
73231437Sluigi
74231437Sluigi		mbx->u0.s.embedded = 1;
75231437Sluigi		mbx->payload_length =
76231437Sluigi		    sizeof(struct ioctl_common_function_reset);
77231437Sluigi
78231437Sluigi		rc = oce_mbox_dispatch(sc, 2);
79231437Sluigi	}
80231437Sluigi
81231437Sluigi	return rc;
82231437Sluigi}
83231437Sluigi
84231437Sluigi
85231437Sluigi/**
86231437Sluigi * @brief  		This funtions tells firmware we are
87231437Sluigi *			done with commands.
88231437Sluigi * @param sc            software handle to the device
89231437Sluigi * @returns             0 on success, ETIMEDOUT on failure
90231437Sluigi */
91231437Sluigiint
92231437Sluigioce_fw_clean(POCE_SOFTC sc)
93231437Sluigi{
94231437Sluigi	struct oce_bmbx *mbx;
95231437Sluigi	uint8_t *ptr;
96231437Sluigi	int ret = 0;
97231437Sluigi
98231437Sluigi	mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
99231437Sluigi	ptr = (uint8_t *) &mbx->mbx;
100231437Sluigi
101231437Sluigi	/* Endian Signature */
102231437Sluigi	*ptr++ = 0xff;
103231437Sluigi	*ptr++ = 0xaa;
104231437Sluigi	*ptr++ = 0xbb;
105231437Sluigi	*ptr++ = 0xff;
106231437Sluigi	*ptr++ = 0xff;
107231437Sluigi	*ptr++ = 0xcc;
108231437Sluigi	*ptr++ = 0xdd;
109231437Sluigi	*ptr = 0xff;
110231437Sluigi
111231437Sluigi	ret = oce_mbox_dispatch(sc, 2);
112231437Sluigi
113231437Sluigi	return ret;
114231437Sluigi}
115231437Sluigi
116231437Sluigi
117231437Sluigi/**
118231437Sluigi * @brief Mailbox wait
119231437Sluigi * @param sc		software handle to the device
120231437Sluigi * @param tmo_sec	timeout in seconds
121231437Sluigi */
122231437Sluigistatic int
123231437Sluigioce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
124231437Sluigi{
125231437Sluigi	tmo_sec *= 10000;
126231437Sluigi	pd_mpu_mbox_db_t mbox_db;
127231437Sluigi
128231437Sluigi	for (;;) {
129231437Sluigi		if (tmo_sec != 0) {
130231437Sluigi			if (--tmo_sec == 0)
131231437Sluigi				break;
132231437Sluigi		}
133231437Sluigi
134231437Sluigi		mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
135231437Sluigi
136231437Sluigi		if (mbox_db.bits.ready)
137231437Sluigi			return 0;
138231437Sluigi
139231437Sluigi		DELAY(100);
140231437Sluigi	}
141231437Sluigi
142231437Sluigi	device_printf(sc->dev, "Mailbox timed out\n");
143231437Sluigi
144231437Sluigi	return ETIMEDOUT;
145231437Sluigi}
146231437Sluigi
147231437Sluigi
148231437Sluigi
149231437Sluigi/**
150231437Sluigi * @brief Mailbox dispatch
151231437Sluigi * @param sc		software handle to the device
152231437Sluigi * @param tmo_sec	timeout in seconds
153231437Sluigi */
154231437Sluigiint
155231437Sluigioce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
156231437Sluigi{
157231437Sluigi	pd_mpu_mbox_db_t mbox_db;
158231437Sluigi	uint32_t pa;
159231437Sluigi	int rc;
160231437Sluigi
161231437Sluigi	oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
162231437Sluigi	pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
163231437Sluigi	bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
164231437Sluigi	mbox_db.bits.ready = 0;
165231437Sluigi	mbox_db.bits.hi = 1;
166231437Sluigi	mbox_db.bits.address = pa;
167231437Sluigi
168231437Sluigi	rc = oce_mbox_wait(sc, tmo_sec);
169231437Sluigi	if (rc == 0) {
170231437Sluigi		OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
171231437Sluigi
172231437Sluigi		pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
173231437Sluigi		mbox_db.bits.ready = 0;
174231437Sluigi		mbox_db.bits.hi = 0;
175231437Sluigi		mbox_db.bits.address = pa;
176231437Sluigi
177231437Sluigi		rc = oce_mbox_wait(sc, tmo_sec);
178231437Sluigi
179231437Sluigi		if (rc == 0) {
180231437Sluigi			OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
181231437Sluigi
182231437Sluigi			rc = oce_mbox_wait(sc, tmo_sec);
183231437Sluigi
184231437Sluigi			oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
185231437Sluigi		}
186231437Sluigi	}
187231437Sluigi
188231437Sluigi	return rc;
189231437Sluigi}
190231437Sluigi
191231437Sluigi
192231437Sluigi
193231437Sluigi/**
194231437Sluigi * @brief 		Mailbox common request header initialization
195231437Sluigi * @param hdr		mailbox header
196231437Sluigi * @param dom		domain
197231437Sluigi * @param port		port
198231437Sluigi * @param subsys	subsystem
199231437Sluigi * @param opcode	opcode
200231437Sluigi * @param timeout	timeout
201231437Sluigi * @param pyld_len	payload length
202231437Sluigi */
203231437Sluigivoid
204231437Sluigimbx_common_req_hdr_init(struct mbx_hdr *hdr,
205231437Sluigi			uint8_t dom, uint8_t port,
206231437Sluigi			uint8_t subsys, uint8_t opcode,
207231437Sluigi			uint32_t timeout, uint32_t pyld_len,
208231437Sluigi			uint8_t version)
209231437Sluigi{
210231437Sluigi	hdr->u0.req.opcode = opcode;
211231437Sluigi	hdr->u0.req.subsystem = subsys;
212231437Sluigi	hdr->u0.req.port_number = port;
213231437Sluigi	hdr->u0.req.domain = dom;
214231437Sluigi
215231437Sluigi	hdr->u0.req.timeout = timeout;
216231437Sluigi	hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
217231437Sluigi	hdr->u0.req.version = version;
218231437Sluigi}
219231437Sluigi
220231437Sluigi
221231437Sluigi
222231437Sluigi/**
223231437Sluigi * @brief Function to initialize the hw with host endian information
224231437Sluigi * @param sc		software handle to the device
225231437Sluigi * @returns		0 on success, ETIMEDOUT on failure
226231437Sluigi */
227231437Sluigiint
228231437Sluigioce_mbox_init(POCE_SOFTC sc)
229231437Sluigi{
230231437Sluigi	struct oce_bmbx *mbx;
231231437Sluigi	uint8_t *ptr;
232231437Sluigi	int ret = 0;
233231437Sluigi
234231437Sluigi	if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
235231437Sluigi		mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
236231437Sluigi		ptr = (uint8_t *) &mbx->mbx;
237231437Sluigi
238231437Sluigi		/* Endian Signature */
239231437Sluigi		*ptr++ = 0xff;
240231437Sluigi		*ptr++ = 0x12;
241231437Sluigi		*ptr++ = 0x34;
242231437Sluigi		*ptr++ = 0xff;
243231437Sluigi		*ptr++ = 0xff;
244231437Sluigi		*ptr++ = 0x56;
245231437Sluigi		*ptr++ = 0x78;
246231437Sluigi		*ptr = 0xff;
247231437Sluigi
248231437Sluigi		ret = oce_mbox_dispatch(sc, 0);
249231437Sluigi	}
250231437Sluigi
251231437Sluigi	return ret;
252231437Sluigi}
253231437Sluigi
254231437Sluigi
255231437Sluigi/**
256231437Sluigi * @brief 		Function to get the firmware version
257231437Sluigi * @param sc		software handle to the device
258231437Sluigi * @returns		0 on success, EIO on failure
259231437Sluigi */
260231437Sluigiint
261231437Sluigioce_get_fw_version(POCE_SOFTC sc)
262231437Sluigi{
263231437Sluigi	struct oce_mbx mbx;
264231437Sluigi	struct mbx_get_common_fw_version *fwcmd;
265231437Sluigi	int ret = 0;
266231437Sluigi
267231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
268231437Sluigi
269231437Sluigi	fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
270231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
271231437Sluigi				MBX_SUBSYSTEM_COMMON,
272231437Sluigi				OPCODE_COMMON_GET_FW_VERSION,
273231437Sluigi				MBX_TIMEOUT_SEC,
274231437Sluigi				sizeof(struct mbx_get_common_fw_version),
275231437Sluigi				OCE_MBX_VER_V0);
276231437Sluigi
277231437Sluigi	mbx.u0.s.embedded = 1;
278231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
279231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
280231437Sluigi
281231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
282231437Sluigi	if (ret)
283231437Sluigi		return ret;
284231437Sluigi
285231437Sluigi	bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
286231437Sluigi
287231437Sluigi	return 0;
288231437Sluigi}
289231437Sluigi
290231437Sluigi
291231437Sluigi/**
292231437Sluigi * @brief		Function to post a MBX to the mbox
293231437Sluigi * @param sc		software handle to the device
294231437Sluigi * @param mbx 		pointer to the MBX to send
295231437Sluigi * @param mbxctx	pointer to the mbx context structure
296231437Sluigi * @returns		0 on success, error on failure
297231437Sluigi */
298231437Sluigiint
299231437Sluigioce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
300231437Sluigi{
301231437Sluigi	struct oce_mbx *mb_mbx = NULL;
302231437Sluigi	struct oce_mq_cqe *mb_cqe = NULL;
303231437Sluigi	struct oce_bmbx *mb = NULL;
304231437Sluigi	int rc = 0;
305231437Sluigi	uint32_t tmo = 0;
306231437Sluigi	uint32_t cstatus = 0;
307231437Sluigi	uint32_t xstatus = 0;
308231437Sluigi
309231437Sluigi	LOCK(&sc->bmbx_lock);
310231437Sluigi
311231437Sluigi	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
312231437Sluigi	mb_mbx = &mb->mbx;
313231437Sluigi
314231437Sluigi	/* get the tmo */
315231437Sluigi	tmo = mbx->tag[0];
316231437Sluigi	mbx->tag[0] = 0;
317231437Sluigi
318231437Sluigi	/* copy mbx into mbox */
319231437Sluigi	bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
320231437Sluigi
321231437Sluigi	/* now dispatch */
322231437Sluigi	rc = oce_mbox_dispatch(sc, tmo);
323231437Sluigi	if (rc == 0) {
324231437Sluigi		/*
325231437Sluigi		 * the command completed successfully. Now get the
326231437Sluigi		 * completion queue entry
327231437Sluigi		 */
328231437Sluigi		mb_cqe = &mb->cqe;
329231437Sluigi		DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
330231437Sluigi
331231437Sluigi		/* copy mbox mbx back */
332231437Sluigi		bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
333231437Sluigi
334231437Sluigi		/* pick up the mailbox status */
335231437Sluigi		cstatus = mb_cqe->u0.s.completion_status;
336231437Sluigi		xstatus = mb_cqe->u0.s.extended_status;
337231437Sluigi
338231437Sluigi		/*
339231437Sluigi		 * store the mbx context in the cqe tag section so that
340231437Sluigi		 * the upper layer handling the cqe can associate the mbx
341231437Sluigi		 * with the response
342231437Sluigi		 */
343231437Sluigi		if (cstatus == 0 && mbxctx) {
344231437Sluigi			/* save context */
345231437Sluigi			mbxctx->mbx = mb_mbx;
346231437Sluigi			bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
347231437Sluigi				sizeof(struct oce_mbx_ctx *));
348231437Sluigi		}
349231437Sluigi	}
350231437Sluigi
351231437Sluigi	UNLOCK(&sc->bmbx_lock);
352231437Sluigi
353231437Sluigi	return rc;
354231437Sluigi}
355231437Sluigi
356231437Sluigi/**
357231437Sluigi * @brief Function to read the mac address associated with an interface
358231437Sluigi * @param sc		software handle to the device
359231437Sluigi * @param if_id 	interface id to read the address from
360231437Sluigi * @param perm 		set to 1 if reading the factory mac address.
361231437Sluigi *			In this case if_id is ignored
362231437Sluigi * @param type 		type of the mac address, whether network or storage
363231437Sluigi * @param[out] mac 	[OUTPUT] pointer to a buffer containing the
364231437Sluigi *			mac address when the command succeeds.
365231437Sluigi * @returns		0 on success, EIO on failure
366231437Sluigi */
367231437Sluigiint
368231437Sluigioce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
369231437Sluigi		uint8_t perm, uint8_t type, struct mac_address_format *mac)
370231437Sluigi{
371231437Sluigi	struct oce_mbx mbx;
372231437Sluigi	struct mbx_query_common_iface_mac *fwcmd;
373231437Sluigi	int ret = 0;
374231437Sluigi
375231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
376231437Sluigi
377231437Sluigi	fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
378231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
379231437Sluigi				MBX_SUBSYSTEM_COMMON,
380231437Sluigi				OPCODE_COMMON_QUERY_IFACE_MAC,
381231437Sluigi				MBX_TIMEOUT_SEC,
382231437Sluigi				sizeof(struct mbx_query_common_iface_mac),
383231437Sluigi				OCE_MBX_VER_V0);
384231437Sluigi
385231437Sluigi	fwcmd->params.req.permanent = perm;
386231437Sluigi	if (!perm)
387231437Sluigi		fwcmd->params.req.if_id = (uint16_t) if_id;
388231437Sluigi	else
389231437Sluigi		fwcmd->params.req.if_id = 0;
390231437Sluigi
391231437Sluigi	fwcmd->params.req.type = type;
392231437Sluigi
393231437Sluigi	mbx.u0.s.embedded = 1;
394231437Sluigi	mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
395231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
396231437Sluigi
397231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
398231437Sluigi	if (ret)
399231437Sluigi		return ret;
400231437Sluigi
401231437Sluigi	/* copy the mac addres in the output parameter */
402231437Sluigi	mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
403231437Sluigi	bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
404231437Sluigi		mac->size_of_struct);
405231437Sluigi
406231437Sluigi	return 0;
407231437Sluigi}
408231437Sluigi
409231437Sluigi/**
410231437Sluigi * @brief Function to query the fw attributes from the hw
411231437Sluigi * @param sc		software handle to the device
412231437Sluigi * @returns		0 on success, EIO on failure
413231437Sluigi */
414231437Sluigiint
415231437Sluigioce_get_fw_config(POCE_SOFTC sc)
416231437Sluigi{
417231437Sluigi	struct oce_mbx mbx;
418231437Sluigi	struct mbx_common_query_fw_config *fwcmd;
419231437Sluigi	int ret = 0;
420231437Sluigi
421231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
422231437Sluigi
423231437Sluigi	fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
424231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
425231437Sluigi				MBX_SUBSYSTEM_COMMON,
426231437Sluigi				OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
427231437Sluigi				MBX_TIMEOUT_SEC,
428231437Sluigi				sizeof(struct mbx_common_query_fw_config),
429231437Sluigi				OCE_MBX_VER_V0);
430231437Sluigi
431231437Sluigi	mbx.u0.s.embedded = 1;
432231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
433231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
434231437Sluigi
435231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
436231437Sluigi	if (ret)
437231437Sluigi		return ret;
438231437Sluigi
439231437Sluigi	DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
440231437Sluigi
441231437Sluigi	sc->config_number = fwcmd->params.rsp.config_number;
442231437Sluigi	sc->asic_revision = fwcmd->params.rsp.asic_revision;
443231437Sluigi	sc->port_id	  = fwcmd->params.rsp.port_id;
444231437Sluigi	sc->function_mode = fwcmd->params.rsp.function_mode;
445231437Sluigi	sc->function_caps = fwcmd->params.rsp.function_caps;
446231437Sluigi
447231437Sluigi	if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
448231437Sluigi		sc->max_tx_rings = fwcmd->params.rsp.ulp[0].nic_wq_tot;
449231437Sluigi		sc->max_rx_rings = fwcmd->params.rsp.ulp[0].lro_rqid_tot;
450231437Sluigi	} else {
451231437Sluigi		sc->max_tx_rings = fwcmd->params.rsp.ulp[1].nic_wq_tot;
452231437Sluigi		sc->max_rx_rings = fwcmd->params.rsp.ulp[1].lro_rqid_tot;
453231437Sluigi	}
454231437Sluigi
455231437Sluigi	return 0;
456231437Sluigi
457231437Sluigi}
458231437Sluigi
459231437Sluigi/**
460231437Sluigi *
461231437Sluigi * @brief function to create a device interface
462231437Sluigi * @param sc		software handle to the device
463231437Sluigi * @param cap_flags	capability flags
464231437Sluigi * @param en_flags	enable capability flags
465231437Sluigi * @param vlan_tag	optional vlan tag to associate with the if
466231437Sluigi * @param mac_addr	pointer to a buffer containing the mac address
467231437Sluigi * @param[out] if_id	[OUTPUT] pointer to an integer to hold the ID of the
468231437Sluigi interface created
469231437Sluigi * @returns		0 on success, EIO on failure
470231437Sluigi */
471231437Sluigiint
472231437Sluigioce_if_create(POCE_SOFTC sc,
473231437Sluigi		uint32_t cap_flags,
474231437Sluigi		uint32_t en_flags,
475231437Sluigi		uint16_t vlan_tag,
476231437Sluigi		uint8_t *mac_addr,
477231437Sluigi		uint32_t *if_id)
478231437Sluigi{
479231437Sluigi	struct oce_mbx mbx;
480231437Sluigi	struct mbx_create_common_iface *fwcmd;
481231437Sluigi	int rc = 0;
482231437Sluigi
483231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
484231437Sluigi
485231437Sluigi	fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
486231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
487231437Sluigi				MBX_SUBSYSTEM_COMMON,
488231437Sluigi				OPCODE_COMMON_CREATE_IFACE,
489231437Sluigi				MBX_TIMEOUT_SEC,
490231437Sluigi				sizeof(struct mbx_create_common_iface),
491231437Sluigi				OCE_MBX_VER_V0);
492231437Sluigi	DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
493231437Sluigi
494231437Sluigi	fwcmd->params.req.version = 0;
495231437Sluigi	fwcmd->params.req.cap_flags = LE_32(cap_flags);
496231437Sluigi	fwcmd->params.req.enable_flags = LE_32(en_flags);
497231437Sluigi	if (mac_addr != NULL) {
498231437Sluigi		bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
499231437Sluigi		fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
500231437Sluigi		fwcmd->params.req.mac_invalid = 0;
501231437Sluigi	} else {
502231437Sluigi		fwcmd->params.req.mac_invalid = 1;
503231437Sluigi	}
504231437Sluigi
505231437Sluigi	mbx.u0.s.embedded = 1;
506231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_iface);
507231437Sluigi	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
508231437Sluigi
509231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
510231437Sluigi	if (rc)
511231437Sluigi		return rc;
512231437Sluigi
513231437Sluigi	*if_id = LE_32(fwcmd->params.rsp.if_id);
514231437Sluigi
515231437Sluigi	if (mac_addr != NULL)
516231437Sluigi		sc->pmac_id = LE_32(fwcmd->params.rsp.pmac_id);
517231437Sluigi
518231437Sluigi	return 0;
519231437Sluigi}
520231437Sluigi
521231437Sluigi/**
522231437Sluigi * @brief		Function to delete an interface
523231437Sluigi * @param sc 		software handle to the device
524231437Sluigi * @param if_id		ID of the interface to delete
525231437Sluigi * @returns		0 on success, EIO on failure
526231437Sluigi */
527231437Sluigiint
528231437Sluigioce_if_del(POCE_SOFTC sc, uint32_t if_id)
529231437Sluigi{
530231437Sluigi	struct oce_mbx mbx;
531231437Sluigi	struct mbx_destroy_common_iface *fwcmd;
532231437Sluigi	int rc = 0;
533231437Sluigi
534231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
535231437Sluigi
536231437Sluigi	fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
537231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
538231437Sluigi				MBX_SUBSYSTEM_COMMON,
539231437Sluigi				OPCODE_COMMON_DESTROY_IFACE,
540231437Sluigi				MBX_TIMEOUT_SEC,
541231437Sluigi				sizeof(struct mbx_destroy_common_iface),
542231437Sluigi				OCE_MBX_VER_V0);
543231437Sluigi
544231437Sluigi	fwcmd->params.req.if_id = if_id;
545231437Sluigi
546231437Sluigi	mbx.u0.s.embedded = 1;
547231437Sluigi	mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
548231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
549231437Sluigi
550231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
551231437Sluigi	return rc;
552231437Sluigi}
553231437Sluigi
554231437Sluigi/**
555231437Sluigi * @brief Function to send the mbx command to configure vlan
556231437Sluigi * @param sc 		software handle to the device
557231437Sluigi * @param if_id 	interface identifier index
558231437Sluigi * @param vtag_arr	array of vlan tags
559231437Sluigi * @param vtag_cnt	number of elements in array
560231437Sluigi * @param untagged	boolean TRUE/FLASE
561231437Sluigi * @param enable_promisc flag to enable/disable VLAN promiscuous mode
562231437Sluigi * @returns		0 on success, EIO on failure
563231437Sluigi */
564231437Sluigiint
565231437Sluigioce_config_vlan(POCE_SOFTC sc,
566231437Sluigi		uint32_t if_id,
567231437Sluigi		struct normal_vlan *vtag_arr,
568231437Sluigi		uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
569231437Sluigi{
570231437Sluigi	struct oce_mbx mbx;
571231437Sluigi	struct mbx_common_config_vlan *fwcmd;
572231437Sluigi	int rc;
573231437Sluigi
574231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
575231437Sluigi	fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
576231437Sluigi
577231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
578231437Sluigi				MBX_SUBSYSTEM_COMMON,
579231437Sluigi				OPCODE_COMMON_CONFIG_IFACE_VLAN,
580231437Sluigi				MBX_TIMEOUT_SEC,
581231437Sluigi				sizeof(struct mbx_common_config_vlan),
582231437Sluigi				OCE_MBX_VER_V0);
583231437Sluigi
584231437Sluigi	fwcmd->params.req.if_id = (uint8_t) if_id;
585231437Sluigi	fwcmd->params.req.promisc = (uint8_t) enable_promisc;
586231437Sluigi	fwcmd->params.req.untagged = (uint8_t) untagged;
587231437Sluigi	fwcmd->params.req.num_vlans = vtag_cnt;
588231437Sluigi
589231437Sluigi	if (!enable_promisc) {
590231437Sluigi		bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
591231437Sluigi			vtag_cnt * sizeof(struct normal_vlan));
592231437Sluigi	}
593231437Sluigi	mbx.u0.s.embedded = 1;
594231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_config_vlan);
595231437Sluigi	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
596231437Sluigi
597231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
598231437Sluigi
599231437Sluigi	return rc;
600231437Sluigi
601231437Sluigi}
602231437Sluigi
603231437Sluigi/**
604231437Sluigi * @brief Function to set flow control capability in the hardware
605231437Sluigi * @param sc 		software handle to the device
606231437Sluigi * @param flow_control	flow control flags to set
607231437Sluigi * @returns		0 on success, EIO on failure
608231437Sluigi */
609231437Sluigiint
610231437Sluigioce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
611231437Sluigi{
612231437Sluigi	struct oce_mbx mbx;
613231437Sluigi	struct mbx_common_get_set_flow_control *fwcmd =
614231437Sluigi		(struct mbx_common_get_set_flow_control *)&mbx.payload;
615231437Sluigi	int rc;
616231437Sluigi
617231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
618231437Sluigi
619231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
620231437Sluigi				MBX_SUBSYSTEM_COMMON,
621231437Sluigi				OPCODE_COMMON_SET_FLOW_CONTROL,
622231437Sluigi				MBX_TIMEOUT_SEC,
623231437Sluigi				sizeof(struct mbx_common_get_set_flow_control),
624231437Sluigi				OCE_MBX_VER_V0);
625231437Sluigi
626231437Sluigi	if (flow_control & OCE_FC_TX)
627231437Sluigi		fwcmd->tx_flow_control = 1;
628231437Sluigi
629231437Sluigi	if (flow_control & OCE_FC_RX)
630231437Sluigi		fwcmd->rx_flow_control = 1;
631231437Sluigi
632231437Sluigi	mbx.u0.s.embedded = 1;
633231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
634231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
635231437Sluigi
636231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
637231437Sluigi
638231437Sluigi	return rc;
639231437Sluigi}
640231437Sluigi
641231437Sluigi/**
642231437Sluigi * @brief Initialize the RSS CPU indirection table
643231437Sluigi *
644231437Sluigi * The table is used to choose the queue to place the incomming packets.
645231437Sluigi * Incomming packets are hashed.  The lowest bits in the hash result
646231437Sluigi * are used as the index into the CPU indirection table.
647231437Sluigi * Each entry in the table contains the RSS CPU-ID returned by the NIC
648231437Sluigi * create.  Based on the CPU ID, the receive completion is routed to
649231437Sluigi * the corresponding RSS CQs.  (Non-RSS packets are always completed
650231437Sluigi * on the default (0) CQ).
651231437Sluigi *
652231437Sluigi * @param sc 		software handle to the device
653231437Sluigi * @param *fwcmd	pointer to the rss mbox command
654231437Sluigi * @returns		none
655231437Sluigi */
656231437Sluigistatic int
657231437Sluigioce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
658231437Sluigi{
659231437Sluigi	int i = 0, j = 0, rc = 0;
660231437Sluigi	uint8_t *tbl = fwcmd->params.req.cputable;
661231437Sluigi
662231437Sluigi
663231437Sluigi	for (j = 0; j < sc->nrqs; j++) {
664231437Sluigi		if (sc->rq[j]->cfg.is_rss_queue) {
665231437Sluigi			tbl[i] = sc->rq[j]->rss_cpuid;
666231437Sluigi			i = i + 1;
667231437Sluigi		}
668231437Sluigi	}
669231437Sluigi	if (i == 0) {
670231437Sluigi		device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
671231437Sluigi		rc = ENXIO;
672231437Sluigi
673231437Sluigi	}
674231437Sluigi
675231437Sluigi	/* fill log2 value indicating the size of the CPU table */
676231437Sluigi	if (rc == 0)
677231437Sluigi		fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(i));
678231437Sluigi
679231437Sluigi	return rc;
680231437Sluigi}
681231437Sluigi
682231437Sluigi/**
683231437Sluigi * @brief Function to set flow control capability in the hardware
684231437Sluigi * @param sc 		software handle to the device
685231437Sluigi * @param if_id 	interface id to read the address from
686231437Sluigi * @param enable_rss	0=disable, RSS_ENABLE_xxx flags otherwise
687231437Sluigi * @returns		0 on success, EIO on failure
688231437Sluigi */
689231437Sluigiint
690231437Sluigioce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
691231437Sluigi{
692231437Sluigi	int rc;
693231437Sluigi	struct oce_mbx mbx;
694231437Sluigi	struct mbx_config_nic_rss *fwcmd =
695231437Sluigi				(struct mbx_config_nic_rss *)&mbx.payload;
696231437Sluigi
697231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
698231437Sluigi
699231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
700231437Sluigi				MBX_SUBSYSTEM_NIC,
701231437Sluigi				NIC_CONFIG_RSS,
702231437Sluigi				MBX_TIMEOUT_SEC,
703231437Sluigi				sizeof(struct mbx_config_nic_rss),
704231437Sluigi				OCE_MBX_VER_V0);
705231437Sluigi	if (enable_rss)
706231437Sluigi		fwcmd->params.req.enable_rss = (RSS_ENABLE_IPV4 |
707231437Sluigi						RSS_ENABLE_TCP_IPV4 |
708231437Sluigi						RSS_ENABLE_IPV6 |
709231437Sluigi						RSS_ENABLE_TCP_IPV6);
710231437Sluigi	fwcmd->params.req.flush = OCE_FLUSH;
711231437Sluigi	fwcmd->params.req.if_id = LE_32(if_id);
712231437Sluigi
713231437Sluigi	srandom(arc4random());	/* random entropy seed */
714231437Sluigi	read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
715231437Sluigi
716231437Sluigi	rc = oce_rss_itbl_init(sc, fwcmd);
717231437Sluigi	if (rc == 0) {
718231437Sluigi		mbx.u0.s.embedded = 1;
719231437Sluigi		mbx.payload_length = sizeof(struct mbx_config_nic_rss);
720231437Sluigi		DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
721231437Sluigi
722231437Sluigi		rc = oce_mbox_post(sc, &mbx, NULL);
723231437Sluigi
724231437Sluigi	}
725231437Sluigi
726231437Sluigi	return rc;
727231437Sluigi}
728231437Sluigi
729231437Sluigi/**
730231437Sluigi * @brief 		RXF function to enable/disable device promiscuous mode
731231437Sluigi * @param sc		software handle to the device
732231437Sluigi * @param enable	enable/disable flag
733231437Sluigi * @returns		0 on success, EIO on failure
734231437Sluigi * @note
735231437Sluigi *	The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
736231437Sluigi *	This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
737231437Sluigi */
738231437Sluigiint
739231437Sluigioce_rxf_set_promiscuous(POCE_SOFTC sc, uint32_t enable)
740231437Sluigi{
741231437Sluigi	struct mbx_set_common_iface_rx_filter *fwcmd;
742231437Sluigi	int sz = sizeof(struct mbx_set_common_iface_rx_filter);
743231437Sluigi	iface_rx_filter_ctx_t *req;
744231437Sluigi	OCE_DMA_MEM sgl;
745231437Sluigi	int rc;
746231437Sluigi
747231437Sluigi	/* allocate mbx payload's dma scatter/gather memory */
748231437Sluigi	rc = oce_dma_alloc(sc, sz, &sgl, 0);
749231437Sluigi	if (rc)
750231437Sluigi		return rc;
751231437Sluigi
752231437Sluigi	fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
753231437Sluigi
754231437Sluigi	req =  &fwcmd->params.req;
755231437Sluigi	req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
756231437Sluigi				MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
757231437Sluigi	if (enable) {
758231437Sluigi		req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
759231437Sluigi				   MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
760231437Sluigi	}
761231437Sluigi	req->if_id = sc->if_id;
762231437Sluigi
763231437Sluigi	rc = oce_set_common_iface_rx_filter(sc, &sgl);
764231437Sluigi	oce_dma_free(sc, &sgl);
765231437Sluigi
766231437Sluigi	return rc;
767231437Sluigi}
768231437Sluigi
769231437Sluigi
770231437Sluigi/**
771231437Sluigi * @brief 			Function modify and select rx filter options
772231437Sluigi * @param sc			software handle to the device
773231437Sluigi * @param sgl			scatter/gather request/response
774231437Sluigi * @returns			0 on success, error code on failure
775231437Sluigi */
776231437Sluigiint
777231437Sluigioce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
778231437Sluigi{
779231437Sluigi	struct oce_mbx mbx;
780231437Sluigi	int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
781231437Sluigi	struct mbx_set_common_iface_rx_filter *fwcmd;
782231437Sluigi	int rc;
783231437Sluigi
784231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
785231437Sluigi	fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
786231437Sluigi
787231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
788231437Sluigi				MBX_SUBSYSTEM_COMMON,
789231437Sluigi				OPCODE_COMMON_SET_IFACE_RX_FILTER,
790231437Sluigi				MBX_TIMEOUT_SEC,
791231437Sluigi				mbx_sz,
792231437Sluigi				OCE_MBX_VER_V0);
793231437Sluigi
794231437Sluigi	oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
795231437Sluigi	mbx.u0.s.embedded = 0;
796231437Sluigi	mbx.u0.s.sge_count = 1;
797231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
798231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
799231437Sluigi	mbx.payload.u0.u1.sgl[0].length = mbx_sz;
800231437Sluigi	mbx.payload_length = mbx_sz;
801231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
802231437Sluigi
803231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
804231437Sluigi	return rc;
805231437Sluigi}
806231437Sluigi
807231437Sluigi/**
808231437Sluigi * @brief Function to query the link status from the hardware
809231437Sluigi * @param sc 		software handle to the device
810231437Sluigi * @param[out] link	pointer to the structure returning link attributes
811231437Sluigi * @returns		0 on success, EIO on failure
812231437Sluigi */
813231437Sluigiint
814231437Sluigioce_get_link_status(POCE_SOFTC sc, struct link_status *link)
815231437Sluigi{
816231437Sluigi	struct oce_mbx mbx;
817231437Sluigi	struct mbx_query_common_link_config *fwcmd;
818231437Sluigi	int rc = 0;
819231437Sluigi
820231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
821231437Sluigi
822231437Sluigi	fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
823231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
824231437Sluigi				MBX_SUBSYSTEM_COMMON,
825231437Sluigi				OPCODE_COMMON_QUERY_LINK_CONFIG,
826231437Sluigi				MBX_TIMEOUT_SEC,
827231437Sluigi				sizeof(struct mbx_query_common_link_config),
828231437Sluigi				OCE_MBX_VER_V0);
829231437Sluigi
830231437Sluigi	mbx.u0.s.embedded = 1;
831231437Sluigi	mbx.payload_length = sizeof(struct mbx_query_common_link_config);
832231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
833231437Sluigi
834231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
835231437Sluigi
836231437Sluigi	if (rc) {
837231437Sluigi		device_printf(sc->dev, "Could not get link speed: %d\n", rc);
838231437Sluigi	} else {
839231437Sluigi		/* interpret response */
840231437Sluigi		bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status));
841231437Sluigi		link->logical_link_status = LE_32(link->logical_link_status);
842231437Sluigi		link->qos_link_speed = LE_16(link->qos_link_speed);
843231437Sluigi	}
844231437Sluigi
845231437Sluigi	return rc;
846231437Sluigi}
847231437Sluigi
848231437Sluigi
849231437Sluigi
850231437Sluigiint
851231437Sluigioce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
852231437Sluigi{
853231437Sluigi	struct oce_mbx mbx;
854231437Sluigi	struct mbx_get_nic_stats_v0 *fwcmd;
855231437Sluigi	int rc = 0;
856231437Sluigi
857231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
858231437Sluigi
859231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v0);
860231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_nic_stats_v0));
861231437Sluigi
862231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
863231437Sluigi				MBX_SUBSYSTEM_NIC,
864231437Sluigi				NIC_GET_STATS,
865231437Sluigi				MBX_TIMEOUT_SEC,
866231437Sluigi				sizeof(struct mbx_get_nic_stats_v0),
867231437Sluigi				OCE_MBX_VER_V0);
868231437Sluigi
869231437Sluigi	mbx.u0.s.embedded = 0;
870231437Sluigi	mbx.u0.s.sge_count = 1;
871231437Sluigi
872231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
873231437Sluigi
874231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
875231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
876231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats_v0);
877231437Sluigi
878231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_nic_stats_v0);
879231437Sluigi
880231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
881231437Sluigi
882231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
883231437Sluigi
884231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
885231437Sluigi
886231437Sluigi	if (rc) {
887231437Sluigi		device_printf(sc->dev,
888231437Sluigi			"Could not get nic statistics: %d\n", rc);
889231437Sluigi	}
890231437Sluigi
891231437Sluigi	return rc;
892231437Sluigi}
893231437Sluigi
894231437Sluigi
895231437Sluigi
896231437Sluigi/**
897231437Sluigi * @brief Function to get NIC statistics
898231437Sluigi * @param sc 		software handle to the device
899231437Sluigi * @param *stats	pointer to where to store statistics
900231437Sluigi * @param reset_stats	resets statistics of set
901231437Sluigi * @returns		0 on success, EIO on failure
902231437Sluigi * @note		command depricated in Lancer
903231437Sluigi */
904231437Sluigiint
905231437Sluigioce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
906231437Sluigi{
907231437Sluigi	struct oce_mbx mbx;
908231437Sluigi	struct mbx_get_nic_stats *fwcmd;
909231437Sluigi	int rc = 0;
910231437Sluigi
911231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
912231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats);
913231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_nic_stats));
914231437Sluigi
915231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
916231437Sluigi				MBX_SUBSYSTEM_NIC,
917231437Sluigi				NIC_GET_STATS,
918231437Sluigi				MBX_TIMEOUT_SEC,
919231437Sluigi				sizeof(struct mbx_get_nic_stats),
920231437Sluigi				OCE_MBX_VER_V1);
921231437Sluigi
922231437Sluigi
923231437Sluigi	mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
924231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
925231437Sluigi
926231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
927231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
928231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
929231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats);
930231437Sluigi
931231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_nic_stats);
932231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
933231437Sluigi
934231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
935231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
936231437Sluigi	if (rc) {
937231437Sluigi		device_printf(sc->dev,
938231437Sluigi			"Could not get nic statistics: %d\n", rc);
939231437Sluigi	}
940231437Sluigi	return rc;
941231437Sluigi}
942231437Sluigi
943231437Sluigi
944231437Sluigi/**
945231437Sluigi * @brief Function to get pport (physical port) statistics
946231437Sluigi * @param sc 		software handle to the device
947231437Sluigi * @param *stats	pointer to where to store statistics
948231437Sluigi * @param reset_stats	resets statistics of set
949231437Sluigi * @returns		0 on success, EIO on failure
950231437Sluigi */
951231437Sluigiint
952231437Sluigioce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
953231437Sluigi				uint32_t reset_stats)
954231437Sluigi{
955231437Sluigi	struct oce_mbx mbx;
956231437Sluigi	struct mbx_get_pport_stats *fwcmd;
957231437Sluigi	int rc = 0;
958231437Sluigi
959231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
960231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
961231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
962231437Sluigi
963231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
964231437Sluigi				MBX_SUBSYSTEM_NIC,
965231437Sluigi				NIC_GET_PPORT_STATS,
966231437Sluigi				MBX_TIMEOUT_SEC,
967231437Sluigi				sizeof(struct mbx_get_pport_stats),
968231437Sluigi				OCE_MBX_VER_V0);
969231437Sluigi
970231437Sluigi	fwcmd->params.req.reset_stats = reset_stats;
971231437Sluigi	fwcmd->params.req.port_number = sc->if_id;
972231437Sluigi
973231437Sluigi	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
974231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
975231437Sluigi
976231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
977231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
978231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
979231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
980231437Sluigi
981231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_pport_stats);
982231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
983231437Sluigi
984231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
985231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
986231437Sluigi
987231437Sluigi	if (rc != 0) {
988231437Sluigi		device_printf(sc->dev,
989231437Sluigi			  "Could not get physical port statistics: %d\n", rc);
990231437Sluigi	}
991231437Sluigi
992231437Sluigi	return rc;
993231437Sluigi}
994231437Sluigi
995231437Sluigi
996231437Sluigi/**
997231437Sluigi * @brief Function to get vport (virtual port) statistics
998231437Sluigi * @param sc 		software handle to the device
999231437Sluigi * @param *stats	pointer to where to store statistics
1000231437Sluigi * @param reset_stats	resets statistics of set
1001231437Sluigi * @returns		0 on success, EIO on failure
1002231437Sluigi */
1003231437Sluigiint
1004231437Sluigioce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1005231437Sluigi				uint32_t req_size, uint32_t reset_stats)
1006231437Sluigi{
1007231437Sluigi	struct oce_mbx mbx;
1008231437Sluigi	struct mbx_get_vport_stats *fwcmd;
1009231437Sluigi	int rc = 0;
1010231437Sluigi
1011231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1012231437Sluigi
1013231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
1014231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
1015231437Sluigi
1016231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1017231437Sluigi				MBX_SUBSYSTEM_NIC,
1018231437Sluigi				NIC_GET_VPORT_STATS,
1019231437Sluigi				MBX_TIMEOUT_SEC,
1020231437Sluigi				sizeof(struct mbx_get_vport_stats),
1021231437Sluigi				OCE_MBX_VER_V0);
1022231437Sluigi
1023231437Sluigi	fwcmd->params.req.reset_stats = reset_stats;
1024231437Sluigi	fwcmd->params.req.vport_number = sc->if_id;
1025231437Sluigi
1026231437Sluigi	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1027231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1028231437Sluigi
1029231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1030231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1031231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1032231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
1033231437Sluigi
1034231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_vport_stats);
1035231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1036231437Sluigi
1037231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1038231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1039231437Sluigi
1040231437Sluigi	if (rc != 0) {
1041231437Sluigi		device_printf(sc->dev,
1042231437Sluigi			  "Could not get physical port statistics: %d\n", rc);
1043231437Sluigi	}
1044231437Sluigi
1045231437Sluigi	return rc;
1046231437Sluigi}
1047231437Sluigi
1048231437Sluigi
1049231437Sluigi/**
1050231437Sluigi * @brief               Function to update the muticast filter with
1051231437Sluigi *                      values in dma_mem
1052231437Sluigi * @param sc            software handle to the device
1053231437Sluigi * @param dma_mem       pointer to dma memory region
1054231437Sluigi * @returns             0 on success, EIO on failure
1055231437Sluigi */
1056231437Sluigiint
1057231437Sluigioce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
1058231437Sluigi{
1059231437Sluigi	struct oce_mbx mbx;
1060231437Sluigi	struct oce_mq_sge *sgl;
1061231437Sluigi	struct mbx_set_common_iface_multicast *req = NULL;
1062231437Sluigi	int rc = 0;
1063231437Sluigi
1064231437Sluigi	req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
1065231437Sluigi	mbx_common_req_hdr_init(&req->hdr, 0, 0,
1066231437Sluigi				MBX_SUBSYSTEM_COMMON,
1067231437Sluigi				OPCODE_COMMON_SET_IFACE_MULTICAST,
1068231437Sluigi				MBX_TIMEOUT_SEC,
1069231437Sluigi				sizeof(struct mbx_set_common_iface_multicast),
1070231437Sluigi				OCE_MBX_VER_V0);
1071231437Sluigi
1072231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1073231437Sluigi
1074231437Sluigi	mbx.u0.s.embedded = 0; /*Non embeded*/
1075231437Sluigi	mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
1076231437Sluigi	mbx.u0.s.sge_count = 1;
1077231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1078231437Sluigi	sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
1079231437Sluigi	sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
1080231437Sluigi	sgl->length = htole32(mbx.payload_length);
1081231437Sluigi
1082231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1083231437Sluigi
1084231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1085231437Sluigi
1086231437Sluigi	return rc;
1087231437Sluigi}
1088231437Sluigi
1089231437Sluigi
1090231437Sluigi/**
1091231437Sluigi * @brief               Function to send passthrough Ioctls
1092231437Sluigi * @param sc            software handle to the device
1093231437Sluigi * @param dma_mem       pointer to dma memory region
1094231437Sluigi * @param req_size      size of dma_mem
1095231437Sluigi * @returns             0 on success, EIO on failure
1096231437Sluigi */
1097231437Sluigiint
1098231437Sluigioce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
1099231437Sluigi{
1100231437Sluigi	struct oce_mbx mbx;
1101231437Sluigi	struct oce_mq_sge *sgl;
1102231437Sluigi	int rc = 0;
1103231437Sluigi
1104231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1105231437Sluigi
1106231437Sluigi	mbx.u0.s.embedded  = 0; /*Non embeded*/
1107231437Sluigi	mbx.payload_length = req_size;
1108231437Sluigi	mbx.u0.s.sge_count = 1;
1109231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1110231437Sluigi	sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
1111231437Sluigi	sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
1112231437Sluigi	sgl->length = htole32(req_size);
1113231437Sluigi
1114231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1115231437Sluigi
1116231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1117231437Sluigi	return rc;
1118231437Sluigi}
1119231437Sluigi
1120231437Sluigi
1121231437Sluigiint
1122231437Sluigioce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
1123231437Sluigi		 uint32_t if_id, uint32_t *pmac_id)
1124231437Sluigi{
1125231437Sluigi	struct oce_mbx mbx;
1126231437Sluigi	struct mbx_add_common_iface_mac *fwcmd;
1127231437Sluigi	int rc = 0;
1128231437Sluigi
1129231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1130231437Sluigi
1131231437Sluigi	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1132231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1133231437Sluigi				MBX_SUBSYSTEM_COMMON,
1134231437Sluigi				OPCODE_COMMON_ADD_IFACE_MAC,
1135231437Sluigi				MBX_TIMEOUT_SEC,
1136231437Sluigi				sizeof(struct mbx_add_common_iface_mac),
1137231437Sluigi				OCE_MBX_VER_V0);
1138231437Sluigi
1139231437Sluigi	fwcmd->params.req.if_id = (uint16_t) if_id;
1140231437Sluigi	bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
1141231437Sluigi
1142231437Sluigi	mbx.u0.s.embedded = 1;
1143231437Sluigi	mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
1144231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1145231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1146231437Sluigi	if (rc)
1147231437Sluigi		return rc;
1148231437Sluigi
1149231437Sluigi	*pmac_id = fwcmd->params.rsp.pmac_id;
1150231437Sluigi
1151231437Sluigi	return rc;
1152231437Sluigi}
1153231437Sluigi
1154231437Sluigi
1155231437Sluigiint
1156231437Sluigioce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
1157231437Sluigi{
1158231437Sluigi	struct oce_mbx mbx;
1159231437Sluigi	struct mbx_del_common_iface_mac *fwcmd;
1160231437Sluigi	int rc = 0;
1161231437Sluigi
1162231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1163231437Sluigi
1164231437Sluigi	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1165231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1166231437Sluigi				MBX_SUBSYSTEM_COMMON,
1167231437Sluigi				OPCODE_COMMON_DEL_IFACE_MAC,
1168231437Sluigi				MBX_TIMEOUT_SEC,
1169231437Sluigi				sizeof(struct mbx_del_common_iface_mac),
1170231437Sluigi				OCE_MBX_VER_V0);
1171231437Sluigi
1172231437Sluigi	fwcmd->params.req.if_id = (uint16_t)if_id;
1173231437Sluigi	fwcmd->params.req.pmac_id = pmac_id;
1174231437Sluigi
1175231437Sluigi	mbx.u0.s.embedded = 1;
1176231437Sluigi	mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
1177231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1178231437Sluigi
1179231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1180231437Sluigi	return rc;
1181231437Sluigi}
1182231437Sluigi
1183231437Sluigi
1184231437Sluigi
1185231437Sluigiint
1186231437Sluigioce_mbox_check_native_mode(POCE_SOFTC sc)
1187231437Sluigi{
1188231437Sluigi	struct oce_mbx mbx;
1189231437Sluigi	struct mbx_common_set_function_cap *fwcmd;
1190231437Sluigi	int rc = 0;
1191231437Sluigi
1192231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1193231437Sluigi
1194231437Sluigi	fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
1195231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1196231437Sluigi				MBX_SUBSYSTEM_COMMON,
1197231437Sluigi				OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
1198231437Sluigi				MBX_TIMEOUT_SEC,
1199231437Sluigi				sizeof(struct mbx_common_set_function_cap),
1200231437Sluigi				OCE_MBX_VER_V0);
1201231437Sluigi
1202231437Sluigi	fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS |
1203231437Sluigi							CAP_BE3_NATIVE_ERX_API;
1204231437Sluigi
1205231437Sluigi	fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
1206231437Sluigi
1207231437Sluigi	mbx.u0.s.embedded = 1;
1208231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
1209231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1210231437Sluigi
1211231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1212231437Sluigi	//if (rc != 0)		This can fail in legacy mode. So skip
1213231437Sluigi	//	FN_LEAVE(rc);
1214231437Sluigi
1215231437Sluigi	sc->be3_native = fwcmd->params.rsp.capability_flags
1216231437Sluigi			& CAP_BE3_NATIVE_ERX_API;
1217231437Sluigi
1218231437Sluigi	return 0;
1219231437Sluigi}
1220231437Sluigi
1221231437Sluigi
1222231437Sluigi
1223231437Sluigiint
1224231437Sluigioce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
1225231437Sluigi		uint8_t loopback_type, uint8_t enable)
1226231437Sluigi{
1227231437Sluigi	struct oce_mbx mbx;
1228231437Sluigi	struct mbx_lowlevel_set_loopback_mode *fwcmd;
1229231437Sluigi	int rc = 0;
1230231437Sluigi
1231231437Sluigi
1232231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1233231437Sluigi
1234231437Sluigi	fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
1235231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1236231437Sluigi				MBX_SUBSYSTEM_LOWLEVEL,
1237231437Sluigi				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
1238231437Sluigi				MBX_TIMEOUT_SEC,
1239231437Sluigi				sizeof(struct mbx_lowlevel_set_loopback_mode),
1240231437Sluigi				OCE_MBX_VER_V0);
1241231437Sluigi
1242231437Sluigi	fwcmd->params.req.src_port = port_num;
1243231437Sluigi	fwcmd->params.req.dest_port = port_num;
1244231437Sluigi	fwcmd->params.req.loopback_type = loopback_type;
1245231437Sluigi	fwcmd->params.req.loopback_state = enable;
1246231437Sluigi
1247231437Sluigi	mbx.u0.s.embedded = 1;
1248231437Sluigi	mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
1249231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1250231437Sluigi
1251231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1252231437Sluigi
1253231437Sluigi	return rc;
1254231437Sluigi
1255231437Sluigi}
1256231437Sluigi
1257231437Sluigiint
1258231437Sluigioce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
1259231437Sluigi	uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
1260231437Sluigi	uint64_t pattern)
1261231437Sluigi{
1262231437Sluigi
1263231437Sluigi	struct oce_mbx mbx;
1264231437Sluigi	struct mbx_lowlevel_test_loopback_mode *fwcmd;
1265231437Sluigi	int rc = 0;
1266231437Sluigi
1267231437Sluigi
1268231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1269231437Sluigi
1270231437Sluigi	fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
1271231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1272231437Sluigi				MBX_SUBSYSTEM_LOWLEVEL,
1273231437Sluigi				OPCODE_LOWLEVEL_TEST_LOOPBACK,
1274231437Sluigi				MBX_TIMEOUT_SEC,
1275231437Sluigi				sizeof(struct mbx_lowlevel_test_loopback_mode),
1276231437Sluigi				OCE_MBX_VER_V0);
1277231437Sluigi
1278231437Sluigi	fwcmd->params.req.pattern = pattern;
1279231437Sluigi	fwcmd->params.req.src_port = port_num;
1280231437Sluigi	fwcmd->params.req.dest_port = port_num;
1281231437Sluigi	fwcmd->params.req.pkt_size = pkt_size;
1282231437Sluigi	fwcmd->params.req.num_pkts = num_pkts;
1283231437Sluigi	fwcmd->params.req.loopback_type = loopback_type;
1284231437Sluigi
1285231437Sluigi	mbx.u0.s.embedded = 1;
1286231437Sluigi	mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
1287231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1288231437Sluigi
1289231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1290231437Sluigi	if (rc)
1291231437Sluigi		return rc;
1292231437Sluigi
1293231437Sluigi	return(fwcmd->params.rsp.status);
1294231437Sluigi}
1295231437Sluigi
1296231437Sluigiint
1297231437Sluigioce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
1298231437Sluigi				POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
1299231437Sluigi{
1300231437Sluigi
1301231437Sluigi	struct oce_mbx mbx;
1302231437Sluigi	struct oce_mq_sge *sgl = NULL;
1303231437Sluigi	struct mbx_common_read_write_flashrom *fwcmd = NULL;
1304231437Sluigi	int rc = 0, payload_len = 0;
1305231437Sluigi
1306231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1307231437Sluigi	fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
1308231437Sluigi	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
1309231437Sluigi
1310231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1311231437Sluigi				MBX_SUBSYSTEM_COMMON,
1312231437Sluigi				OPCODE_COMMON_WRITE_FLASHROM,
1313231437Sluigi				LONG_TIMEOUT,
1314231437Sluigi				payload_len,
1315231437Sluigi				OCE_MBX_VER_V0);
1316231437Sluigi
1317231437Sluigi	fwcmd->flash_op_type = optype;
1318231437Sluigi	fwcmd->flash_op_code = opcode;
1319231437Sluigi	fwcmd->data_buffer_size = num_bytes;
1320231437Sluigi
1321231437Sluigi	mbx.u0.s.embedded  = 0; /*Non embeded*/
1322231437Sluigi	mbx.payload_length = payload_len;
1323231437Sluigi	mbx.u0.s.sge_count = 1;
1324231437Sluigi
1325231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1326231437Sluigi	sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
1327231437Sluigi	sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
1328231437Sluigi	sgl->length = payload_len;
1329231437Sluigi
1330231437Sluigi	/* post the command */
1331231437Sluigi	if (rc) {
1332231437Sluigi		device_printf(sc->dev, "Write FlashROM mbox post failed\n");
1333231437Sluigi	} else {
1334231437Sluigi		rc = fwcmd->hdr.u0.rsp.status;
1335231437Sluigi	}
1336231437Sluigi
1337231437Sluigi	return rc;
1338231437Sluigi
1339231437Sluigi}
1340231437Sluigi
1341231437Sluigiint
1342231437Sluigioce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
1343231437Sluigi				uint32_t offset, uint32_t optype)
1344231437Sluigi{
1345231437Sluigi
1346231437Sluigi	int rc = 0, payload_len = 0;
1347231437Sluigi	struct oce_mbx mbx;
1348231437Sluigi	struct mbx_common_read_write_flashrom *fwcmd;
1349231437Sluigi
1350231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1351231437Sluigi
1352231437Sluigi	fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
1353231437Sluigi
1354231437Sluigi	/* Firmware requires extra 4 bytes with this ioctl. Since there
1355231437Sluigi	   is enough room in the mbx payload it should be good enough
1356231437Sluigi	   Reference: Bug 14853
1357231437Sluigi	*/
1358231437Sluigi	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
1359231437Sluigi
1360231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1361231437Sluigi				MBX_SUBSYSTEM_COMMON,
1362231437Sluigi				OPCODE_COMMON_READ_FLASHROM,
1363231437Sluigi				MBX_TIMEOUT_SEC,
1364231437Sluigi				payload_len,
1365231437Sluigi				OCE_MBX_VER_V0);
1366231437Sluigi
1367231437Sluigi	fwcmd->flash_op_type = optype;
1368231437Sluigi	fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
1369231437Sluigi	fwcmd->data_offset = offset;
1370231437Sluigi	fwcmd->data_buffer_size = 0x4;
1371231437Sluigi
1372231437Sluigi	mbx.u0.s.embedded  = 1;
1373231437Sluigi	mbx.payload_length = payload_len;
1374231437Sluigi
1375231437Sluigi	/* post the command */
1376231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1377231437Sluigi	if (rc) {
1378231437Sluigi		device_printf(sc->dev, "Read FlashROM CRC mbox post failed\n");
1379231437Sluigi	} else {
1380231437Sluigi		bcopy(fwcmd->data_buffer, flash_crc, 4);
1381231437Sluigi		rc = fwcmd->hdr.u0.rsp.status;
1382231437Sluigi	}
1383231437Sluigi	return rc;
1384231437Sluigi}
1385231437Sluigi
1386231437Sluigiint
1387231437Sluigioce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
1388231437Sluigi{
1389231437Sluigi
1390231437Sluigi	struct oce_mbx mbx;
1391231437Sluigi	struct mbx_common_phy_info *fwcmd;
1392231437Sluigi	int rc = 0;
1393231437Sluigi
1394231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1395231437Sluigi
1396231437Sluigi	fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
1397231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1398231437Sluigi				MBX_SUBSYSTEM_COMMON,
1399231437Sluigi				OPCODE_COMMON_GET_PHY_CONFIG,
1400231437Sluigi				MBX_TIMEOUT_SEC,
1401231437Sluigi				sizeof(struct mbx_common_phy_info),
1402231437Sluigi				OCE_MBX_VER_V0);
1403231437Sluigi
1404231437Sluigi	mbx.u0.s.embedded = 1;
1405231437Sluigi	mbx.payload_length = sizeof(struct  mbx_common_phy_info);
1406231437Sluigi
1407231437Sluigi	/* now post the command */
1408231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1409231437Sluigi	if (rc) {
1410231437Sluigi		device_printf(sc->dev, "Read PHY info  mbox post failed\n");
1411231437Sluigi	} else {
1412231437Sluigi		rc = fwcmd->hdr.u0.rsp.status;
1413231437Sluigi		phy_info->phy_type = fwcmd->params.rsp.phy_info.phy_type;
1414231437Sluigi		phy_info->interface_type =
1415231437Sluigi				fwcmd->params.rsp.phy_info.interface_type;
1416231437Sluigi		phy_info->auto_speeds_supported =
1417231437Sluigi			fwcmd->params.rsp.phy_info.auto_speeds_supported;
1418231437Sluigi		phy_info->fixed_speeds_supported =
1419231437Sluigi			fwcmd->params.rsp.phy_info.fixed_speeds_supported;
1420231437Sluigi		phy_info->misc_params =fwcmd->params.rsp.phy_info.misc_params;
1421231437Sluigi
1422231437Sluigi	}
1423231437Sluigi	return rc;
1424231437Sluigi
1425231437Sluigi}
1426231437Sluigi
1427231437Sluigi
1428231437Sluigiint
1429231437Sluigioce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
1430231437Sluigi			uint32_t data_offset, POCE_DMA_MEM pdma_mem,
1431231437Sluigi			uint32_t *written_data, uint32_t *additional_status)
1432231437Sluigi{
1433231437Sluigi
1434231437Sluigi	struct oce_mbx mbx;
1435231437Sluigi	struct mbx_lancer_common_write_object *fwcmd = NULL;
1436231437Sluigi	int rc = 0, payload_len = 0;
1437231437Sluigi
1438231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1439231437Sluigi	payload_len = sizeof(struct mbx_lancer_common_write_object);
1440231437Sluigi
1441231437Sluigi	mbx.u0.s.embedded  = 1;/* Embedded */
1442231437Sluigi	mbx.payload_length = payload_len;
1443231437Sluigi	fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
1444231437Sluigi
1445231437Sluigi	/* initialize the ioctl header */
1446231437Sluigi	mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
1447231437Sluigi				MBX_SUBSYSTEM_COMMON,
1448231437Sluigi				OPCODE_COMMON_WRITE_OBJECT,
1449231437Sluigi				LONG_TIMEOUT,
1450231437Sluigi				payload_len,
1451231437Sluigi				OCE_MBX_VER_V0);
1452231437Sluigi
1453231437Sluigi	fwcmd->params.req.write_length = data_size;
1454231437Sluigi	if (data_size == 0)
1455231437Sluigi		fwcmd->params.req.eof = 1;
1456231437Sluigi	else
1457231437Sluigi		fwcmd->params.req.eof = 0;
1458231437Sluigi
1459231437Sluigi	strcpy(fwcmd->params.req.object_name, "/prg");
1460231437Sluigi	fwcmd->params.req.descriptor_count = 1;
1461231437Sluigi	fwcmd->params.req.write_offset = data_offset;
1462231437Sluigi	fwcmd->params.req.buffer_length = data_size;
1463231437Sluigi	fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
1464231437Sluigi	fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
1465231437Sluigi
1466231437Sluigi	/* post the command */
1467231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1468231437Sluigi	if (rc) {
1469231437Sluigi		device_printf(sc->dev,
1470231437Sluigi			"Write Lancer FlashROM mbox post failed\n");
1471231437Sluigi	} else {
1472231437Sluigi		*written_data = fwcmd->params.rsp.actual_write_length;
1473231437Sluigi		*additional_status = fwcmd->params.rsp.additional_status;
1474231437Sluigi		rc = fwcmd->params.rsp.status;
1475231437Sluigi	}
1476231437Sluigi	return rc;
1477231437Sluigi
1478231437Sluigi}
1479231437Sluigi
1480231437Sluigi
1481231437Sluigi
1482231437Sluigiint
1483231437Sluigioce_mbox_create_rq(struct oce_rq *rq)
1484231437Sluigi{
1485231437Sluigi
1486231437Sluigi	struct oce_mbx mbx;
1487231437Sluigi	struct mbx_create_nic_rq *fwcmd;
1488231437Sluigi	POCE_SOFTC sc = rq->parent;
1489231437Sluigi	int rc, num_pages = 0;
1490231437Sluigi
1491231437Sluigi	if (rq->qstate == QCREATED)
1492231437Sluigi		return 0;
1493231437Sluigi
1494231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1495231437Sluigi
1496231437Sluigi	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
1497231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1498231437Sluigi				MBX_SUBSYSTEM_NIC,
1499231437Sluigi				NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
1500231437Sluigi				sizeof(struct mbx_create_nic_rq),
1501231437Sluigi				OCE_MBX_VER_V0);
1502231437Sluigi
1503231437Sluigi	/* oce_page_list will also prepare pages */
1504231437Sluigi	num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
1505231437Sluigi
1506231437Sluigi	if (IS_XE201(sc)) {
1507231437Sluigi		fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
1508231437Sluigi		fwcmd->params.req.page_size = 1;
1509231437Sluigi		fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
1510231437Sluigi	} else
1511231437Sluigi		fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
1512231437Sluigi	fwcmd->params.req.num_pages = num_pages;
1513231437Sluigi	fwcmd->params.req.cq_id = rq->cq->cq_id;
1514231437Sluigi	fwcmd->params.req.if_id = sc->if_id;
1515231437Sluigi	fwcmd->params.req.max_frame_size = rq->cfg.mtu;
1516231437Sluigi	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
1517231437Sluigi
1518231437Sluigi	mbx.u0.s.embedded = 1;
1519231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_nic_rq);
1520231437Sluigi
1521231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1522231437Sluigi	if (rc)
1523231437Sluigi		goto error;
1524231437Sluigi
1525231437Sluigi	rq->rq_id = fwcmd->params.rsp.rq_id;
1526231437Sluigi	rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
1527231437Sluigi
1528231437Sluigi	return 0;
1529231437Sluigierror:
1530231437Sluigi	device_printf(sc->dev, "Mbox Create RQ failed\n");
1531231437Sluigi	return rc;
1532231437Sluigi
1533231437Sluigi}
1534231437Sluigi
1535231437Sluigi
1536231437Sluigi
1537231437Sluigiint
1538231437Sluigioce_mbox_create_wq(struct oce_wq *wq)
1539231437Sluigi{
1540231437Sluigi	struct oce_mbx mbx;
1541231437Sluigi	struct mbx_create_nic_wq *fwcmd;
1542231437Sluigi	POCE_SOFTC sc = wq->parent;
1543231437Sluigi	int rc = 0, version, num_pages;
1544231437Sluigi
1545231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1546231437Sluigi
1547231437Sluigi	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
1548231437Sluigi	if (IS_XE201(sc)) {
1549231437Sluigi		version = OCE_MBX_VER_V1;
1550231437Sluigi		fwcmd->params.req.if_id = sc->if_id;
1551231437Sluigi	} else
1552231437Sluigi		version = OCE_MBX_VER_V0;
1553231437Sluigi
1554231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1555231437Sluigi				MBX_SUBSYSTEM_NIC,
1556231437Sluigi				NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
1557231437Sluigi				sizeof(struct mbx_create_nic_wq),
1558231437Sluigi				version);
1559231437Sluigi
1560231437Sluigi	num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
1561231437Sluigi
1562231437Sluigi	fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
1563231437Sluigi	fwcmd->params.req.num_pages = num_pages;
1564231437Sluigi	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
1565231437Sluigi	fwcmd->params.req.cq_id = wq->cq->cq_id;
1566231437Sluigi	fwcmd->params.req.ulp_num = 1;
1567231437Sluigi
1568231437Sluigi	mbx.u0.s.embedded = 1;
1569231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_nic_wq);
1570231437Sluigi
1571231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1572231437Sluigi	if (rc)
1573231437Sluigi		goto error;
1574231437Sluigi
1575231437Sluigi	wq->wq_id = LE_16(fwcmd->params.rsp.wq_id);
1576231437Sluigi
1577231437Sluigi	return 0;
1578231437Sluigierror:
1579231437Sluigi	device_printf(sc->dev, "Mbox Create WQ failed\n");
1580231437Sluigi	return rc;
1581231437Sluigi
1582231437Sluigi}
1583231437Sluigi
1584231437Sluigi
1585231437Sluigi
1586231437Sluigiint
1587231437Sluigioce_mbox_create_eq(struct oce_eq *eq)
1588231437Sluigi{
1589231437Sluigi	struct oce_mbx mbx;
1590231437Sluigi	struct mbx_create_common_eq *fwcmd;
1591231437Sluigi	POCE_SOFTC sc = eq->parent;
1592231437Sluigi	int rc = 0;
1593231437Sluigi	uint32_t num_pages;
1594231437Sluigi
1595231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1596231437Sluigi
1597231437Sluigi	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
1598231437Sluigi
1599231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1600231437Sluigi				MBX_SUBSYSTEM_COMMON,
1601231437Sluigi				OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
1602231437Sluigi				sizeof(struct mbx_create_common_eq),
1603231437Sluigi				OCE_MBX_VER_V0);
1604231437Sluigi
1605231437Sluigi	num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
1606231437Sluigi	fwcmd->params.req.ctx.num_pages = num_pages;
1607231437Sluigi	fwcmd->params.req.ctx.valid = 1;
1608231437Sluigi	fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
1609231437Sluigi	fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
1610231437Sluigi	fwcmd->params.req.ctx.armed = 0;
1611231437Sluigi	fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
1612231437Sluigi
1613231437Sluigi
1614231437Sluigi	mbx.u0.s.embedded = 1;
1615231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_eq);
1616231437Sluigi
1617231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1618231437Sluigi	if (rc)
1619231437Sluigi		goto error;
1620231437Sluigi
1621231437Sluigi	eq->eq_id = LE_16(fwcmd->params.rsp.eq_id);
1622231437Sluigi
1623231437Sluigi	return 0;
1624231437Sluigierror:
1625231437Sluigi	device_printf(sc->dev, "Mbox Create EQ failed\n");
1626231437Sluigi	return rc;
1627231437Sluigi}
1628231437Sluigi
1629231437Sluigi
1630231437Sluigi
1631231437Sluigiint
1632231437Sluigioce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
1633231437Sluigi{
1634231437Sluigi	struct oce_mbx mbx;
1635231437Sluigi	struct mbx_create_common_cq *fwcmd;
1636231437Sluigi	POCE_SOFTC sc = cq->parent;
1637231437Sluigi	uint8_t version;
1638231437Sluigi	oce_cq_ctx_t *ctx;
1639231437Sluigi	uint32_t num_pages, page_size;
1640231437Sluigi	int rc = 0;
1641231437Sluigi
1642231437Sluigi
1643231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1644231437Sluigi
1645231437Sluigi	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
1646231437Sluigi
1647231437Sluigi	if (IS_XE201(sc))
1648231437Sluigi		version = OCE_MBX_VER_V2;
1649231437Sluigi	else
1650231437Sluigi		version = OCE_MBX_VER_V0;
1651231437Sluigi
1652231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1653231437Sluigi				MBX_SUBSYSTEM_COMMON,
1654231437Sluigi				OPCODE_COMMON_CREATE_CQ,
1655231437Sluigi				MBX_TIMEOUT_SEC,
1656231437Sluigi				sizeof(struct mbx_create_common_cq),
1657231437Sluigi				version);
1658231437Sluigi
1659231437Sluigi	ctx = &fwcmd->params.req.cq_ctx;
1660231437Sluigi
1661231437Sluigi	num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
1662231437Sluigi	page_size =  1;  /* 1 for 4K */
1663231437Sluigi
1664231437Sluigi	if (version == OCE_MBX_VER_V2) {
1665231437Sluigi		ctx->v2.num_pages = LE_16(num_pages);
1666231437Sluigi		ctx->v2.page_size = page_size;
1667231437Sluigi		ctx->v2.eventable = is_eventable;
1668231437Sluigi		ctx->v2.valid = 1;
1669231437Sluigi		ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1670231437Sluigi		ctx->v2.nodelay = cq->cq_cfg.nodelay;
1671231437Sluigi		ctx->v2.coalesce_wm = ncoalesce;
1672231437Sluigi		ctx->v2.armed = 0;
1673231437Sluigi		ctx->v2.eq_id = cq->eq->eq_id;
1674231437Sluigi		if (ctx->v2.count == 3) {
1675231437Sluigi			if (cq->cq_cfg.q_len > (4*1024)-1)
1676231437Sluigi				ctx->v2.cqe_count = (4*1024)-1;
1677231437Sluigi			else
1678231437Sluigi				ctx->v2.cqe_count = cq->cq_cfg.q_len;
1679231437Sluigi		}
1680231437Sluigi	} else {
1681231437Sluigi		ctx->v0.num_pages = LE_16(num_pages);
1682231437Sluigi		ctx->v0.eventable = is_eventable;
1683231437Sluigi		ctx->v0.valid = 1;
1684231437Sluigi		ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1685231437Sluigi		ctx->v0.nodelay = cq->cq_cfg.nodelay;
1686231437Sluigi		ctx->v0.coalesce_wm = ncoalesce;
1687231437Sluigi		ctx->v0.armed = 0;
1688231437Sluigi		ctx->v0.eq_id = cq->eq->eq_id;
1689231437Sluigi	}
1690231437Sluigi
1691231437Sluigi	mbx.u0.s.embedded = 1;
1692231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_cq);
1693231437Sluigi
1694231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1695231437Sluigi	if (rc)
1696231437Sluigi		goto error;
1697231437Sluigi
1698231437Sluigi	cq->cq_id = LE_16(fwcmd->params.rsp.cq_id);
1699231437Sluigi
1700231437Sluigi	return 0;
1701231437Sluigierror:
1702231437Sluigi	device_printf(sc->dev, "Mbox Create CQ failed\n");
1703231437Sluigi	return rc;
1704231437Sluigi
1705231437Sluigi}
1706