1227569Sphilip/*-
2227569Sphilip * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
3227569Sphilip *
4227569Sphilip * Redistribution and use in source and binary forms, with or without
5227569Sphilip * modification, are permitted provided that the following conditions
6227569Sphilip * are met:
7227569Sphilip * 1. Redistributions of source code must retain the above copyright
8227569Sphilip *    notice, this list of conditions and the following disclaimer.
9227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright
10227569Sphilip *    notice, this list of conditions and the following disclaimer in the
11227569Sphilip *    documentation and/or other materials provided with the distribution.
12227569Sphilip *
13227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16227569Sphilip * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23227569Sphilip * SUCH DAMAGE.
24227569Sphilip */
25228078Sphilip
26228078Sphilip#include <sys/cdefs.h>
27228078Sphilip__FBSDID("$FreeBSD$");
28228078Sphilip
29227569Sphilip#include "efsys.h"
30227569Sphilip#include "efx.h"
31227569Sphilip#include "efx_impl.h"
32227569Sphilip
33227569Sphilip#if EFSYS_OPT_SIENA
34227569Sphilip
35227569Sphilip	__checkReturn	int
36227569Sphilipsiena_mac_poll(
37227569Sphilip	__in		efx_nic_t *enp,
38227569Sphilip	__out		efx_link_mode_t *link_modep)
39227569Sphilip{
40227569Sphilip	efx_port_t *epp = &(enp->en_port);
41227569Sphilip	siena_link_state_t sls;
42227569Sphilip	int rc;
43227569Sphilip
44227569Sphilip	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
45227569Sphilip		goto fail1;
46227569Sphilip
47227569Sphilip	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
48227569Sphilip	epp->ep_fcntl = sls.sls_fcntl;
49227569Sphilip
50227569Sphilip	*link_modep = sls.sls_link_mode;
51227569Sphilip
52227569Sphilip	return (0);
53227569Sphilip
54227569Sphilipfail1:
55227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
56227569Sphilip
57227569Sphilip	*link_modep = EFX_LINK_UNKNOWN;
58227569Sphilip
59227569Sphilip	return (rc);
60227569Sphilip}
61227569Sphilip
62227569Sphilip	__checkReturn	int
63227569Sphilipsiena_mac_up(
64227569Sphilip	__in		efx_nic_t *enp,
65227569Sphilip	__out		boolean_t *mac_upp)
66227569Sphilip{
67227569Sphilip	siena_link_state_t sls;
68227569Sphilip	int rc;
69227569Sphilip
70227569Sphilip	/*
71227569Sphilip	 * Because Siena doesn't *require* polling, we can't rely on
72227569Sphilip	 * siena_mac_poll() being executed to populate epp->ep_mac_up.
73227569Sphilip	 */
74227569Sphilip	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
75227569Sphilip		goto fail1;
76227569Sphilip
77227569Sphilip	*mac_upp = sls.sls_mac_up;
78227569Sphilip
79227569Sphilip	return (0);
80227569Sphilip
81227569Sphilipfail1:
82227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
83227569Sphilip
84227569Sphilip	return (rc);
85227569Sphilip}
86227569Sphilip
87227569Sphilip	__checkReturn	int
88227569Sphilipsiena_mac_reconfigure(
89227569Sphilip	__in		efx_nic_t *enp)
90227569Sphilip{
91227569Sphilip	efx_port_t *epp = &(enp->en_port);
92227569Sphilip	uint8_t payload[MAX(MC_CMD_SET_MAC_IN_LEN,
93227569Sphilip			    MC_CMD_SET_MCAST_HASH_IN_LEN)];
94227569Sphilip	efx_mcdi_req_t req;
95227569Sphilip	unsigned int fcntl;
96227569Sphilip	int rc;
97227569Sphilip
98227569Sphilip	req.emr_cmd = MC_CMD_SET_MAC;
99227569Sphilip	req.emr_in_buf = payload;
100227569Sphilip	req.emr_in_length = MC_CMD_SET_MAC_IN_LEN;
101227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_SET_MAC_OUT_LEN == 0);
102227569Sphilip	req.emr_out_buf = NULL;
103227569Sphilip	req.emr_out_length = 0;
104227569Sphilip
105227569Sphilip	MCDI_IN_SET_DWORD(req, SET_MAC_IN_MTU, epp->ep_mac_pdu);
106227569Sphilip	MCDI_IN_SET_DWORD(req, SET_MAC_IN_DRAIN, epp->ep_mac_drain ? 1 : 0);
107227569Sphilip	EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, SET_MAC_IN_ADDR),
108227569Sphilip			    epp->ep_mac_addr);
109227569Sphilip	MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT,
110227569Sphilip				    SET_MAC_IN_REJECT_UNCST, !epp->ep_unicst,
111227569Sphilip				    SET_MAC_IN_REJECT_BRDCST, !epp->ep_brdcst);
112227569Sphilip
113227569Sphilip	if (epp->ep_fcntl_autoneg)
114227569Sphilip		/* efx_fcntl_set() has already set the phy capabilities */
115227569Sphilip		fcntl = MC_CMD_FCNTL_AUTO;
116227569Sphilip	else if (epp->ep_fcntl & EFX_FCNTL_RESPOND)
117227569Sphilip		fcntl = (epp->ep_fcntl & EFX_FCNTL_GENERATE)
118227569Sphilip			? MC_CMD_FCNTL_BIDIR
119227569Sphilip			: MC_CMD_FCNTL_RESPOND;
120227569Sphilip	else
121227569Sphilip		fcntl = MC_CMD_FCNTL_OFF;
122227569Sphilip
123227569Sphilip	MCDI_IN_SET_DWORD(req, SET_MAC_IN_FCNTL, fcntl);
124227569Sphilip
125227569Sphilip	efx_mcdi_execute(enp, &req);
126227569Sphilip
127227569Sphilip	if (req.emr_rc != 0) {
128227569Sphilip		rc = req.emr_rc;
129227569Sphilip		goto fail1;
130227569Sphilip	}
131227569Sphilip
132227569Sphilip	/* Push multicast hash. Set the broadcast bit (0xff) appropriately */
133227569Sphilip	req.emr_cmd = MC_CMD_SET_MCAST_HASH;
134227569Sphilip	req.emr_in_buf = payload;
135227569Sphilip	req.emr_in_length = MC_CMD_SET_MCAST_HASH_IN_LEN;
136227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_SET_MCAST_HASH_OUT_LEN == 0);
137227569Sphilip	req.emr_out_buf = NULL;
138227569Sphilip	req.emr_out_length = 0;
139227569Sphilip
140227569Sphilip	memcpy(MCDI_IN2(req, uint8_t, SET_MCAST_HASH_IN_HASH0),
141227569Sphilip	    epp->ep_multicst_hash, sizeof (epp->ep_multicst_hash));
142227569Sphilip	if (epp->ep_brdcst)
143227569Sphilip		EFX_SET_OWORD_BIT(*MCDI_IN2(req, efx_oword_t,
144227569Sphilip		    SET_MCAST_HASH_IN_HASH1), 0x7f);
145227569Sphilip
146227569Sphilip	efx_mcdi_execute(enp, &req);
147227569Sphilip
148227569Sphilip	if (req.emr_rc != 0) {
149227569Sphilip		rc = req.emr_rc;
150227569Sphilip		goto fail2;
151227569Sphilip	}
152227569Sphilip
153227569Sphilip	return (0);
154227569Sphilip
155227569Sphilipfail2:
156227569Sphilip	EFSYS_PROBE(fail2);
157227569Sphilipfail1:
158227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
159227569Sphilip
160227569Sphilip	return (rc);
161227569Sphilip}
162227569Sphilip
163227569Sphilip#if EFSYS_OPT_LOOPBACK
164227569Sphilip
165227569Sphilip	__checkReturn	int
166227569Sphilipsiena_mac_loopback_set(
167227569Sphilip	__in		efx_nic_t *enp,
168227569Sphilip	__in		efx_link_mode_t link_mode,
169227569Sphilip	__in		efx_loopback_type_t loopback_type)
170227569Sphilip{
171227569Sphilip	efx_port_t *epp = &(enp->en_port);
172227569Sphilip	efx_phy_ops_t *epop = epp->ep_epop;
173227569Sphilip	efx_loopback_type_t old_loopback_type;
174227569Sphilip	efx_link_mode_t old_loopback_link_mode;
175227569Sphilip	int rc;
176227569Sphilip
177227569Sphilip	/* The PHY object handles this on Siena */
178227569Sphilip	old_loopback_type = epp->ep_loopback_type;
179227569Sphilip	old_loopback_link_mode = epp->ep_loopback_link_mode;
180227569Sphilip	epp->ep_loopback_type = loopback_type;
181227569Sphilip	epp->ep_loopback_link_mode = link_mode;
182227569Sphilip
183227569Sphilip	if ((rc = epop->epo_reconfigure(enp)) != 0)
184227569Sphilip		goto fail1;
185227569Sphilip
186227569Sphilip	return (0);
187227569Sphilip
188227569Sphilipfail1:
189227569Sphilip	EFSYS_PROBE(fail2);
190227569Sphilip
191227569Sphilip	epp->ep_loopback_type = old_loopback_type;
192227569Sphilip	epp->ep_loopback_link_mode = old_loopback_link_mode;
193227569Sphilip
194227569Sphilip	return (rc);
195227569Sphilip}
196227569Sphilip
197227569Sphilip#endif	/* EFSYS_OPT_LOOPBACK */
198227569Sphilip
199227569Sphilip#if EFSYS_OPT_MAC_STATS
200227569Sphilip
201227569Sphilip	__checkReturn			int
202227569Sphilipsiena_mac_stats_clear(
203227569Sphilip	__in				efx_nic_t *enp)
204227569Sphilip{
205227569Sphilip	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
206227569Sphilip	efx_mcdi_req_t req;
207227569Sphilip	int rc;
208227569Sphilip
209227569Sphilip	req.emr_cmd = MC_CMD_MAC_STATS;
210227569Sphilip	req.emr_in_buf = payload;
211227569Sphilip	req.emr_in_length = sizeof (payload);
212227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
213227569Sphilip	req.emr_out_buf = NULL;
214227569Sphilip	req.emr_out_length = 0;
215227569Sphilip
216227569Sphilip	MCDI_IN_POPULATE_DWORD_3(req, MAC_STATS_IN_CMD,
217227569Sphilip				    MAC_STATS_IN_DMA, 0,
218227569Sphilip				    MAC_STATS_IN_CLEAR, 1,
219227569Sphilip				    MAC_STATS_IN_PERIODIC_CHANGE, 0);
220227569Sphilip
221227569Sphilip	efx_mcdi_execute(enp, &req);
222227569Sphilip
223227569Sphilip	if (req.emr_rc != 0) {
224227569Sphilip		rc = req.emr_rc;
225227569Sphilip		goto fail1;
226227569Sphilip	}
227227569Sphilip
228227569Sphilip	return (0);
229227569Sphilip
230227569Sphilipfail1:
231227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
232227569Sphilip
233227569Sphilip	return (rc);
234227569Sphilip}
235227569Sphilip
236227569Sphilip	__checkReturn			int
237227569Sphilipsiena_mac_stats_upload(
238227569Sphilip	__in				efx_nic_t *enp,
239227569Sphilip	__in				efsys_mem_t *esmp)
240227569Sphilip{
241227569Sphilip	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
242227569Sphilip	efx_mcdi_req_t req;
243227569Sphilip	size_t bytes;
244227569Sphilip	int rc;
245227569Sphilip
246227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MAC_NSTATS * sizeof (uint64_t) <=
247227569Sphilip	    EFX_MAC_STATS_SIZE);
248227569Sphilip
249227569Sphilip	bytes = MC_CMD_MAC_NSTATS * sizeof (uint64_t);
250227569Sphilip
251227569Sphilip	req.emr_cmd = MC_CMD_MAC_STATS;
252227569Sphilip	req.emr_in_buf = payload;
253227569Sphilip	req.emr_in_length = sizeof (payload);
254227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
255227569Sphilip	req.emr_out_buf = NULL;
256227569Sphilip	req.emr_out_length = 0;
257227569Sphilip
258227569Sphilip	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_LO,
259227569Sphilip			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
260227569Sphilip	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_HI,
261227569Sphilip			    EFSYS_MEM_ADDR(esmp) >> 32);
262227569Sphilip	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_LEN, bytes);
263227569Sphilip
264227569Sphilip	/*
265227569Sphilip	 * The MC DMAs aggregate statistics for our convinience, so we can
266227569Sphilip	 * avoid having to pull the statistics buffer into the cache to
267227569Sphilip	 * maintain cumulative statistics.
268227569Sphilip	 */
269227569Sphilip	MCDI_IN_POPULATE_DWORD_3(req, MAC_STATS_IN_CMD,
270227569Sphilip				    MAC_STATS_IN_DMA, 1,
271227569Sphilip				    MAC_STATS_IN_CLEAR, 0,
272227569Sphilip				    MAC_STATS_IN_PERIODIC_CHANGE, 0);
273227569Sphilip
274227569Sphilip	efx_mcdi_execute(enp, &req);
275227569Sphilip
276227569Sphilip	if (req.emr_rc != 0) {
277227569Sphilip		rc = req.emr_rc;
278227569Sphilip		goto fail1;
279227569Sphilip	}
280227569Sphilip
281227569Sphilip	return (0);
282227569Sphilip
283227569Sphilipfail1:
284227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
285227569Sphilip
286227569Sphilip	return (rc);
287227569Sphilip}
288227569Sphilip
289227569Sphilip	__checkReturn			int
290227569Sphilipsiena_mac_stats_periodic(
291227569Sphilip	__in				efx_nic_t *enp,
292227569Sphilip	__in				efsys_mem_t *esmp,
293227569Sphilip	__in				uint16_t period,
294227569Sphilip	__in				boolean_t events)
295227569Sphilip{
296227569Sphilip	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
297227569Sphilip	efx_mcdi_req_t req;
298227569Sphilip	size_t bytes;
299227569Sphilip	int rc;
300227569Sphilip
301227569Sphilip	bytes = MC_CMD_MAC_NSTATS * sizeof (uint64_t);
302227569Sphilip
303227569Sphilip	req.emr_cmd = MC_CMD_MAC_STATS;
304227569Sphilip	req.emr_in_buf = payload;
305227569Sphilip	req.emr_in_length = sizeof (payload);
306227569Sphilip	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
307227569Sphilip	req.emr_out_buf = NULL;
308227569Sphilip	req.emr_out_length = 0;
309227569Sphilip
310227569Sphilip	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_LO,
311227569Sphilip			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
312227569Sphilip	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_HI,
313227569Sphilip			    EFSYS_MEM_ADDR(esmp) >> 32);
314227569Sphilip	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_LEN, bytes);
315227569Sphilip
316227569Sphilip	/*
317227569Sphilip	 * The MC DMAs aggregate statistics for our convinience, so we can
318227569Sphilip	 * avoid having to pull the statistics buffer into the cache to
319227569Sphilip	 * maintain cumulative statistics.
320227569Sphilip	 */
321227569Sphilip	MCDI_IN_POPULATE_DWORD_6(req, MAC_STATS_IN_CMD,
322227569Sphilip			    MAC_STATS_IN_DMA, 0,
323227569Sphilip			    MAC_STATS_IN_CLEAR, 0,
324227569Sphilip			    MAC_STATS_IN_PERIODIC_CHANGE, 1,
325227569Sphilip			    MAC_STATS_IN_PERIODIC_ENABLE, period ? 1 : 0,
326227569Sphilip			    MAC_STATS_IN_PERIODIC_NOEVENT, events ? 0 : 1,
327227569Sphilip			    MAC_STATS_IN_PERIOD_MS, period);
328227569Sphilip
329227569Sphilip	efx_mcdi_execute(enp, &req);
330227569Sphilip
331227569Sphilip	if (req.emr_rc != 0) {
332227569Sphilip		rc = req.emr_rc;
333227569Sphilip		goto fail1;
334227569Sphilip	}
335227569Sphilip
336227569Sphilip	return (0);
337227569Sphilip
338227569Sphilipfail1:
339227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
340227569Sphilip
341227569Sphilip	return (rc);
342227569Sphilip}
343227569Sphilip
344227569Sphilip
345227569Sphilip#define	SIENA_MAC_STAT_READ(_esmp, _field, _eqp)			\
346227569Sphilip	EFSYS_MEM_READQ((_esmp), (_field) * sizeof (efx_qword_t), _eqp)
347227569Sphilip
348227569Sphilip	__checkReturn			int
349227569Sphilipsiena_mac_stats_update(
350227569Sphilip	__in				efx_nic_t *enp,
351227569Sphilip	__in				efsys_mem_t *esmp,
352227569Sphilip	__out_ecount(EFX_MAC_NSTATS)	efsys_stat_t *stat,
353227569Sphilip	__out_opt			uint32_t *generationp)
354227569Sphilip{
355227569Sphilip	efx_qword_t rx_pkts;
356227569Sphilip	efx_qword_t value;
357227569Sphilip	efx_qword_t generation_start;
358227569Sphilip	efx_qword_t generation_end;
359227569Sphilip
360227569Sphilip	_NOTE(ARGUNUSED(enp))
361227569Sphilip
362227569Sphilip	/* Read END first so we don't race with the MC */
363227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END,
364227569Sphilip			    &generation_end);
365227569Sphilip	EFSYS_MEM_READ_BARRIER();
366227569Sphilip
367227569Sphilip	/* TX */
368227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PKTS, &value);
369227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
370227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_CONTROL_PKTS, &value);
371227569Sphilip	EFSYS_STAT_SUBR_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
372227569Sphilip
373227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PAUSE_PKTS, &value);
374227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PAUSE_PKTS]), &value);
375227569Sphilip
376227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_UNICAST_PKTS, &value);
377227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_UNICST_PKTS]), &value);
378227569Sphilip
379227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTICAST_PKTS, &value);
380227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULTICST_PKTS]), &value);
381227569Sphilip
382227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BROADCAST_PKTS, &value);
383227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_BRDCST_PKTS]), &value);
384227569Sphilip
385227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BYTES, &value);
386227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_OCTETS]), &value);
387227569Sphilip
388227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LT64_PKTS, &value);
389227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
390227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_64_PKTS, &value);
391227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
392227569Sphilip
393227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_65_TO_127_PKTS, &value);
394227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_65_TO_127_PKTS]), &value);
395227569Sphilip
396227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_128_TO_255_PKTS, &value);
397227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_128_TO_255_PKTS]), &value);
398227569Sphilip
399227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_256_TO_511_PKTS, &value);
400227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_256_TO_511_PKTS]), &value);
401227569Sphilip
402227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_512_TO_1023_PKTS, &value);
403227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_512_TO_1023_PKTS]), &value);
404227569Sphilip
405227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_1024_TO_15XX_PKTS, &value);
406227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_1024_TO_15XX_PKTS]), &value);
407227569Sphilip
408227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS, &value);
409227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
410227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_GTJUMBO_PKTS, &value);
411227569Sphilip	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
412227569Sphilip
413227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BAD_FCS_PKTS, &value);
414227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_ERRORS]), &value);
415227569Sphilip
416227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS, &value);
417227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_SGL_COL_PKTS]), &value);
418227569Sphilip
419227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS,
420227569Sphilip			    &value);
421227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULT_COL_PKTS]), &value);
422227569Sphilip
423227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS,
424227569Sphilip			    &value);
425227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_COL_PKTS]), &value);
426227569Sphilip
427227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LATE_COLLISION_PKTS, &value);
428227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LATE_COL_PKTS]), &value);
429227569Sphilip
430227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_DEFERRED_PKTS, &value);
431227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_DEF_PKTS]), &value);
432227569Sphilip
433227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS,
434227569Sphilip	    &value);
435227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_DEF_PKTS]), &value);
436227569Sphilip
437227569Sphilip	/* RX */
438227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BYTES, &rx_pkts);
439227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_OCTETS]), &rx_pkts);
440227569Sphilip
441227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PKTS, &value);
442227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PKTS]), &value);
443227569Sphilip
444227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNICAST_PKTS, &value);
445227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_UNICST_PKTS]), &value);
446227569Sphilip
447227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MULTICAST_PKTS, &value);
448227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MULTICST_PKTS]), &value);
449227569Sphilip
450227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BROADCAST_PKTS, &value);
451227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_BRDCST_PKTS]), &value);
452227569Sphilip
453227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PAUSE_PKTS, &value);
454227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PAUSE_PKTS]), &value);
455227569Sphilip
456227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNDERSIZE_PKTS, &value);
457227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
458227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_64_PKTS, &value);
459227569Sphilip	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
460227569Sphilip
461227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_65_TO_127_PKTS, &value);
462227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_65_TO_127_PKTS]), &value);
463227569Sphilip
464227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_128_TO_255_PKTS, &value);
465227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_128_TO_255_PKTS]), &value);
466227569Sphilip
467227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_256_TO_511_PKTS, &value);
468227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_256_TO_511_PKTS]), &value);
469227569Sphilip
470227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_512_TO_1023_PKTS, &value);
471227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_512_TO_1023_PKTS]), &value);
472227569Sphilip
473227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_1024_TO_15XX_PKTS, &value);
474227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_1024_TO_15XX_PKTS]), &value);
475227569Sphilip
476227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS, &value);
477227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
478227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_GTJUMBO_PKTS, &value);
479227569Sphilip	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
480227569Sphilip
481227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BAD_FCS_PKTS, &value);
482227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FCS_ERRORS]), &value);
483227569Sphilip
484227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_OVERFLOW_PKTS, &value);
485227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_DROP_EVENTS]), &value);
486227569Sphilip
487227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_FALSE_CARRIER_PKTS, &value);
488227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FALSE_CARRIER_ERRORS]), &value);
489227569Sphilip
490227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS, &value);
491227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_SYMBOL_ERRORS]), &value);
492227569Sphilip
493227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_ALIGN_ERROR_PKTS, &value);
494227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_ALIGN_ERRORS]), &value);
495227569Sphilip
496227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS, &value);
497227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_INTERNAL_ERRORS]), &value);
498227569Sphilip
499227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_JABBER_PKTS, &value);
500227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_JABBER_PKTS]), &value);
501227569Sphilip
502227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_CHAR_ERR, &value);
503227569Sphilip	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_CHAR_ERR]),
504227569Sphilip			    &(value.eq_dword[0]));
505227569Sphilip	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_CHAR_ERR]),
506227569Sphilip			    &(value.eq_dword[1]));
507227569Sphilip
508227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_CHAR_ERR, &value);
509227569Sphilip	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_CHAR_ERR]),
510227569Sphilip			    &(value.eq_dword[0]));
511227569Sphilip	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_CHAR_ERR]),
512227569Sphilip			    &(value.eq_dword[1]));
513227569Sphilip
514227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_DISP_ERR, &value);
515227569Sphilip	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_DISP_ERR]),
516227569Sphilip			    &(value.eq_dword[0]));
517227569Sphilip	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_DISP_ERR]),
518227569Sphilip			    &(value.eq_dword[1]));
519227569Sphilip
520227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_DISP_ERR, &value);
521227569Sphilip	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_DISP_ERR]),
522227569Sphilip			    &(value.eq_dword[0]));
523227569Sphilip	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_DISP_ERR]),
524227569Sphilip			    &(value.eq_dword[1]));
525227569Sphilip
526227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MATCH_FAULT, &value);
527227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MATCH_FAULT]), &value);
528227569Sphilip
529227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_NODESC_DROPS, &value);
530227569Sphilip	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), &value);
531227569Sphilip
532227569Sphilip	EFSYS_MEM_READ_BARRIER();
533227569Sphilip	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START,
534227569Sphilip			    &generation_start);
535227569Sphilip
536227569Sphilip	/* Check that we didn't read the stats in the middle of a DMA */
537227569Sphilip	if (memcmp(&generation_start, &generation_end,
538227569Sphilip	    sizeof (generation_start)))
539227569Sphilip		return (EAGAIN);
540227569Sphilip
541227569Sphilip	if (generationp)
542227569Sphilip		*generationp = EFX_QWORD_FIELD(generation_start, EFX_DWORD_0);
543227569Sphilip
544227569Sphilip	return (0);
545227569Sphilip}
546227569Sphilip
547227569Sphilip#endif	/* EFSYS_OPT_MAC_STATS */
548227569Sphilip
549227569Sphilip#endif	/* EFSYS_OPT_SIENA */
550