diff options
Diffstat (limited to 'drivers/net/chelsio/pm3393.c')
-rw-r--r-- | drivers/net/chelsio/pm3393.c | 125 |
1 files changed, 50 insertions, 75 deletions
diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index 04a1404fc65e..63cabeb98afe 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c | |||
@@ -43,21 +43,7 @@ | |||
43 | #include "elmer0.h" | 43 | #include "elmer0.h" |
44 | #include "suni1x10gexp_regs.h" | 44 | #include "suni1x10gexp_regs.h" |
45 | 45 | ||
46 | /* 802.3ae 10Gb/s MDIO Manageable Device(MMD) | 46 | #include <linux/crc32.h> |
47 | */ | ||
48 | enum { | ||
49 | MMD_RESERVED, | ||
50 | MMD_PMAPMD, | ||
51 | MMD_WIS, | ||
52 | MMD_PCS, | ||
53 | MMD_PHY_XGXS, /* XGMII Extender Sublayer */ | ||
54 | MMD_DTE_XGXS, | ||
55 | }; | ||
56 | |||
57 | enum { | ||
58 | PHY_XGXS_CTRL_1, | ||
59 | PHY_XGXS_STATUS_1 | ||
60 | }; | ||
61 | 47 | ||
62 | #define OFFSET(REG_ADDR) (REG_ADDR << 2) | 48 | #define OFFSET(REG_ADDR) (REG_ADDR << 2) |
63 | 49 | ||
@@ -88,6 +74,8 @@ enum { /* RMON registers */ | |||
88 | RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW, | 74 | RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW, |
89 | RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW, | 75 | RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW, |
90 | RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW, | 76 | RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW, |
77 | RxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW, | ||
78 | RxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW, | ||
91 | 79 | ||
92 | TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW, | 80 | TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW, |
93 | TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW, | 81 | TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW, |
@@ -95,7 +83,9 @@ enum { /* RMON registers */ | |||
95 | TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW, | 83 | TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW, |
96 | TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW, | 84 | TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW, |
97 | TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW, | 85 | TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW, |
98 | TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW | 86 | TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW, |
87 | TxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW, | ||
88 | TxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW | ||
99 | }; | 89 | }; |
100 | 90 | ||
101 | struct _cmac_instance { | 91 | struct _cmac_instance { |
@@ -124,12 +114,12 @@ static int pm3393_reset(struct cmac *cmac) | |||
124 | 114 | ||
125 | /* | 115 | /* |
126 | * Enable interrupts for the PM3393 | 116 | * Enable interrupts for the PM3393 |
127 | 117 | * | |
128 | 1. Enable PM3393 BLOCK interrupts. | 118 | * 1. Enable PM3393 BLOCK interrupts. |
129 | 2. Enable PM3393 Master Interrupt bit(INTE) | 119 | * 2. Enable PM3393 Master Interrupt bit(INTE) |
130 | 3. Enable ELMER's PM3393 bit. | 120 | * 3. Enable ELMER's PM3393 bit. |
131 | 4. Enable Terminator external interrupt. | 121 | * 4. Enable Terminator external interrupt. |
132 | */ | 122 | */ |
133 | static int pm3393_interrupt_enable(struct cmac *cmac) | 123 | static int pm3393_interrupt_enable(struct cmac *cmac) |
134 | { | 124 | { |
135 | u32 pl_intr; | 125 | u32 pl_intr; |
@@ -257,14 +247,12 @@ static int pm3393_interrupt_clear(struct cmac *cmac) | |||
257 | static int pm3393_interrupt_handler(struct cmac *cmac) | 247 | static int pm3393_interrupt_handler(struct cmac *cmac) |
258 | { | 248 | { |
259 | u32 master_intr_status; | 249 | u32 master_intr_status; |
260 | /* | 250 | |
261 | 1. Read master interrupt register. | ||
262 | 2. Read BLOCK's interrupt status registers. | ||
263 | 3. Handle BLOCK interrupts. | ||
264 | */ | ||
265 | /* Read the master interrupt status register. */ | 251 | /* Read the master interrupt status register. */ |
266 | pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, | 252 | pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, |
267 | &master_intr_status); | 253 | &master_intr_status); |
254 | CH_DBG(cmac->adapter, INTR, "PM3393 intr cause 0x%x\n", | ||
255 | master_intr_status); | ||
268 | 256 | ||
269 | /* TBD XXX Lets just clear everything for now */ | 257 | /* TBD XXX Lets just clear everything for now */ |
270 | pm3393_interrupt_clear(cmac); | 258 | pm3393_interrupt_clear(cmac); |
@@ -307,11 +295,7 @@ static int pm3393_enable_port(struct cmac *cmac, int which) | |||
307 | * The PHY doesn't give us link status indication on its own so have | 295 | * The PHY doesn't give us link status indication on its own so have |
308 | * the link management code query it instead. | 296 | * the link management code query it instead. |
309 | */ | 297 | */ |
310 | { | 298 | t1_link_changed(cmac->adapter, 0); |
311 | extern void link_changed(adapter_t *adapter, int port_id); | ||
312 | |||
313 | link_changed(cmac->adapter, 0); | ||
314 | } | ||
315 | return 0; | 299 | return 0; |
316 | } | 300 | } |
317 | 301 | ||
@@ -363,33 +347,6 @@ static int pm3393_set_mtu(struct cmac *cmac, int mtu) | |||
363 | return 0; | 347 | return 0; |
364 | } | 348 | } |
365 | 349 | ||
366 | static u32 calc_crc(u8 *b, int len) | ||
367 | { | ||
368 | int i; | ||
369 | u32 crc = (u32)~0; | ||
370 | |||
371 | /* calculate crc one bit at a time */ | ||
372 | while (len--) { | ||
373 | crc ^= *b++; | ||
374 | for (i = 0; i < 8; i++) { | ||
375 | if (crc & 0x1) | ||
376 | crc = (crc >> 1) ^ 0xedb88320; | ||
377 | else | ||
378 | crc = (crc >> 1); | ||
379 | } | ||
380 | } | ||
381 | |||
382 | /* reverse bits */ | ||
383 | crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0); | ||
384 | crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc); | ||
385 | crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa); | ||
386 | /* swap bytes */ | ||
387 | crc = (crc >> 16) | (crc << 16); | ||
388 | crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00); | ||
389 | |||
390 | return crc; | ||
391 | } | ||
392 | |||
393 | static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm) | 350 | static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm) |
394 | { | 351 | { |
395 | int enabled = cmac->instance->enabled & MAC_DIRECTION_RX; | 352 | int enabled = cmac->instance->enabled & MAC_DIRECTION_RX; |
@@ -423,7 +380,7 @@ static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm) | |||
423 | u16 mc_filter[4] = { 0, }; | 380 | u16 mc_filter[4] = { 0, }; |
424 | 381 | ||
425 | while ((addr = t1_get_next_mcaddr(rm))) { | 382 | while ((addr = t1_get_next_mcaddr(rm))) { |
426 | bit = (calc_crc(addr, ETH_ALEN) >> 23) & 0x3f; /* bit[23:28] */ | 383 | bit = (ether_crc(ETH_ALEN, addr) >> 23) & 0x3f; /* bit[23:28] */ |
427 | mc_filter[bit >> 4] |= 1 << (bit & 0xf); | 384 | mc_filter[bit >> 4] |= 1 << (bit & 0xf); |
428 | } | 385 | } |
429 | pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]); | 386 | pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]); |
@@ -471,20 +428,29 @@ static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex, | |||
471 | return 0; | 428 | return 0; |
472 | } | 429 | } |
473 | 430 | ||
431 | static void pm3393_rmon_update(struct adapter *adapter, u32 offs, u64 *val, | ||
432 | int over) | ||
433 | { | ||
434 | u32 val0, val1, val2; | ||
435 | |||
436 | t1_tpi_read(adapter, offs, &val0); | ||
437 | t1_tpi_read(adapter, offs + 4, &val1); | ||
438 | t1_tpi_read(adapter, offs + 8, &val2); | ||
439 | |||
440 | *val &= ~0ull << 40; | ||
441 | *val |= val0 & 0xffff; | ||
442 | *val |= (val1 & 0xffff) << 16; | ||
443 | *val |= (u64)(val2 & 0xff) << 32; | ||
444 | |||
445 | if (over) | ||
446 | *val += 1ull << 40; | ||
447 | } | ||
448 | |||
474 | #define RMON_UPDATE(mac, name, stat_name) \ | 449 | #define RMON_UPDATE(mac, name, stat_name) \ |
475 | { \ | 450 | pm3393_rmon_update((mac)->adapter, OFFSET(name), \ |
476 | t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \ | 451 | &(mac)->stats.stat_name, \ |
477 | t1_tpi_read((mac)->adapter, OFFSET(((name)+1)), &val1); \ | 452 | (ro &((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) |
478 | t1_tpi_read((mac)->adapter, OFFSET(((name)+2)), &val2); \ | 453 | |
479 | (mac)->stats.stat_name = ((u64)val0 & 0xffff) | \ | ||
480 | (((u64)val1 & 0xffff) << 16) | \ | ||
481 | (((u64)val2 & 0xff) << 32) | \ | ||
482 | ((mac)->stats.stat_name & \ | ||
483 | (~(u64)0 << 40)); \ | ||
484 | if (ro & \ | ||
485 | ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \ | ||
486 | (mac)->stats.stat_name += ((u64)1 << 40); \ | ||
487 | } | ||
488 | 454 | ||
489 | static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, | 455 | static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, |
490 | int flag) | 456 | int flag) |
@@ -519,6 +485,8 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, | |||
519 | RMON_UPDATE(mac, RxJabbers, RxJabberErrors); | 485 | RMON_UPDATE(mac, RxJabbers, RxJabberErrors); |
520 | RMON_UPDATE(mac, RxFragments, RxRuntErrors); | 486 | RMON_UPDATE(mac, RxFragments, RxRuntErrors); |
521 | RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors); | 487 | RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors); |
488 | RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK); | ||
489 | RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK); | ||
522 | 490 | ||
523 | /* Tx stats */ | 491 | /* Tx stats */ |
524 | RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK); | 492 | RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK); |
@@ -529,6 +497,8 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, | |||
529 | RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK); | 497 | RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK); |
530 | RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK); | 498 | RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK); |
531 | RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames); | 499 | RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames); |
500 | RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK); | ||
501 | RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK); | ||
532 | 502 | ||
533 | return &mac->stats; | 503 | return &mac->stats; |
534 | } | 504 | } |
@@ -631,10 +601,9 @@ static struct cmac *pm3393_mac_create(adapter_t *adapter, int index) | |||
631 | { | 601 | { |
632 | struct cmac *cmac; | 602 | struct cmac *cmac; |
633 | 603 | ||
634 | cmac = kmalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL); | 604 | cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL); |
635 | if (!cmac) | 605 | if (!cmac) |
636 | return NULL; | 606 | return NULL; |
637 | memset(cmac, 0, sizeof(*cmac)); | ||
638 | 607 | ||
639 | cmac->ops = &pm3393_ops; | 608 | cmac->ops = &pm3393_ops; |
640 | cmac->instance = (cmac_instance *) (cmac + 1); | 609 | cmac->instance = (cmac_instance *) (cmac + 1); |
@@ -815,6 +784,12 @@ static int pm3393_mac_reset(adapter_t * adapter) | |||
815 | 784 | ||
816 | successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock | 785 | successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock |
817 | && is_xaui_mabc_pll_locked); | 786 | && is_xaui_mabc_pll_locked); |
787 | |||
788 | CH_DBG(adapter, HW, | ||
789 | "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, " | ||
790 | "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n", | ||
791 | i, is_pl4_reset_finished, val, is_pl4_outof_lock, | ||
792 | is_xaui_mabc_pll_locked); | ||
818 | } | 793 | } |
819 | return successful_reset ? 0 : 1; | 794 | return successful_reset ? 0 : 1; |
820 | } | 795 | } |