1f7917c00SJeff Kirsher /*
2f7917c00SJeff Kirsher * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
3f7917c00SJeff Kirsher *
4f7917c00SJeff Kirsher * This software is available to you under a choice of one of two
5f7917c00SJeff Kirsher * licenses. You may choose to be licensed under the terms of the GNU
6f7917c00SJeff Kirsher * General Public License (GPL) Version 2, available from the file
7f7917c00SJeff Kirsher * COPYING in the main directory of this source tree, or the
8f7917c00SJeff Kirsher * OpenIB.org BSD license below:
9f7917c00SJeff Kirsher *
10f7917c00SJeff Kirsher * Redistribution and use in source and binary forms, with or
11f7917c00SJeff Kirsher * without modification, are permitted provided that the following
12f7917c00SJeff Kirsher * conditions are met:
13f7917c00SJeff Kirsher *
14f7917c00SJeff Kirsher * - Redistributions of source code must retain the above
15f7917c00SJeff Kirsher * copyright notice, this list of conditions and the following
16f7917c00SJeff Kirsher * disclaimer.
17f7917c00SJeff Kirsher *
18f7917c00SJeff Kirsher * - Redistributions in binary form must reproduce the above
19f7917c00SJeff Kirsher * copyright notice, this list of conditions and the following
20f7917c00SJeff Kirsher * disclaimer in the documentation and/or other materials
21f7917c00SJeff Kirsher * provided with the distribution.
22f7917c00SJeff Kirsher *
23f7917c00SJeff Kirsher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24f7917c00SJeff Kirsher * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25f7917c00SJeff Kirsher * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26f7917c00SJeff Kirsher * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27f7917c00SJeff Kirsher * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28f7917c00SJeff Kirsher * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29f7917c00SJeff Kirsher * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30f7917c00SJeff Kirsher * SOFTWARE.
31f7917c00SJeff Kirsher */
32f7917c00SJeff Kirsher #include "common.h"
33f7917c00SJeff Kirsher #include "regs.h"
34f7917c00SJeff Kirsher
35f7917c00SJeff Kirsher /*
36f7917c00SJeff Kirsher * # of exact address filters. The first one is used for the station address,
37f7917c00SJeff Kirsher * the rest are available for multicast addresses.
38f7917c00SJeff Kirsher */
39f7917c00SJeff Kirsher #define EXACT_ADDR_FILTERS 8
40f7917c00SJeff Kirsher
macidx(const struct cmac * mac)41f7917c00SJeff Kirsher static inline int macidx(const struct cmac *mac)
42f7917c00SJeff Kirsher {
43f7917c00SJeff Kirsher return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR);
44f7917c00SJeff Kirsher }
45f7917c00SJeff Kirsher
xaui_serdes_reset(struct cmac * mac)46f7917c00SJeff Kirsher static void xaui_serdes_reset(struct cmac *mac)
47f7917c00SJeff Kirsher {
48f7917c00SJeff Kirsher static const unsigned int clear[] = {
49f7917c00SJeff Kirsher F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1,
50f7917c00SJeff Kirsher F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3
51f7917c00SJeff Kirsher };
52f7917c00SJeff Kirsher
53f7917c00SJeff Kirsher int i;
54f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
55f7917c00SJeff Kirsher u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset;
56f7917c00SJeff Kirsher
57f7917c00SJeff Kirsher t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] |
58f7917c00SJeff Kirsher F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 |
59f7917c00SJeff Kirsher F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 |
60f7917c00SJeff Kirsher F_RESETPLL23 | F_RESETPLL01);
61f7917c00SJeff Kirsher t3_read_reg(adap, ctrl);
62f7917c00SJeff Kirsher udelay(15);
63f7917c00SJeff Kirsher
64f7917c00SJeff Kirsher for (i = 0; i < ARRAY_SIZE(clear); i++) {
65f7917c00SJeff Kirsher t3_set_reg_field(adap, ctrl, clear[i], 0);
66f7917c00SJeff Kirsher udelay(15);
67f7917c00SJeff Kirsher }
68f7917c00SJeff Kirsher }
69f7917c00SJeff Kirsher
t3b_pcs_reset(struct cmac * mac)70f7917c00SJeff Kirsher void t3b_pcs_reset(struct cmac *mac)
71f7917c00SJeff Kirsher {
72f7917c00SJeff Kirsher t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
73f7917c00SJeff Kirsher F_PCS_RESET_, 0);
74f7917c00SJeff Kirsher udelay(20);
75f7917c00SJeff Kirsher t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0,
76f7917c00SJeff Kirsher F_PCS_RESET_);
77f7917c00SJeff Kirsher }
78f7917c00SJeff Kirsher
t3_mac_reset(struct cmac * mac)79f7917c00SJeff Kirsher int t3_mac_reset(struct cmac *mac)
80f7917c00SJeff Kirsher {
81f7917c00SJeff Kirsher static const struct addr_val_pair mac_reset_avp[] = {
82f7917c00SJeff Kirsher {A_XGM_TX_CTRL, 0},
83f7917c00SJeff Kirsher {A_XGM_RX_CTRL, 0},
84f7917c00SJeff Kirsher {A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES |
85f7917c00SJeff Kirsher F_RMFCS | F_ENJUMBO | F_ENHASHMCAST},
86f7917c00SJeff Kirsher {A_XGM_RX_HASH_LOW, 0},
87f7917c00SJeff Kirsher {A_XGM_RX_HASH_HIGH, 0},
88f7917c00SJeff Kirsher {A_XGM_RX_EXACT_MATCH_LOW_1, 0},
89f7917c00SJeff Kirsher {A_XGM_RX_EXACT_MATCH_LOW_2, 0},
90f7917c00SJeff Kirsher {A_XGM_RX_EXACT_MATCH_LOW_3, 0},
91f7917c00SJeff Kirsher {A_XGM_RX_EXACT_MATCH_LOW_4, 0},
92f7917c00SJeff Kirsher {A_XGM_RX_EXACT_MATCH_LOW_5, 0},
93f7917c00SJeff Kirsher {A_XGM_RX_EXACT_MATCH_LOW_6, 0},
94f7917c00SJeff Kirsher {A_XGM_RX_EXACT_MATCH_LOW_7, 0},
95f7917c00SJeff Kirsher {A_XGM_RX_EXACT_MATCH_LOW_8, 0},
96f7917c00SJeff Kirsher {A_XGM_STAT_CTRL, F_CLRSTATS}
97f7917c00SJeff Kirsher };
98f7917c00SJeff Kirsher u32 val;
99f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
100f7917c00SJeff Kirsher unsigned int oft = mac->offset;
101f7917c00SJeff Kirsher
102f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
103f7917c00SJeff Kirsher t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
104f7917c00SJeff Kirsher
105f7917c00SJeff Kirsher t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft);
106f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft,
107f7917c00SJeff Kirsher F_RXSTRFRWRD | F_DISERRFRAMES,
108f7917c00SJeff Kirsher uses_xaui(adap) ? 0 : F_RXSTRFRWRD);
109f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX);
110f7917c00SJeff Kirsher
111f7917c00SJeff Kirsher if (uses_xaui(adap)) {
112f7917c00SJeff Kirsher if (adap->params.rev == 0) {
113f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
114f7917c00SJeff Kirsher F_RXENABLE | F_TXENABLE);
115f7917c00SJeff Kirsher if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft,
116f7917c00SJeff Kirsher F_CMULOCK, 1, 5, 2)) {
117f7917c00SJeff Kirsher CH_ERR(adap,
118f7917c00SJeff Kirsher "MAC %d XAUI SERDES CMU lock failed\n",
119f7917c00SJeff Kirsher macidx(mac));
120f7917c00SJeff Kirsher return -1;
121f7917c00SJeff Kirsher }
122f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
123f7917c00SJeff Kirsher F_SERDESRESET_);
124f7917c00SJeff Kirsher } else
125f7917c00SJeff Kirsher xaui_serdes_reset(mac);
126f7917c00SJeff Kirsher }
127f7917c00SJeff Kirsher
128f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
129f7917c00SJeff Kirsher V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE),
130f7917c00SJeff Kirsher V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER);
131f7917c00SJeff Kirsher val = F_MAC_RESET_ | F_XGMAC_STOP_EN;
132f7917c00SJeff Kirsher
133f7917c00SJeff Kirsher if (is_10G(adap))
134f7917c00SJeff Kirsher val |= F_PCS_RESET_;
135f7917c00SJeff Kirsher else if (uses_xaui(adap))
136f7917c00SJeff Kirsher val |= F_PCS_RESET_ | F_XG2G_RESET_;
137f7917c00SJeff Kirsher else
138f7917c00SJeff Kirsher val |= F_RGMII_RESET_ | F_XG2G_RESET_;
139f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
140f7917c00SJeff Kirsher t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
141f7917c00SJeff Kirsher if ((val & F_PCS_RESET_) && adap->params.rev) {
142f7917c00SJeff Kirsher msleep(1);
143f7917c00SJeff Kirsher t3b_pcs_reset(mac);
144f7917c00SJeff Kirsher }
145f7917c00SJeff Kirsher
146f7917c00SJeff Kirsher memset(&mac->stats, 0, sizeof(mac->stats));
147f7917c00SJeff Kirsher return 0;
148f7917c00SJeff Kirsher }
149f7917c00SJeff Kirsher
t3b2_mac_reset(struct cmac * mac)150f7917c00SJeff Kirsher static int t3b2_mac_reset(struct cmac *mac)
151f7917c00SJeff Kirsher {
152f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
153f7917c00SJeff Kirsher unsigned int oft = mac->offset, store;
154f7917c00SJeff Kirsher int idx = macidx(mac);
155f7917c00SJeff Kirsher u32 val;
156f7917c00SJeff Kirsher
157f7917c00SJeff Kirsher if (!macidx(mac))
158f7917c00SJeff Kirsher t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
159f7917c00SJeff Kirsher else
160f7917c00SJeff Kirsher t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
161f7917c00SJeff Kirsher
162f7917c00SJeff Kirsher /* Stop NIC traffic to reduce the number of TXTOGGLES */
163f7917c00SJeff Kirsher t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0);
164f7917c00SJeff Kirsher /* Ensure TX drains */
165f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0);
166f7917c00SJeff Kirsher
167f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
168f7917c00SJeff Kirsher t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
169f7917c00SJeff Kirsher
170f7917c00SJeff Kirsher /* Store A_TP_TX_DROP_CFG_CH0 */
171f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
172f7917c00SJeff Kirsher store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx);
173f7917c00SJeff Kirsher
174f7917c00SJeff Kirsher msleep(10);
175f7917c00SJeff Kirsher
176f7917c00SJeff Kirsher /* Change DROP_CFG to 0xc0000011 */
177f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
178f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011);
179f7917c00SJeff Kirsher
180f7917c00SJeff Kirsher /* Check for xgm Rx fifo empty */
181f7917c00SJeff Kirsher /* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */
182f7917c00SJeff Kirsher if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
183f7917c00SJeff Kirsher 0x80000000, 1, 1000, 2)) {
184f7917c00SJeff Kirsher CH_ERR(adap, "MAC %d Rx fifo drain failed\n",
185f7917c00SJeff Kirsher macidx(mac));
186f7917c00SJeff Kirsher return -1;
187f7917c00SJeff Kirsher }
188f7917c00SJeff Kirsher
189f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0);
190f7917c00SJeff Kirsher t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
191f7917c00SJeff Kirsher
192f7917c00SJeff Kirsher val = F_MAC_RESET_;
193f7917c00SJeff Kirsher if (is_10G(adap))
194f7917c00SJeff Kirsher val |= F_PCS_RESET_;
195f7917c00SJeff Kirsher else if (uses_xaui(adap))
196f7917c00SJeff Kirsher val |= F_PCS_RESET_ | F_XG2G_RESET_;
197f7917c00SJeff Kirsher else
198f7917c00SJeff Kirsher val |= F_RGMII_RESET_ | F_XG2G_RESET_;
199f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
200f7917c00SJeff Kirsher t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
201f7917c00SJeff Kirsher if ((val & F_PCS_RESET_) && adap->params.rev) {
202f7917c00SJeff Kirsher msleep(1);
203f7917c00SJeff Kirsher t3b_pcs_reset(mac);
204f7917c00SJeff Kirsher }
205f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_CFG + oft,
206f7917c00SJeff Kirsher F_DISPAUSEFRAMES | F_EN1536BFRAMES |
207f7917c00SJeff Kirsher F_RMFCS | F_ENJUMBO | F_ENHASHMCAST);
208f7917c00SJeff Kirsher
209f7917c00SJeff Kirsher /* Restore the DROP_CFG */
210f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
211f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_DATA, store);
212f7917c00SJeff Kirsher
213f7917c00SJeff Kirsher if (!idx)
214f7917c00SJeff Kirsher t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE);
215f7917c00SJeff Kirsher else
216f7917c00SJeff Kirsher t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE);
217f7917c00SJeff Kirsher
218f7917c00SJeff Kirsher /* re-enable nic traffic */
219f7917c00SJeff Kirsher t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
220f7917c00SJeff Kirsher
221f7917c00SJeff Kirsher /* Set: re-enable NIC traffic */
222f7917c00SJeff Kirsher t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
223f7917c00SJeff Kirsher
224f7917c00SJeff Kirsher return 0;
225f7917c00SJeff Kirsher }
226f7917c00SJeff Kirsher
227f7917c00SJeff Kirsher /*
228f7917c00SJeff Kirsher * Set the exact match register 'idx' to recognize the given Ethernet address.
229f7917c00SJeff Kirsher */
set_addr_filter(struct cmac * mac,int idx,const u8 * addr)230f7917c00SJeff Kirsher static void set_addr_filter(struct cmac *mac, int idx, const u8 * addr)
231f7917c00SJeff Kirsher {
232f7917c00SJeff Kirsher u32 addr_lo, addr_hi;
233f7917c00SJeff Kirsher unsigned int oft = mac->offset + idx * 8;
234f7917c00SJeff Kirsher
235f7917c00SJeff Kirsher addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
236f7917c00SJeff Kirsher addr_hi = (addr[5] << 8) | addr[4];
237f7917c00SJeff Kirsher
238f7917c00SJeff Kirsher t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo);
239f7917c00SJeff Kirsher t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi);
240f7917c00SJeff Kirsher }
241f7917c00SJeff Kirsher
242f7917c00SJeff Kirsher /* Set one of the station's unicast MAC addresses. */
t3_mac_set_address(struct cmac * mac,unsigned int idx,const u8 addr[6])243*76660757SJakub Kicinski int t3_mac_set_address(struct cmac *mac, unsigned int idx, const u8 addr[6])
244f7917c00SJeff Kirsher {
245f7917c00SJeff Kirsher if (idx >= mac->nucast)
246f7917c00SJeff Kirsher return -EINVAL;
247f7917c00SJeff Kirsher set_addr_filter(mac, idx, addr);
248f7917c00SJeff Kirsher return 0;
249f7917c00SJeff Kirsher }
250f7917c00SJeff Kirsher
251f7917c00SJeff Kirsher /*
252f7917c00SJeff Kirsher * Specify the number of exact address filters that should be reserved for
253f7917c00SJeff Kirsher * unicast addresses. Caller should reload the unicast and multicast addresses
254f7917c00SJeff Kirsher * after calling this.
255f7917c00SJeff Kirsher */
t3_mac_set_num_ucast(struct cmac * mac,int n)256f7917c00SJeff Kirsher int t3_mac_set_num_ucast(struct cmac *mac, int n)
257f7917c00SJeff Kirsher {
258f7917c00SJeff Kirsher if (n > EXACT_ADDR_FILTERS)
259f7917c00SJeff Kirsher return -EINVAL;
260f7917c00SJeff Kirsher mac->nucast = n;
261f7917c00SJeff Kirsher return 0;
262f7917c00SJeff Kirsher }
263f7917c00SJeff Kirsher
t3_mac_disable_exact_filters(struct cmac * mac)264f7917c00SJeff Kirsher void t3_mac_disable_exact_filters(struct cmac *mac)
265f7917c00SJeff Kirsher {
266f7917c00SJeff Kirsher unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
267f7917c00SJeff Kirsher
268f7917c00SJeff Kirsher for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
269f7917c00SJeff Kirsher u32 v = t3_read_reg(mac->adapter, reg);
270f7917c00SJeff Kirsher t3_write_reg(mac->adapter, reg, v);
271f7917c00SJeff Kirsher }
272f7917c00SJeff Kirsher t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
273f7917c00SJeff Kirsher }
274f7917c00SJeff Kirsher
t3_mac_enable_exact_filters(struct cmac * mac)275f7917c00SJeff Kirsher void t3_mac_enable_exact_filters(struct cmac *mac)
276f7917c00SJeff Kirsher {
277f7917c00SJeff Kirsher unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
278f7917c00SJeff Kirsher
279f7917c00SJeff Kirsher for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
280f7917c00SJeff Kirsher u32 v = t3_read_reg(mac->adapter, reg);
281f7917c00SJeff Kirsher t3_write_reg(mac->adapter, reg, v);
282f7917c00SJeff Kirsher }
283f7917c00SJeff Kirsher t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
284f7917c00SJeff Kirsher }
285f7917c00SJeff Kirsher
286f7917c00SJeff Kirsher /* Calculate the RX hash filter index of an Ethernet address */
hash_hw_addr(const u8 * addr)287f7917c00SJeff Kirsher static int hash_hw_addr(const u8 * addr)
288f7917c00SJeff Kirsher {
289f7917c00SJeff Kirsher int hash = 0, octet, bit, i = 0, c;
290f7917c00SJeff Kirsher
291f7917c00SJeff Kirsher for (octet = 0; octet < 6; ++octet)
292f7917c00SJeff Kirsher for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) {
293f7917c00SJeff Kirsher hash ^= (c & 1) << i;
294f7917c00SJeff Kirsher if (++i == 6)
295f7917c00SJeff Kirsher i = 0;
296f7917c00SJeff Kirsher }
297f7917c00SJeff Kirsher return hash;
298f7917c00SJeff Kirsher }
299f7917c00SJeff Kirsher
t3_mac_set_rx_mode(struct cmac * mac,struct net_device * dev)300f7917c00SJeff Kirsher int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev)
301f7917c00SJeff Kirsher {
302f7917c00SJeff Kirsher u32 val, hash_lo, hash_hi;
303f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
304f7917c00SJeff Kirsher unsigned int oft = mac->offset;
305f7917c00SJeff Kirsher
306f7917c00SJeff Kirsher val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES;
307f7917c00SJeff Kirsher if (dev->flags & IFF_PROMISC)
308f7917c00SJeff Kirsher val |= F_COPYALLFRAMES;
309f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_CFG + oft, val);
310f7917c00SJeff Kirsher
311f7917c00SJeff Kirsher if (dev->flags & IFF_ALLMULTI)
312f7917c00SJeff Kirsher hash_lo = hash_hi = 0xffffffff;
313f7917c00SJeff Kirsher else {
314f7917c00SJeff Kirsher struct netdev_hw_addr *ha;
315f7917c00SJeff Kirsher int exact_addr_idx = mac->nucast;
316f7917c00SJeff Kirsher
317f7917c00SJeff Kirsher hash_lo = hash_hi = 0;
318f7917c00SJeff Kirsher netdev_for_each_mc_addr(ha, dev)
319f7917c00SJeff Kirsher if (exact_addr_idx < EXACT_ADDR_FILTERS)
320f7917c00SJeff Kirsher set_addr_filter(mac, exact_addr_idx++,
321f7917c00SJeff Kirsher ha->addr);
322f7917c00SJeff Kirsher else {
323f7917c00SJeff Kirsher int hash = hash_hw_addr(ha->addr);
324f7917c00SJeff Kirsher
325f7917c00SJeff Kirsher if (hash < 32)
326f7917c00SJeff Kirsher hash_lo |= (1 << hash);
327f7917c00SJeff Kirsher else
328f7917c00SJeff Kirsher hash_hi |= (1 << (hash - 32));
329f7917c00SJeff Kirsher }
330f7917c00SJeff Kirsher }
331f7917c00SJeff Kirsher
332f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo);
333f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi);
334f7917c00SJeff Kirsher return 0;
335f7917c00SJeff Kirsher }
336f7917c00SJeff Kirsher
rx_fifo_hwm(int mtu)337f7917c00SJeff Kirsher static int rx_fifo_hwm(int mtu)
338f7917c00SJeff Kirsher {
339f7917c00SJeff Kirsher int hwm;
340f7917c00SJeff Kirsher
341f7917c00SJeff Kirsher hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
342f7917c00SJeff Kirsher return min(hwm, MAC_RXFIFO_SIZE - 8192);
343f7917c00SJeff Kirsher }
344f7917c00SJeff Kirsher
t3_mac_set_mtu(struct cmac * mac,unsigned int mtu)345f7917c00SJeff Kirsher int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
346f7917c00SJeff Kirsher {
347f7917c00SJeff Kirsher int hwm, lwm, divisor;
348f7917c00SJeff Kirsher int ipg;
349f7917c00SJeff Kirsher unsigned int thres, v, reg;
350f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
351f7917c00SJeff Kirsher
352f7917c00SJeff Kirsher /*
353f7917c00SJeff Kirsher * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max
354f7917c00SJeff Kirsher * packet size register includes header, but not FCS.
355f7917c00SJeff Kirsher */
356f7917c00SJeff Kirsher mtu += 14;
357f7917c00SJeff Kirsher if (mtu > 1536)
358f7917c00SJeff Kirsher mtu += 4;
359f7917c00SJeff Kirsher
360f7917c00SJeff Kirsher if (mtu > MAX_FRAME_SIZE - 4)
361f7917c00SJeff Kirsher return -EINVAL;
362f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
363f7917c00SJeff Kirsher
364f7917c00SJeff Kirsher if (adap->params.rev >= T3_REV_B2 &&
365f7917c00SJeff Kirsher (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
366f7917c00SJeff Kirsher t3_mac_disable_exact_filters(mac);
367f7917c00SJeff Kirsher v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
368f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
369f7917c00SJeff Kirsher F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
370f7917c00SJeff Kirsher
371f7917c00SJeff Kirsher reg = adap->params.rev == T3_REV_B2 ?
372f7917c00SJeff Kirsher A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG;
373f7917c00SJeff Kirsher
374f7917c00SJeff Kirsher /* drain RX FIFO */
375f7917c00SJeff Kirsher if (t3_wait_op_done(adap, reg + mac->offset,
376f7917c00SJeff Kirsher F_RXFIFO_EMPTY, 1, 20, 5)) {
377f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
378f7917c00SJeff Kirsher t3_mac_enable_exact_filters(mac);
379f7917c00SJeff Kirsher return -EIO;
380f7917c00SJeff Kirsher }
381f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
382f7917c00SJeff Kirsher V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
383f7917c00SJeff Kirsher V_RXMAXPKTSIZE(mtu));
384f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
385f7917c00SJeff Kirsher t3_mac_enable_exact_filters(mac);
386f7917c00SJeff Kirsher } else
387f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
388f7917c00SJeff Kirsher V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
389f7917c00SJeff Kirsher V_RXMAXPKTSIZE(mtu));
390f7917c00SJeff Kirsher
391f7917c00SJeff Kirsher /*
392f7917c00SJeff Kirsher * Adjust the PAUSE frame watermarks. We always set the LWM, and the
393f7917c00SJeff Kirsher * HWM only if flow-control is enabled.
394f7917c00SJeff Kirsher */
395f7917c00SJeff Kirsher hwm = rx_fifo_hwm(mtu);
396f7917c00SJeff Kirsher lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
397f7917c00SJeff Kirsher v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
398f7917c00SJeff Kirsher v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
399f7917c00SJeff Kirsher v |= V_RXFIFOPAUSELWM(lwm / 8);
400f7917c00SJeff Kirsher if (G_RXFIFOPAUSEHWM(v))
401f7917c00SJeff Kirsher v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
402f7917c00SJeff Kirsher V_RXFIFOPAUSEHWM(hwm / 8);
403f7917c00SJeff Kirsher
404f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
405f7917c00SJeff Kirsher
406f7917c00SJeff Kirsher /* Adjust the TX FIFO threshold based on the MTU */
407f7917c00SJeff Kirsher thres = (adap->params.vpd.cclk * 1000) / 15625;
408f7917c00SJeff Kirsher thres = (thres * mtu) / 1000;
409f7917c00SJeff Kirsher if (is_10G(adap))
410f7917c00SJeff Kirsher thres /= 10;
411f7917c00SJeff Kirsher thres = mtu > thres ? (mtu - thres + 7) / 8 : 0;
412f7917c00SJeff Kirsher thres = max(thres, 8U); /* need at least 8 */
413f7917c00SJeff Kirsher ipg = (adap->params.rev == T3_REV_C) ? 0 : 1;
414f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
415f7917c00SJeff Kirsher V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
416f7917c00SJeff Kirsher V_TXFIFOTHRESH(thres) | V_TXIPG(ipg));
417f7917c00SJeff Kirsher
418f7917c00SJeff Kirsher if (adap->params.rev > 0) {
419f7917c00SJeff Kirsher divisor = (adap->params.rev == T3_REV_C) ? 64 : 8;
420f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
421f7917c00SJeff Kirsher (hwm - lwm) * 4 / divisor);
422f7917c00SJeff Kirsher }
423f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
424f7917c00SJeff Kirsher MAC_RXFIFO_SIZE * 4 * 8 / 512);
425f7917c00SJeff Kirsher return 0;
426f7917c00SJeff Kirsher }
427f7917c00SJeff Kirsher
t3_mac_set_speed_duplex_fc(struct cmac * mac,int speed,int duplex,int fc)428f7917c00SJeff Kirsher int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
429f7917c00SJeff Kirsher {
430f7917c00SJeff Kirsher u32 val;
431f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
432f7917c00SJeff Kirsher unsigned int oft = mac->offset;
433f7917c00SJeff Kirsher
434f7917c00SJeff Kirsher if (duplex >= 0 && duplex != DUPLEX_FULL)
435f7917c00SJeff Kirsher return -EINVAL;
436f7917c00SJeff Kirsher if (speed >= 0) {
437f7917c00SJeff Kirsher if (speed == SPEED_10)
438f7917c00SJeff Kirsher val = V_PORTSPEED(0);
439f7917c00SJeff Kirsher else if (speed == SPEED_100)
440f7917c00SJeff Kirsher val = V_PORTSPEED(1);
441f7917c00SJeff Kirsher else if (speed == SPEED_1000)
442f7917c00SJeff Kirsher val = V_PORTSPEED(2);
443f7917c00SJeff Kirsher else if (speed == SPEED_10000)
444f7917c00SJeff Kirsher val = V_PORTSPEED(3);
445f7917c00SJeff Kirsher else
446f7917c00SJeff Kirsher return -EINVAL;
447f7917c00SJeff Kirsher
448f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
449f7917c00SJeff Kirsher V_PORTSPEED(M_PORTSPEED), val);
450f7917c00SJeff Kirsher }
451f7917c00SJeff Kirsher
452f7917c00SJeff Kirsher val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
453f7917c00SJeff Kirsher val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
454f7917c00SJeff Kirsher if (fc & PAUSE_TX) {
455f7917c00SJeff Kirsher u32 rx_max_pkt_size =
456f7917c00SJeff Kirsher G_RXMAXPKTSIZE(t3_read_reg(adap,
457f7917c00SJeff Kirsher A_XGM_RX_MAX_PKT_SIZE + oft));
458f7917c00SJeff Kirsher val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
459f7917c00SJeff Kirsher }
460f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
461f7917c00SJeff Kirsher
462f7917c00SJeff Kirsher t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
463f7917c00SJeff Kirsher (fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
464f7917c00SJeff Kirsher return 0;
465f7917c00SJeff Kirsher }
466f7917c00SJeff Kirsher
t3_mac_enable(struct cmac * mac,int which)467f7917c00SJeff Kirsher int t3_mac_enable(struct cmac *mac, int which)
468f7917c00SJeff Kirsher {
469f7917c00SJeff Kirsher int idx = macidx(mac);
470f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
471f7917c00SJeff Kirsher unsigned int oft = mac->offset;
472f7917c00SJeff Kirsher struct mac_stats *s = &mac->stats;
473f7917c00SJeff Kirsher
474f7917c00SJeff Kirsher if (which & MAC_DIRECTION_TX) {
475f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
476f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_DATA,
477f7917c00SJeff Kirsher adap->params.rev == T3_REV_C ?
478f7917c00SJeff Kirsher 0xc4ffff01 : 0xc0ede401);
479f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
480f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx,
481f7917c00SJeff Kirsher adap->params.rev == T3_REV_C ? 0 : 1 << idx);
482f7917c00SJeff Kirsher
483f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
484f7917c00SJeff Kirsher
485f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
486f7917c00SJeff Kirsher mac->tx_mcnt = s->tx_frames;
487f7917c00SJeff Kirsher mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
488f7917c00SJeff Kirsher A_TP_PIO_DATA)));
489f7917c00SJeff Kirsher mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
490f7917c00SJeff Kirsher A_XGM_TX_SPI4_SOP_EOP_CNT +
491f7917c00SJeff Kirsher oft)));
492f7917c00SJeff Kirsher mac->rx_mcnt = s->rx_frames;
493f7917c00SJeff Kirsher mac->rx_pause = s->rx_pause;
494f7917c00SJeff Kirsher mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
495f7917c00SJeff Kirsher A_XGM_RX_SPI4_SOP_EOP_CNT +
496f7917c00SJeff Kirsher oft)));
497f7917c00SJeff Kirsher mac->rx_ocnt = s->rx_fifo_ovfl;
498f7917c00SJeff Kirsher mac->txen = F_TXEN;
499f7917c00SJeff Kirsher mac->toggle_cnt = 0;
500f7917c00SJeff Kirsher }
501f7917c00SJeff Kirsher if (which & MAC_DIRECTION_RX)
502f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
503f7917c00SJeff Kirsher return 0;
504f7917c00SJeff Kirsher }
505f7917c00SJeff Kirsher
t3_mac_disable(struct cmac * mac,int which)506f7917c00SJeff Kirsher int t3_mac_disable(struct cmac *mac, int which)
507f7917c00SJeff Kirsher {
508f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
509f7917c00SJeff Kirsher
510f7917c00SJeff Kirsher if (which & MAC_DIRECTION_TX) {
511f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
512f7917c00SJeff Kirsher mac->txen = 0;
513f7917c00SJeff Kirsher }
514f7917c00SJeff Kirsher if (which & MAC_DIRECTION_RX) {
515f7917c00SJeff Kirsher int val = F_MAC_RESET_;
516f7917c00SJeff Kirsher
517f7917c00SJeff Kirsher t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
518f7917c00SJeff Kirsher F_PCS_RESET_, 0);
519f7917c00SJeff Kirsher msleep(100);
520f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
521f7917c00SJeff Kirsher if (is_10G(adap))
522f7917c00SJeff Kirsher val |= F_PCS_RESET_;
523f7917c00SJeff Kirsher else if (uses_xaui(adap))
524f7917c00SJeff Kirsher val |= F_PCS_RESET_ | F_XG2G_RESET_;
525f7917c00SJeff Kirsher else
526f7917c00SJeff Kirsher val |= F_RGMII_RESET_ | F_XG2G_RESET_;
527f7917c00SJeff Kirsher t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
528f7917c00SJeff Kirsher }
529f7917c00SJeff Kirsher return 0;
530f7917c00SJeff Kirsher }
531f7917c00SJeff Kirsher
t3b2_mac_watchdog_task(struct cmac * mac)532f7917c00SJeff Kirsher int t3b2_mac_watchdog_task(struct cmac *mac)
533f7917c00SJeff Kirsher {
534f7917c00SJeff Kirsher struct adapter *adap = mac->adapter;
535f7917c00SJeff Kirsher struct mac_stats *s = &mac->stats;
536f7917c00SJeff Kirsher unsigned int tx_tcnt, tx_xcnt;
537f7917c00SJeff Kirsher u64 tx_mcnt = s->tx_frames;
538f7917c00SJeff Kirsher int status;
539f7917c00SJeff Kirsher
540f7917c00SJeff Kirsher status = 0;
541f7917c00SJeff Kirsher tx_xcnt = 1; /* By default tx_xcnt is making progress */
542f7917c00SJeff Kirsher tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt */
543f7917c00SJeff Kirsher if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) {
544f7917c00SJeff Kirsher tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
545f7917c00SJeff Kirsher A_XGM_TX_SPI4_SOP_EOP_CNT +
546f7917c00SJeff Kirsher mac->offset)));
547f7917c00SJeff Kirsher if (tx_xcnt == 0) {
548f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_ADDR,
549f7917c00SJeff Kirsher A_TP_TX_DROP_CNT_CH0 + macidx(mac));
550f7917c00SJeff Kirsher tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
551f7917c00SJeff Kirsher A_TP_PIO_DATA)));
552f7917c00SJeff Kirsher } else {
553f7917c00SJeff Kirsher goto out;
554f7917c00SJeff Kirsher }
555f7917c00SJeff Kirsher } else {
556f7917c00SJeff Kirsher mac->toggle_cnt = 0;
557f7917c00SJeff Kirsher goto out;
558f7917c00SJeff Kirsher }
559f7917c00SJeff Kirsher
560f7917c00SJeff Kirsher if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) {
561f7917c00SJeff Kirsher if (mac->toggle_cnt > 4) {
562f7917c00SJeff Kirsher status = 2;
563f7917c00SJeff Kirsher goto out;
564f7917c00SJeff Kirsher } else {
565f7917c00SJeff Kirsher status = 1;
566f7917c00SJeff Kirsher goto out;
567f7917c00SJeff Kirsher }
568f7917c00SJeff Kirsher } else {
569f7917c00SJeff Kirsher mac->toggle_cnt = 0;
570f7917c00SJeff Kirsher goto out;
571f7917c00SJeff Kirsher }
572f7917c00SJeff Kirsher
573f7917c00SJeff Kirsher out:
574f7917c00SJeff Kirsher mac->tx_tcnt = tx_tcnt;
575f7917c00SJeff Kirsher mac->tx_xcnt = tx_xcnt;
576f7917c00SJeff Kirsher mac->tx_mcnt = s->tx_frames;
577f7917c00SJeff Kirsher mac->rx_pause = s->rx_pause;
578f7917c00SJeff Kirsher if (status == 1) {
579f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
580f7917c00SJeff Kirsher t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
581f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
582f7917c00SJeff Kirsher t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
583f7917c00SJeff Kirsher mac->toggle_cnt++;
584f7917c00SJeff Kirsher } else if (status == 2) {
585f7917c00SJeff Kirsher t3b2_mac_reset(mac);
586f7917c00SJeff Kirsher mac->toggle_cnt = 0;
587f7917c00SJeff Kirsher }
588f7917c00SJeff Kirsher return status;
589f7917c00SJeff Kirsher }
590f7917c00SJeff Kirsher
591f7917c00SJeff Kirsher /*
592f7917c00SJeff Kirsher * This function is called periodically to accumulate the current values of the
593f7917c00SJeff Kirsher * RMON counters into the port statistics. Since the packet counters are only
594f7917c00SJeff Kirsher * 32 bits they can overflow in ~286 secs at 10G, so the function should be
595f7917c00SJeff Kirsher * called more frequently than that. The byte counters are 45-bit wide, they
596f7917c00SJeff Kirsher * would overflow in ~7.8 hours.
597f7917c00SJeff Kirsher */
t3_mac_update_stats(struct cmac * mac)598f7917c00SJeff Kirsher const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
599f7917c00SJeff Kirsher {
600f7917c00SJeff Kirsher #define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset)
601f7917c00SJeff Kirsher #define RMON_UPDATE(mac, name, reg) \
602f7917c00SJeff Kirsher (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg)
603f7917c00SJeff Kirsher #define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \
604f7917c00SJeff Kirsher (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \
605f7917c00SJeff Kirsher ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32)
606f7917c00SJeff Kirsher
607f7917c00SJeff Kirsher u32 v, lo;
608f7917c00SJeff Kirsher
609f7917c00SJeff Kirsher RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH);
610f7917c00SJeff Kirsher RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH);
611f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES);
612f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES);
613f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES);
614f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES);
615f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES);
616f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES);
617f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES);
618f7917c00SJeff Kirsher
619f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES);
620f7917c00SJeff Kirsher
621f7917c00SJeff Kirsher v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
622f7917c00SJeff Kirsher if (mac->adapter->params.rev == T3_REV_B2)
623f7917c00SJeff Kirsher v &= 0x7fffffff;
624f7917c00SJeff Kirsher mac->stats.rx_too_long += v;
625f7917c00SJeff Kirsher
626f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES);
627f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES);
628f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES);
629f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES);
630f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES);
631f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES);
632f7917c00SJeff Kirsher RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES);
633f7917c00SJeff Kirsher
634f7917c00SJeff Kirsher RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH);
635f7917c00SJeff Kirsher RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH);
636f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST);
637f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST);
638f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_pause, TX_PAUSE);
639f7917c00SJeff Kirsher /* This counts error frames in general (bad FCS, underrun, etc). */
640f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES);
641f7917c00SJeff Kirsher
642f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES);
643f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES);
644f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES);
645f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES);
646f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES);
647f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES);
648f7917c00SJeff Kirsher RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES);
649f7917c00SJeff Kirsher
650f7917c00SJeff Kirsher /* The next stat isn't clear-on-read. */
651f7917c00SJeff Kirsher t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50);
652f7917c00SJeff Kirsher v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA);
653f7917c00SJeff Kirsher lo = (u32) mac->stats.rx_cong_drops;
654f7917c00SJeff Kirsher mac->stats.rx_cong_drops += (u64) (v - lo);
655f7917c00SJeff Kirsher
656f7917c00SJeff Kirsher return &mac->stats;
657f7917c00SJeff Kirsher }
658