2 * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
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:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
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.
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
36 * # of exact address filters. The first one is used for the station address,
37 * the rest are available for multicast addresses.
39 #define EXACT_ADDR_FILTERS 8
41 static inline int macidx(const struct cmac
*mac
)
43 return mac
->offset
/ (XGMAC0_1_BASE_ADDR
- XGMAC0_0_BASE_ADDR
);
46 static void xaui_serdes_reset(struct cmac
*mac
)
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
54 struct adapter
*adap
= mac
->adapter
;
55 u32 ctrl
= A_XGM_SERDES_CTRL0
+ mac
->offset
;
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
);
64 for (i
= 0; i
< ARRAY_SIZE(clear
); i
++) {
65 t3_set_reg_field(adap
, ctrl
, clear
[i
], 0);
70 void t3b_pcs_reset(struct cmac
*mac
)
72 t3_set_reg_field(mac
->adapter
, A_XGM_RESET_CTRL
+ mac
->offset
,
75 t3_set_reg_field(mac
->adapter
, A_XGM_RESET_CTRL
+ mac
->offset
, 0,
79 int t3_mac_reset(struct cmac
*mac
)
81 static const struct addr_val_pair mac_reset_avp
[] = {
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
}
99 struct adapter
*adap
= mac
->adapter
;
100 unsigned int oft
= mac
->offset
;
102 t3_write_reg(adap
, A_XGM_RESET_CTRL
+ oft
, F_MAC_RESET_
);
103 t3_read_reg(adap
, A_XGM_RESET_CTRL
+ oft
); /* flush */
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
);
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)) {
117 "MAC %d XAUI SERDES CMU lock failed\n",
121 t3_set_reg_field(adap
, A_XGM_SERDES_CTRL
+ oft
, 0,
124 xaui_serdes_reset(mac
);
130 else if (uses_xaui(adap
))
131 val
|= F_PCS_RESET_
| F_XG2G_RESET_
;
133 val
|= F_RGMII_RESET_
| F_XG2G_RESET_
;
134 t3_write_reg(adap
, A_XGM_RESET_CTRL
+ oft
, val
);
135 t3_read_reg(adap
, A_XGM_RESET_CTRL
+ oft
); /* flush */
136 if ((val
& F_PCS_RESET_
) && adap
->params
.rev
) {
141 memset(&mac
->stats
, 0, sizeof(mac
->stats
));
145 int t3b2_mac_reset(struct cmac
*mac
)
147 struct adapter
*adap
= mac
->adapter
;
148 unsigned int oft
= mac
->offset
;
152 t3_set_reg_field(adap
, A_MPS_CFG
, F_PORT0ACTIVE
, 0);
154 t3_set_reg_field(adap
, A_MPS_CFG
, F_PORT1ACTIVE
, 0);
156 t3_write_reg(adap
, A_XGM_RESET_CTRL
+ oft
, F_MAC_RESET_
);
157 t3_read_reg(adap
, A_XGM_RESET_CTRL
+ oft
); /* flush */
161 /* Check for xgm Rx fifo empty */
162 if (t3_wait_op_done(adap
, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT
+ oft
,
163 0x80000000, 1, 5, 2)) {
164 CH_ERR(adap
, "MAC %d Rx fifo drain failed\n",
169 t3_write_reg(adap
, A_XGM_RESET_CTRL
+ oft
, 0);
170 t3_read_reg(adap
, A_XGM_RESET_CTRL
+ oft
); /* flush */
175 else if (uses_xaui(adap
))
176 val
|= F_PCS_RESET_
| F_XG2G_RESET_
;
178 val
|= F_RGMII_RESET_
| F_XG2G_RESET_
;
179 t3_write_reg(adap
, A_XGM_RESET_CTRL
+ oft
, val
);
180 t3_read_reg(adap
, A_XGM_RESET_CTRL
+ oft
); /* flush */
181 if ((val
& F_PCS_RESET_
) && adap
->params
.rev
) {
185 t3_write_reg(adap
, A_XGM_RX_CFG
+ oft
,
186 F_DISPAUSEFRAMES
| F_EN1536BFRAMES
|
187 F_RMFCS
| F_ENJUMBO
| F_ENHASHMCAST
);
190 t3_set_reg_field(adap
, A_MPS_CFG
, 0, F_PORT0ACTIVE
);
192 t3_set_reg_field(adap
, A_MPS_CFG
, 0, F_PORT1ACTIVE
);
198 * Set the exact match register 'idx' to recognize the given Ethernet address.
200 static void set_addr_filter(struct cmac
*mac
, int idx
, const u8
* addr
)
202 u32 addr_lo
, addr_hi
;
203 unsigned int oft
= mac
->offset
+ idx
* 8;
205 addr_lo
= (addr
[3] << 24) | (addr
[2] << 16) | (addr
[1] << 8) | addr
[0];
206 addr_hi
= (addr
[5] << 8) | addr
[4];
208 t3_write_reg(mac
->adapter
, A_XGM_RX_EXACT_MATCH_LOW_1
+ oft
, addr_lo
);
209 t3_write_reg(mac
->adapter
, A_XGM_RX_EXACT_MATCH_HIGH_1
+ oft
, addr_hi
);
212 /* Set one of the station's unicast MAC addresses. */
213 int t3_mac_set_address(struct cmac
*mac
, unsigned int idx
, u8 addr
[6])
215 if (idx
>= mac
->nucast
)
217 set_addr_filter(mac
, idx
, addr
);
222 * Specify the number of exact address filters that should be reserved for
223 * unicast addresses. Caller should reload the unicast and multicast addresses
224 * after calling this.
226 int t3_mac_set_num_ucast(struct cmac
*mac
, int n
)
228 if (n
> EXACT_ADDR_FILTERS
)
234 /* Calculate the RX hash filter index of an Ethernet address */
235 static int hash_hw_addr(const u8
* addr
)
237 int hash
= 0, octet
, bit
, i
= 0, c
;
239 for (octet
= 0; octet
< 6; ++octet
)
240 for (c
= addr
[octet
], bit
= 0; bit
< 8; c
>>= 1, ++bit
) {
241 hash
^= (c
& 1) << i
;
248 int t3_mac_set_rx_mode(struct cmac
*mac
, struct t3_rx_mode
*rm
)
250 u32 val
, hash_lo
, hash_hi
;
251 struct adapter
*adap
= mac
->adapter
;
252 unsigned int oft
= mac
->offset
;
254 val
= t3_read_reg(adap
, A_XGM_RX_CFG
+ oft
) & ~F_COPYALLFRAMES
;
255 if (rm
->dev
->flags
& IFF_PROMISC
)
256 val
|= F_COPYALLFRAMES
;
257 t3_write_reg(adap
, A_XGM_RX_CFG
+ oft
, val
);
259 if (rm
->dev
->flags
& IFF_ALLMULTI
)
260 hash_lo
= hash_hi
= 0xffffffff;
263 int exact_addr_idx
= mac
->nucast
;
265 hash_lo
= hash_hi
= 0;
266 while ((addr
= t3_get_next_mcaddr(rm
)))
267 if (exact_addr_idx
< EXACT_ADDR_FILTERS
)
268 set_addr_filter(mac
, exact_addr_idx
++, addr
);
270 int hash
= hash_hw_addr(addr
);
273 hash_lo
|= (1 << hash
);
275 hash_hi
|= (1 << (hash
- 32));
279 t3_write_reg(adap
, A_XGM_RX_HASH_LOW
+ oft
, hash_lo
);
280 t3_write_reg(adap
, A_XGM_RX_HASH_HIGH
+ oft
, hash_hi
);
284 int t3_mac_set_mtu(struct cmac
*mac
, unsigned int mtu
)
287 unsigned int thres
, v
;
288 struct adapter
*adap
= mac
->adapter
;
291 * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max
292 * packet size register includes header, but not FCS.
295 if (mtu
> MAX_FRAME_SIZE
- 4)
297 t3_write_reg(adap
, A_XGM_RX_MAX_PKT_SIZE
+ mac
->offset
, mtu
);
300 * Adjust the PAUSE frame watermarks. We always set the LWM, and the
301 * HWM only if flow-control is enabled.
303 hwm
= max_t(unsigned int, MAC_RXFIFO_SIZE
- 3 * mtu
,
304 MAC_RXFIFO_SIZE
* 38 / 100);
305 hwm
= min(hwm
, MAC_RXFIFO_SIZE
- 8192);
306 lwm
= min(3 * (int)mtu
, MAC_RXFIFO_SIZE
/ 4);
308 v
= t3_read_reg(adap
, A_XGM_RXFIFO_CFG
+ mac
->offset
);
309 v
&= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM
);
310 v
|= V_RXFIFOPAUSELWM(lwm
/ 8);
311 if (G_RXFIFOPAUSEHWM(v
))
312 v
= (v
& ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM
)) |
313 V_RXFIFOPAUSEHWM(hwm
/ 8);
314 t3_write_reg(adap
, A_XGM_RXFIFO_CFG
+ mac
->offset
, v
);
316 /* Adjust the TX FIFO threshold based on the MTU */
317 thres
= (adap
->params
.vpd
.cclk
* 1000) / 15625;
318 thres
= (thres
* mtu
) / 1000;
321 thres
= mtu
> thres
? (mtu
- thres
+ 7) / 8 : 0;
322 thres
= max(thres
, 8U); /* need at least 8 */
323 t3_set_reg_field(adap
, A_XGM_TXFIFO_CFG
+ mac
->offset
,
324 V_TXFIFOTHRESH(M_TXFIFOTHRESH
) | V_TXIPG(M_TXIPG
),
325 V_TXFIFOTHRESH(thres
) | V_TXIPG(1));
327 if (adap
->params
.rev
> 0)
328 t3_write_reg(adap
, A_XGM_PAUSE_TIMER
+ mac
->offset
,
329 (hwm
- lwm
) * 4 / 8);
330 t3_write_reg(adap
, A_XGM_TX_PAUSE_QUANTA
+ mac
->offset
,
331 MAC_RXFIFO_SIZE
* 4 * 8 / 512);
336 int t3_mac_set_speed_duplex_fc(struct cmac
*mac
, int speed
, int duplex
, int fc
)
339 struct adapter
*adap
= mac
->adapter
;
340 unsigned int oft
= mac
->offset
;
342 if (duplex
>= 0 && duplex
!= DUPLEX_FULL
)
345 if (speed
== SPEED_10
)
346 val
= V_PORTSPEED(0);
347 else if (speed
== SPEED_100
)
348 val
= V_PORTSPEED(1);
349 else if (speed
== SPEED_1000
)
350 val
= V_PORTSPEED(2);
351 else if (speed
== SPEED_10000
)
352 val
= V_PORTSPEED(3);
356 t3_set_reg_field(adap
, A_XGM_PORT_CFG
+ oft
,
357 V_PORTSPEED(M_PORTSPEED
), val
);
360 t3_set_reg_field(adap
, A_XGM_TX_CFG
+ oft
, F_TXPAUSEEN
,
361 (fc
& PAUSE_RX
) ? F_TXPAUSEEN
: 0);
365 int t3_mac_enable(struct cmac
*mac
, int which
)
367 int idx
= macidx(mac
);
368 struct adapter
*adap
= mac
->adapter
;
369 unsigned int oft
= mac
->offset
;
371 if (which
& MAC_DIRECTION_TX
) {
372 t3_write_reg(adap
, A_XGM_TX_CTRL
+ oft
, F_TXEN
);
373 t3_write_reg(adap
, A_TP_PIO_ADDR
, A_TP_TX_DROP_CFG_CH0
+ idx
);
374 t3_write_reg(adap
, A_TP_PIO_DATA
, 0xc0ede401);
375 t3_write_reg(adap
, A_TP_PIO_ADDR
, A_TP_TX_DROP_MODE
);
376 t3_set_reg_field(adap
, A_TP_PIO_DATA
, 1 << idx
, 1 << idx
);
378 t3_write_reg(adap
, A_TP_PIO_ADDR
, A_TP_TX_DROP_CNT_CH0
+ idx
);
379 mac
->tcnt
= (G_TXDROPCNTCH0RCVD(t3_read_reg(adap
,
381 mac
->xcnt
= (G_TXSPI4SOPCNT(t3_read_reg(adap
,
382 A_XGM_TX_SPI4_SOP_EOP_CNT
)));
386 if (which
& MAC_DIRECTION_RX
)
387 t3_write_reg(adap
, A_XGM_RX_CTRL
+ oft
, F_RXEN
);
391 int t3_mac_disable(struct cmac
*mac
, int which
)
393 int idx
= macidx(mac
);
394 struct adapter
*adap
= mac
->adapter
;
396 if (which
& MAC_DIRECTION_TX
) {
397 t3_write_reg(adap
, A_XGM_TX_CTRL
+ mac
->offset
, 0);
398 t3_write_reg(adap
, A_TP_PIO_ADDR
, A_TP_TX_DROP_CFG_CH0
+ idx
);
399 t3_write_reg(adap
, A_TP_PIO_DATA
, 0xc000001f);
400 t3_write_reg(adap
, A_TP_PIO_ADDR
, A_TP_TX_DROP_MODE
);
401 t3_set_reg_field(adap
, A_TP_PIO_DATA
, 1 << idx
, 1 << idx
);
404 if (which
& MAC_DIRECTION_RX
)
405 t3_write_reg(adap
, A_XGM_RX_CTRL
+ mac
->offset
, 0);
409 int t3b2_mac_watchdog_task(struct cmac
*mac
)
411 struct adapter
*adap
= mac
->adapter
;
412 unsigned int tcnt
, xcnt
;
415 t3_write_reg(adap
, A_TP_PIO_ADDR
, A_TP_TX_DROP_CNT_CH0
+ macidx(mac
));
416 tcnt
= (G_TXDROPCNTCH0RCVD(t3_read_reg(adap
, A_TP_PIO_DATA
)));
417 xcnt
= (G_TXSPI4SOPCNT(t3_read_reg(adap
,
418 A_XGM_TX_SPI4_SOP_EOP_CNT
+
421 if (tcnt
!= mac
->tcnt
&& xcnt
== 0 && mac
->xcnt
== 0) {
422 if (mac
->toggle_cnt
> 4) {
427 t3_write_reg(adap
, A_XGM_TX_CTRL
+ mac
->offset
, 0);
428 t3_read_reg(adap
, A_XGM_TX_CTRL
+ mac
->offset
);
429 t3_write_reg(adap
, A_XGM_TX_CTRL
+ mac
->offset
,
431 t3_read_reg(adap
, A_XGM_TX_CTRL
+ mac
->offset
);
446 * This function is called periodically to accumulate the current values of the
447 * RMON counters into the port statistics. Since the packet counters are only
448 * 32 bits they can overflow in ~286 secs at 10G, so the function should be
449 * called more frequently than that. The byte counters are 45-bit wide, they
450 * would overflow in ~7.8 hours.
452 const struct mac_stats
*t3_mac_update_stats(struct cmac
*mac
)
454 #define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset)
455 #define RMON_UPDATE(mac, name, reg) \
456 (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg)
457 #define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \
458 (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \
459 ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32)
463 RMON_UPDATE64(mac
, rx_octets
, RX_BYTES_LOW
, RX_BYTES_HIGH
);
464 RMON_UPDATE64(mac
, rx_frames
, RX_FRAMES_LOW
, RX_FRAMES_HIGH
);
465 RMON_UPDATE(mac
, rx_mcast_frames
, RX_MCAST_FRAMES
);
466 RMON_UPDATE(mac
, rx_bcast_frames
, RX_BCAST_FRAMES
);
467 RMON_UPDATE(mac
, rx_fcs_errs
, RX_CRC_ERR_FRAMES
);
468 RMON_UPDATE(mac
, rx_pause
, RX_PAUSE_FRAMES
);
469 RMON_UPDATE(mac
, rx_jabber
, RX_JABBER_FRAMES
);
470 RMON_UPDATE(mac
, rx_short
, RX_SHORT_FRAMES
);
471 RMON_UPDATE(mac
, rx_symbol_errs
, RX_SYM_CODE_ERR_FRAMES
);
473 RMON_UPDATE(mac
, rx_too_long
, RX_OVERSIZE_FRAMES
);
475 v
= RMON_READ(mac
, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT
);
476 if (mac
->adapter
->params
.rev
== T3_REV_B2
)
478 mac
->stats
.rx_too_long
+= v
;
480 RMON_UPDATE(mac
, rx_frames_64
, RX_64B_FRAMES
);
481 RMON_UPDATE(mac
, rx_frames_65_127
, RX_65_127B_FRAMES
);
482 RMON_UPDATE(mac
, rx_frames_128_255
, RX_128_255B_FRAMES
);
483 RMON_UPDATE(mac
, rx_frames_256_511
, RX_256_511B_FRAMES
);
484 RMON_UPDATE(mac
, rx_frames_512_1023
, RX_512_1023B_FRAMES
);
485 RMON_UPDATE(mac
, rx_frames_1024_1518
, RX_1024_1518B_FRAMES
);
486 RMON_UPDATE(mac
, rx_frames_1519_max
, RX_1519_MAXB_FRAMES
);
488 RMON_UPDATE64(mac
, tx_octets
, TX_BYTE_LOW
, TX_BYTE_HIGH
);
489 RMON_UPDATE64(mac
, tx_frames
, TX_FRAME_LOW
, TX_FRAME_HIGH
);
490 RMON_UPDATE(mac
, tx_mcast_frames
, TX_MCAST
);
491 RMON_UPDATE(mac
, tx_bcast_frames
, TX_BCAST
);
492 RMON_UPDATE(mac
, tx_pause
, TX_PAUSE
);
493 /* This counts error frames in general (bad FCS, underrun, etc). */
494 RMON_UPDATE(mac
, tx_underrun
, TX_ERR_FRAMES
);
496 RMON_UPDATE(mac
, tx_frames_64
, TX_64B_FRAMES
);
497 RMON_UPDATE(mac
, tx_frames_65_127
, TX_65_127B_FRAMES
);
498 RMON_UPDATE(mac
, tx_frames_128_255
, TX_128_255B_FRAMES
);
499 RMON_UPDATE(mac
, tx_frames_256_511
, TX_256_511B_FRAMES
);
500 RMON_UPDATE(mac
, tx_frames_512_1023
, TX_512_1023B_FRAMES
);
501 RMON_UPDATE(mac
, tx_frames_1024_1518
, TX_1024_1518B_FRAMES
);
502 RMON_UPDATE(mac
, tx_frames_1519_max
, TX_1519_MAXB_FRAMES
);
504 /* The next stat isn't clear-on-read. */
505 t3_write_reg(mac
->adapter
, A_TP_MIB_INDEX
, mac
->offset
? 51 : 50);
506 v
= t3_read_reg(mac
->adapter
, A_TP_MIB_RDATA
);
507 lo
= (u32
) mac
->stats
.rx_cong_drops
;
508 mac
->stats
.rx_cong_drops
+= (u64
) (v
- lo
);