diff options
author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-02-10 14:45:43 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-02-10 14:45:43 -0500 |
commit | 81b7bbd1932a04869d4c8635a75222dfc6089f96 (patch) | |
tree | 285ae868a1e3a41fb0dbfe346c28e380949bcb55 /drivers/net/cxgb3/xgmac.c | |
parent | 98051995ab44b993f992946055edc6115351f725 (diff) | |
parent | 66efc5a7e3061c3597ac43a8bb1026488d57e66b (diff) |
Merge branch 'linus'
Conflicts:
drivers/scsi/ipr.c
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/net/cxgb3/xgmac.c')
-rw-r--r-- | drivers/net/cxgb3/xgmac.c | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c new file mode 100644 index 000000000000..907a272ae32d --- /dev/null +++ b/drivers/net/cxgb3/xgmac.c | |||
@@ -0,0 +1,409 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the | ||
8 | * OpenIB.org BSD license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or | ||
11 | * without modification, are permitted provided that the following | ||
12 | * conditions are met: | ||
13 | * | ||
14 | * - Redistributions of source code must retain the above | ||
15 | * copyright notice, this list of conditions and the following | ||
16 | * disclaimer. | ||
17 | * | ||
18 | * - Redistributions in binary form must reproduce the above | ||
19 | * copyright notice, this list of conditions and the following | ||
20 | * disclaimer in the documentation and/or other materials | ||
21 | * provided with the distribution. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
30 | * SOFTWARE. | ||
31 | */ | ||
32 | #include "common.h" | ||
33 | #include "regs.h" | ||
34 | |||
35 | /* | ||
36 | * # of exact address filters. The first one is used for the station address, | ||
37 | * the rest are available for multicast addresses. | ||
38 | */ | ||
39 | #define EXACT_ADDR_FILTERS 8 | ||
40 | |||
41 | static inline int macidx(const struct cmac *mac) | ||
42 | { | ||
43 | return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR); | ||
44 | } | ||
45 | |||
46 | static void xaui_serdes_reset(struct cmac *mac) | ||
47 | { | ||
48 | static const unsigned int clear[] = { | ||
49 | F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1, | ||
50 | F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3 | ||
51 | }; | ||
52 | |||
53 | int i; | ||
54 | struct adapter *adap = mac->adapter; | ||
55 | u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset; | ||
56 | |||
57 | t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] | | ||
58 | F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 | | ||
59 | F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 | | ||
60 | F_RESETPLL23 | F_RESETPLL01); | ||
61 | t3_read_reg(adap, ctrl); | ||
62 | udelay(15); | ||
63 | |||
64 | for (i = 0; i < ARRAY_SIZE(clear); i++) { | ||
65 | t3_set_reg_field(adap, ctrl, clear[i], 0); | ||
66 | udelay(15); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | void t3b_pcs_reset(struct cmac *mac) | ||
71 | { | ||
72 | t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, | ||
73 | F_PCS_RESET_, 0); | ||
74 | udelay(20); | ||
75 | t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0, | ||
76 | F_PCS_RESET_); | ||
77 | } | ||
78 | |||
79 | int t3_mac_reset(struct cmac *mac) | ||
80 | { | ||
81 | static const struct addr_val_pair mac_reset_avp[] = { | ||
82 | {A_XGM_TX_CTRL, 0}, | ||
83 | {A_XGM_RX_CTRL, 0}, | ||
84 | {A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES | | ||
85 | F_RMFCS | F_ENJUMBO | F_ENHASHMCAST}, | ||
86 | {A_XGM_RX_HASH_LOW, 0}, | ||
87 | {A_XGM_RX_HASH_HIGH, 0}, | ||
88 | {A_XGM_RX_EXACT_MATCH_LOW_1, 0}, | ||
89 | {A_XGM_RX_EXACT_MATCH_LOW_2, 0}, | ||
90 | {A_XGM_RX_EXACT_MATCH_LOW_3, 0}, | ||
91 | {A_XGM_RX_EXACT_MATCH_LOW_4, 0}, | ||
92 | {A_XGM_RX_EXACT_MATCH_LOW_5, 0}, | ||
93 | {A_XGM_RX_EXACT_MATCH_LOW_6, 0}, | ||
94 | {A_XGM_RX_EXACT_MATCH_LOW_7, 0}, | ||
95 | {A_XGM_RX_EXACT_MATCH_LOW_8, 0}, | ||
96 | {A_XGM_STAT_CTRL, F_CLRSTATS} | ||
97 | }; | ||
98 | u32 val; | ||
99 | struct adapter *adap = mac->adapter; | ||
100 | unsigned int oft = mac->offset; | ||
101 | |||
102 | t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); | ||
103 | t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ | ||
104 | |||
105 | t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft); | ||
106 | t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft, | ||
107 | F_RXSTRFRWRD | F_DISERRFRAMES, | ||
108 | uses_xaui(adap) ? 0 : F_RXSTRFRWRD); | ||
109 | |||
110 | if (uses_xaui(adap)) { | ||
111 | if (adap->params.rev == 0) { | ||
112 | t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, | ||
113 | F_RXENABLE | F_TXENABLE); | ||
114 | if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft, | ||
115 | F_CMULOCK, 1, 5, 2)) { | ||
116 | CH_ERR(adap, | ||
117 | "MAC %d XAUI SERDES CMU lock failed\n", | ||
118 | macidx(mac)); | ||
119 | return -1; | ||
120 | } | ||
121 | t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, | ||
122 | F_SERDESRESET_); | ||
123 | } else | ||
124 | xaui_serdes_reset(mac); | ||
125 | } | ||
126 | |||
127 | if (adap->params.rev > 0) | ||
128 | t3_write_reg(adap, A_XGM_PAUSE_TIMER + oft, 0xf000); | ||
129 | |||
130 | val = F_MAC_RESET_; | ||
131 | if (is_10G(adap)) | ||
132 | val |= F_PCS_RESET_; | ||
133 | else if (uses_xaui(adap)) | ||
134 | val |= F_PCS_RESET_ | F_XG2G_RESET_; | ||
135 | else | ||
136 | val |= F_RGMII_RESET_ | F_XG2G_RESET_; | ||
137 | t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); | ||
138 | t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ | ||
139 | if ((val & F_PCS_RESET_) && adap->params.rev) { | ||
140 | msleep(1); | ||
141 | t3b_pcs_reset(mac); | ||
142 | } | ||
143 | |||
144 | memset(&mac->stats, 0, sizeof(mac->stats)); | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Set the exact match register 'idx' to recognize the given Ethernet address. | ||
150 | */ | ||
151 | static void set_addr_filter(struct cmac *mac, int idx, const u8 * addr) | ||
152 | { | ||
153 | u32 addr_lo, addr_hi; | ||
154 | unsigned int oft = mac->offset + idx * 8; | ||
155 | |||
156 | addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; | ||
157 | addr_hi = (addr[5] << 8) | addr[4]; | ||
158 | |||
159 | t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo); | ||
160 | t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi); | ||
161 | } | ||
162 | |||
163 | /* Set one of the station's unicast MAC addresses. */ | ||
164 | int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]) | ||
165 | { | ||
166 | if (idx >= mac->nucast) | ||
167 | return -EINVAL; | ||
168 | set_addr_filter(mac, idx, addr); | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Specify the number of exact address filters that should be reserved for | ||
174 | * unicast addresses. Caller should reload the unicast and multicast addresses | ||
175 | * after calling this. | ||
176 | */ | ||
177 | int t3_mac_set_num_ucast(struct cmac *mac, int n) | ||
178 | { | ||
179 | if (n > EXACT_ADDR_FILTERS) | ||
180 | return -EINVAL; | ||
181 | mac->nucast = n; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | /* Calculate the RX hash filter index of an Ethernet address */ | ||
186 | static int hash_hw_addr(const u8 * addr) | ||
187 | { | ||
188 | int hash = 0, octet, bit, i = 0, c; | ||
189 | |||
190 | for (octet = 0; octet < 6; ++octet) | ||
191 | for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) { | ||
192 | hash ^= (c & 1) << i; | ||
193 | if (++i == 6) | ||
194 | i = 0; | ||
195 | } | ||
196 | return hash; | ||
197 | } | ||
198 | |||
199 | int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm) | ||
200 | { | ||
201 | u32 val, hash_lo, hash_hi; | ||
202 | struct adapter *adap = mac->adapter; | ||
203 | unsigned int oft = mac->offset; | ||
204 | |||
205 | val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES; | ||
206 | if (rm->dev->flags & IFF_PROMISC) | ||
207 | val |= F_COPYALLFRAMES; | ||
208 | t3_write_reg(adap, A_XGM_RX_CFG + oft, val); | ||
209 | |||
210 | if (rm->dev->flags & IFF_ALLMULTI) | ||
211 | hash_lo = hash_hi = 0xffffffff; | ||
212 | else { | ||
213 | u8 *addr; | ||
214 | int exact_addr_idx = mac->nucast; | ||
215 | |||
216 | hash_lo = hash_hi = 0; | ||
217 | while ((addr = t3_get_next_mcaddr(rm))) | ||
218 | if (exact_addr_idx < EXACT_ADDR_FILTERS) | ||
219 | set_addr_filter(mac, exact_addr_idx++, addr); | ||
220 | else { | ||
221 | int hash = hash_hw_addr(addr); | ||
222 | |||
223 | if (hash < 32) | ||
224 | hash_lo |= (1 << hash); | ||
225 | else | ||
226 | hash_hi |= (1 << (hash - 32)); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo); | ||
231 | t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi); | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) | ||
236 | { | ||
237 | int hwm, lwm; | ||
238 | unsigned int thres, v; | ||
239 | struct adapter *adap = mac->adapter; | ||
240 | |||
241 | /* | ||
242 | * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max | ||
243 | * packet size register includes header, but not FCS. | ||
244 | */ | ||
245 | mtu += 14; | ||
246 | if (mtu > MAX_FRAME_SIZE - 4) | ||
247 | return -EINVAL; | ||
248 | t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); | ||
249 | |||
250 | /* | ||
251 | * Adjust the PAUSE frame watermarks. We always set the LWM, and the | ||
252 | * HWM only if flow-control is enabled. | ||
253 | */ | ||
254 | hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, MAC_RXFIFO_SIZE / 2U); | ||
255 | hwm = min(hwm, 3 * MAC_RXFIFO_SIZE / 4 + 1024); | ||
256 | lwm = hwm - 1024; | ||
257 | v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset); | ||
258 | v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM); | ||
259 | v |= V_RXFIFOPAUSELWM(lwm / 8); | ||
260 | if (G_RXFIFOPAUSEHWM(v)) | ||
261 | v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) | | ||
262 | V_RXFIFOPAUSEHWM(hwm / 8); | ||
263 | t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v); | ||
264 | |||
265 | /* Adjust the TX FIFO threshold based on the MTU */ | ||
266 | thres = (adap->params.vpd.cclk * 1000) / 15625; | ||
267 | thres = (thres * mtu) / 1000; | ||
268 | if (is_10G(adap)) | ||
269 | thres /= 10; | ||
270 | thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; | ||
271 | thres = max(thres, 8U); /* need at least 8 */ | ||
272 | t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, | ||
273 | V_TXFIFOTHRESH(M_TXFIFOTHRESH), V_TXFIFOTHRESH(thres)); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) | ||
278 | { | ||
279 | u32 val; | ||
280 | struct adapter *adap = mac->adapter; | ||
281 | unsigned int oft = mac->offset; | ||
282 | |||
283 | if (duplex >= 0 && duplex != DUPLEX_FULL) | ||
284 | return -EINVAL; | ||
285 | if (speed >= 0) { | ||
286 | if (speed == SPEED_10) | ||
287 | val = V_PORTSPEED(0); | ||
288 | else if (speed == SPEED_100) | ||
289 | val = V_PORTSPEED(1); | ||
290 | else if (speed == SPEED_1000) | ||
291 | val = V_PORTSPEED(2); | ||
292 | else if (speed == SPEED_10000) | ||
293 | val = V_PORTSPEED(3); | ||
294 | else | ||
295 | return -EINVAL; | ||
296 | |||
297 | t3_set_reg_field(adap, A_XGM_PORT_CFG + oft, | ||
298 | V_PORTSPEED(M_PORTSPEED), val); | ||
299 | } | ||
300 | |||
301 | val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); | ||
302 | val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); | ||
303 | if (fc & PAUSE_TX) | ||
304 | val |= V_RXFIFOPAUSEHWM(G_RXFIFOPAUSELWM(val) + 128); /* +1KB */ | ||
305 | t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); | ||
306 | |||
307 | t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, | ||
308 | (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | int t3_mac_enable(struct cmac *mac, int which) | ||
313 | { | ||
314 | int idx = macidx(mac); | ||
315 | struct adapter *adap = mac->adapter; | ||
316 | unsigned int oft = mac->offset; | ||
317 | |||
318 | if (which & MAC_DIRECTION_TX) { | ||
319 | t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); | ||
320 | t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); | ||
321 | t3_write_reg(adap, A_TP_PIO_DATA, 0xbf000001); | ||
322 | t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); | ||
323 | t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); | ||
324 | } | ||
325 | if (which & MAC_DIRECTION_RX) | ||
326 | t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | int t3_mac_disable(struct cmac *mac, int which) | ||
331 | { | ||
332 | int idx = macidx(mac); | ||
333 | struct adapter *adap = mac->adapter; | ||
334 | |||
335 | if (which & MAC_DIRECTION_TX) { | ||
336 | t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); | ||
337 | t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); | ||
338 | t3_write_reg(adap, A_TP_PIO_DATA, 0xc000001f); | ||
339 | t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); | ||
340 | t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 0); | ||
341 | } | ||
342 | if (which & MAC_DIRECTION_RX) | ||
343 | t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * This function is called periodically to accumulate the current values of the | ||
349 | * RMON counters into the port statistics. Since the packet counters are only | ||
350 | * 32 bits they can overflow in ~286 secs at 10G, so the function should be | ||
351 | * called more frequently than that. The byte counters are 45-bit wide, they | ||
352 | * would overflow in ~7.8 hours. | ||
353 | */ | ||
354 | const struct mac_stats *t3_mac_update_stats(struct cmac *mac) | ||
355 | { | ||
356 | #define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset) | ||
357 | #define RMON_UPDATE(mac, name, reg) \ | ||
358 | (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg) | ||
359 | #define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \ | ||
360 | (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \ | ||
361 | ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32) | ||
362 | |||
363 | u32 v, lo; | ||
364 | |||
365 | RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH); | ||
366 | RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH); | ||
367 | RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES); | ||
368 | RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES); | ||
369 | RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES); | ||
370 | RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES); | ||
371 | RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES); | ||
372 | RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES); | ||
373 | RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES); | ||
374 | |||
375 | RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES); | ||
376 | mac->stats.rx_too_long += RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); | ||
377 | |||
378 | RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES); | ||
379 | RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES); | ||
380 | RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES); | ||
381 | RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES); | ||
382 | RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES); | ||
383 | RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES); | ||
384 | RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES); | ||
385 | |||
386 | RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH); | ||
387 | RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH); | ||
388 | RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST); | ||
389 | RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST); | ||
390 | RMON_UPDATE(mac, tx_pause, TX_PAUSE); | ||
391 | /* This counts error frames in general (bad FCS, underrun, etc). */ | ||
392 | RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES); | ||
393 | |||
394 | RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES); | ||
395 | RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES); | ||
396 | RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES); | ||
397 | RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES); | ||
398 | RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES); | ||
399 | RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES); | ||
400 | RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES); | ||
401 | |||
402 | /* The next stat isn't clear-on-read. */ | ||
403 | t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50); | ||
404 | v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA); | ||
405 | lo = (u32) mac->stats.rx_cong_drops; | ||
406 | mac->stats.rx_cong_drops += (u64) (v - lo); | ||
407 | |||
408 | return &mac->stats; | ||
409 | } | ||