aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ibm_newemac/core.c
diff options
context:
space:
mode:
authorGrant Erickson <gerickson@nuovations.com>2008-07-07 18:03:11 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-07-09 02:30:46 -0400
commit05781ccd74c63c6c8567f99101587d5c07c163e0 (patch)
treebd1e666433674363e5d0819c08afae87e7105995 /drivers/net/ibm_newemac/core.c
parent801eb73f45371accc78ca9d6d22d647eeb722c11 (diff)
ibm_newemac: Parameterize EMAC Multicast Match Handling
Various instances of the EMAC core have varying: 1) number of address match slots, 2) width of the registers for handling address match slots, 3) number of registers for handling address match slots and 4) base offset for those registers. As the driver stands today, it assumes that all EMACs have 4 IAHT and GAHT 32-bit registers, starting at offset 0x30 from the register base, with only 16-bits of each used for a total of 64 match slots. The 405EX(r) and 460EX now use the EMAC4SYNC core rather than the EMAC4 core. This core has 8 IAHT and GAHT registers, starting at offset 0x80 from the register base, with ALL 32-bits of each used for a total of 256 match slots. This adds a new compatible device tree entry "emac4sync" and a new, related feature flag "EMAC_FTR_EMAC4SYNC" along with a series of macros and inlines which supply the appropriate parameterized value based on the presence or absence of the EMAC4SYNC feature. The code has further been reworked where appropriate to use those macros and inlines. In addition, the register size passed to ioremap is now taken from the device tree: c4 for EMAC4SYNC cores 74 for EMAC4 cores 70 for EMAC cores rather than sizeof (emac_regs). Finally, the device trees have been updated with the appropriate compatible entries and resource sizes. This has been tested on an AMCC Haleakala board such that: 1) inbound ICMP requests to 'haleakala.local' via MDNS from both Mac OS X 10.4.11 and Ubuntu 8.04 systems as well as 2) outbound ICMP requests from 'haleakala.local' to those same systems in the '.local' domain via MDNS now work. Signed-off-by: Grant Erickson <gerickson@nuovations.com> Acked-by: Jeff Garzik <jgarzik@pobox.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/net/ibm_newemac/core.c')
-rw-r--r--drivers/net/ibm_newemac/core.c61
1 files changed, 42 insertions, 19 deletions
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 5d2108c5ac7c..ed24a1d607dd 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -363,25 +363,31 @@ static int emac_reset(struct emac_instance *dev)
363 363
364static void emac_hash_mc(struct emac_instance *dev) 364static void emac_hash_mc(struct emac_instance *dev)
365{ 365{
366 struct emac_regs __iomem *p = dev->emacp; 366 const int regs = EMAC_XAHT_REGS(dev);
367 u16 gaht[4] = { 0 }; 367 u32 *gaht_base = emac_gaht_base(dev);
368 u32 gaht_temp[regs];
368 struct dev_mc_list *dmi; 369 struct dev_mc_list *dmi;
370 int i;
369 371
370 DBG(dev, "hash_mc %d" NL, dev->ndev->mc_count); 372 DBG(dev, "hash_mc %d" NL, dev->ndev->mc_count);
371 373
374 memset(gaht_temp, 0, sizeof (gaht_temp));
375
372 for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) { 376 for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
373 int bit; 377 int slot, reg, mask;
374 DBG2(dev, "mc %02x:%02x:%02x:%02x:%02x:%02x" NL, 378 DBG2(dev, "mc %02x:%02x:%02x:%02x:%02x:%02x" NL,
375 dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], 379 dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
376 dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]); 380 dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
377 381
378 bit = 63 - (ether_crc(ETH_ALEN, dmi->dmi_addr) >> 26); 382 slot = EMAC_XAHT_CRC_TO_SLOT(dev, ether_crc(ETH_ALEN, dmi->dmi_addr));
379 gaht[bit >> 4] |= 0x8000 >> (bit & 0x0f); 383 reg = EMAC_XAHT_SLOT_TO_REG(dev, slot);
384 mask = EMAC_XAHT_SLOT_TO_MASK(dev, slot);
385
386 gaht_temp[reg] |= mask;
380 } 387 }
381 out_be32(&p->gaht1, gaht[0]); 388
382 out_be32(&p->gaht2, gaht[1]); 389 for (i = 0; i < regs; i++)
383 out_be32(&p->gaht3, gaht[2]); 390 out_be32(gaht_base + i, gaht_temp[i]);
384 out_be32(&p->gaht4, gaht[3]);
385} 391}
386 392
387static inline u32 emac_iff2rmr(struct net_device *ndev) 393static inline u32 emac_iff2rmr(struct net_device *ndev)
@@ -398,7 +404,8 @@ static inline u32 emac_iff2rmr(struct net_device *ndev)
398 404
399 if (ndev->flags & IFF_PROMISC) 405 if (ndev->flags & IFF_PROMISC)
400 r |= EMAC_RMR_PME; 406 r |= EMAC_RMR_PME;
401 else if (ndev->flags & IFF_ALLMULTI || ndev->mc_count > 32) 407 else if (ndev->flags & IFF_ALLMULTI ||
408 (ndev->mc_count > EMAC_XAHT_SLOTS(dev)))
402 r |= EMAC_RMR_PMME; 409 r |= EMAC_RMR_PMME;
403 else if (ndev->mc_count > 0) 410 else if (ndev->mc_count > 0)
404 r |= EMAC_RMR_MAE; 411 r |= EMAC_RMR_MAE;
@@ -542,7 +549,7 @@ static int emac_configure(struct emac_instance *dev)
542 /* Put some arbitrary OUI, Manuf & Rev IDs so we can 549 /* Put some arbitrary OUI, Manuf & Rev IDs so we can
543 * identify this GPCS PHY later. 550 * identify this GPCS PHY later.
544 */ 551 */
545 out_be32(&p->ipcr, 0xdeadbeef); 552 out_be32(&p->u1.emac4.ipcr, 0xdeadbeef);
546 } else 553 } else
547 mr1 |= EMAC_MR1_MF_1000; 554 mr1 |= EMAC_MR1_MF_1000;
548 555
@@ -2015,10 +2022,10 @@ static int emac_get_regs_len(struct emac_instance *dev)
2015{ 2022{
2016 if (emac_has_feature(dev, EMAC_FTR_EMAC4)) 2023 if (emac_has_feature(dev, EMAC_FTR_EMAC4))
2017 return sizeof(struct emac_ethtool_regs_subhdr) + 2024 return sizeof(struct emac_ethtool_regs_subhdr) +
2018 EMAC4_ETHTOOL_REGS_SIZE; 2025 EMAC4_ETHTOOL_REGS_SIZE(dev);
2019 else 2026 else
2020 return sizeof(struct emac_ethtool_regs_subhdr) + 2027 return sizeof(struct emac_ethtool_regs_subhdr) +
2021 EMAC_ETHTOOL_REGS_SIZE; 2028 EMAC_ETHTOOL_REGS_SIZE(dev);
2022} 2029}
2023 2030
2024static int emac_ethtool_get_regs_len(struct net_device *ndev) 2031static int emac_ethtool_get_regs_len(struct net_device *ndev)
@@ -2045,12 +2052,12 @@ static void *emac_dump_regs(struct emac_instance *dev, void *buf)
2045 hdr->index = dev->cell_index; 2052 hdr->index = dev->cell_index;
2046 if (emac_has_feature(dev, EMAC_FTR_EMAC4)) { 2053 if (emac_has_feature(dev, EMAC_FTR_EMAC4)) {
2047 hdr->version = EMAC4_ETHTOOL_REGS_VER; 2054 hdr->version = EMAC4_ETHTOOL_REGS_VER;
2048 memcpy_fromio(hdr + 1, dev->emacp, EMAC4_ETHTOOL_REGS_SIZE); 2055 memcpy_fromio(hdr + 1, dev->emacp, EMAC4_ETHTOOL_REGS_SIZE(dev));
2049 return ((void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE); 2056 return ((void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE(dev));
2050 } else { 2057 } else {
2051 hdr->version = EMAC_ETHTOOL_REGS_VER; 2058 hdr->version = EMAC_ETHTOOL_REGS_VER;
2052 memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE); 2059 memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE(dev));
2053 return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE); 2060 return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE(dev));
2054 } 2061 }
2055} 2062}
2056 2063
@@ -2540,7 +2547,9 @@ static int __devinit emac_init_config(struct emac_instance *dev)
2540 } 2547 }
2541 2548
2542 /* Check EMAC version */ 2549 /* Check EMAC version */
2543 if (of_device_is_compatible(np, "ibm,emac4")) { 2550 if (of_device_is_compatible(np, "ibm,emac4sync")) {
2551 dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC);
2552 } else if (of_device_is_compatible(np, "ibm,emac4")) {
2544 dev->features |= EMAC_FTR_EMAC4; 2553 dev->features |= EMAC_FTR_EMAC4;
2545 if (of_device_is_compatible(np, "ibm,emac-440gx")) 2554 if (of_device_is_compatible(np, "ibm,emac-440gx"))
2546 dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX; 2555 dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX;
@@ -2601,6 +2610,15 @@ static int __devinit emac_init_config(struct emac_instance *dev)
2601 } 2610 }
2602 memcpy(dev->ndev->dev_addr, p, 6); 2611 memcpy(dev->ndev->dev_addr, p, 6);
2603 2612
2613 /* IAHT and GAHT filter parameterization */
2614 if (emac_has_feature(dev, EMAC_FTR_EMAC4SYNC)) {
2615 dev->xaht_slots_shift = EMAC4SYNC_XAHT_SLOTS_SHIFT;
2616 dev->xaht_width_shift = EMAC4SYNC_XAHT_WIDTH_SHIFT;
2617 } else {
2618 dev->xaht_slots_shift = EMAC4_XAHT_SLOTS_SHIFT;
2619 dev->xaht_width_shift = EMAC4_XAHT_WIDTH_SHIFT;
2620 }
2621
2604 DBG(dev, "features : 0x%08x / 0x%08x\n", dev->features, EMAC_FTRS_POSSIBLE); 2622 DBG(dev, "features : 0x%08x / 0x%08x\n", dev->features, EMAC_FTRS_POSSIBLE);
2605 DBG(dev, "tx_fifo_size : %d (%d gige)\n", dev->tx_fifo_size, dev->tx_fifo_size_gige); 2623 DBG(dev, "tx_fifo_size : %d (%d gige)\n", dev->tx_fifo_size, dev->tx_fifo_size_gige);
2606 DBG(dev, "rx_fifo_size : %d (%d gige)\n", dev->rx_fifo_size, dev->rx_fifo_size_gige); 2624 DBG(dev, "rx_fifo_size : %d (%d gige)\n", dev->rx_fifo_size, dev->rx_fifo_size_gige);
@@ -2672,7 +2690,8 @@ static int __devinit emac_probe(struct of_device *ofdev,
2672 goto err_irq_unmap; 2690 goto err_irq_unmap;
2673 } 2691 }
2674 // TODO : request_mem_region 2692 // TODO : request_mem_region
2675 dev->emacp = ioremap(dev->rsrc_regs.start, sizeof(struct emac_regs)); 2693 dev->emacp = ioremap(dev->rsrc_regs.start,
2694 dev->rsrc_regs.end - dev->rsrc_regs.start + 1);
2676 if (dev->emacp == NULL) { 2695 if (dev->emacp == NULL) {
2677 printk(KERN_ERR "%s: Can't map device registers!\n", 2696 printk(KERN_ERR "%s: Can't map device registers!\n",
2678 np->full_name); 2697 np->full_name);
@@ -2884,6 +2903,10 @@ static struct of_device_id emac_match[] =
2884 .type = "network", 2903 .type = "network",
2885 .compatible = "ibm,emac4", 2904 .compatible = "ibm,emac4",
2886 }, 2905 },
2906 {
2907 .type = "network",
2908 .compatible = "ibm,emac4sync",
2909 },
2887 {}, 2910 {},
2888}; 2911};
2889 2912