* Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net)
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/log2.h>
#include <linux/jiffies.h>
#include <linux/crc32.h>
+#include <linux/list.h>
#include <linux/io.h>
#include "niu.h"
#define DRV_MODULE_NAME "niu"
-#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.0"
#define DRV_MODULE_RELDATE "Nov 14, 2008"
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
-#ifndef DMA_44BIT_MASK
-#define DMA_44BIT_MASK 0x00000fffffffffffULL
-#endif
-
#ifndef readq
static u64 readq(void __iomem *reg)
{
}
#endif
-static struct pci_device_id niu_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(niu_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_SUN, 0xabcd)},
{}
};
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "NIU debug level");
-#define niudbg(TYPE, f, a...) \
-do { if ((np)->msg_enable & NETIF_MSG_##TYPE) \
- printk(KERN_DEBUG PFX f, ## a); \
-} while (0)
-
-#define niuinfo(TYPE, f, a...) \
-do { if ((np)->msg_enable & NETIF_MSG_##TYPE) \
- printk(KERN_INFO PFX f, ## a); \
-} while (0)
-
-#define niuwarn(TYPE, f, a...) \
-do { if ((np)->msg_enable & NETIF_MSG_##TYPE) \
- printk(KERN_WARNING PFX f, ## a); \
-} while (0)
-
#define niu_lock_parent(np, flags) \
spin_lock_irqsave(&np->parent->lock, flags)
#define niu_unlock_parent(np, flags) \
nw64_mac(reg, bits);
err = __niu_wait_bits_clear_mac(np, reg, bits, limit, delay);
if (err)
- dev_err(np->device, PFX "%s: bits (%llx) of register %s "
- "would not clear, val[%llx]\n",
- np->dev->name, (unsigned long long) bits, reg_name,
- (unsigned long long) nr64_mac(reg));
+ netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n",
+ (unsigned long long)bits, reg_name,
+ (unsigned long long)nr64_mac(reg));
return err;
}
err = __niu_wait_bits_clear_ipp(np, reg, bits, limit, delay);
if (err)
- dev_err(np->device, PFX "%s: bits (%llx) of register %s "
- "would not clear, val[%llx]\n",
- np->dev->name, (unsigned long long) bits, reg_name,
- (unsigned long long) nr64_ipp(reg));
+ netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n",
+ (unsigned long long)bits, reg_name,
+ (unsigned long long)nr64_ipp(reg));
return err;
}
nw64(reg, bits);
err = __niu_wait_bits_clear(np, reg, bits, limit, delay);
if (err)
- dev_err(np->device, PFX "%s: bits (%llx) of register %s "
- "would not clear, val[%llx]\n",
- np->dev->name, (unsigned long long) bits, reg_name,
- (unsigned long long) nr64(reg));
+ netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n",
+ (unsigned long long)bits, reg_name,
+ (unsigned long long)nr64(reg));
return err;
}
err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
ESR2_TI_PLL_CFG_L, pll_cfg);
if (err) {
- dev_err(np->device, PFX "NIU Port %d "
- "serdes_init_niu_1g_serdes: "
- "mdio write to ESR2_TI_PLL_CFG_L failed", np->port);
+ netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_CFG_L failed\n",
+ np->port, __func__);
return err;
}
err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
ESR2_TI_PLL_STS_L, pll_sts);
if (err) {
- dev_err(np->device, PFX "NIU Port %d "
- "serdes_init_niu_1g_serdes: "
- "mdio write to ESR2_TI_PLL_STS_L failed", np->port);
+ netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_STS_L failed\n",
+ np->port, __func__);
return err;
}
}
if ((sig & mask) != val) {
- dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
- "[%08x]\n", np->port, (int) (sig & mask), (int) val);
+ netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n",
+ np->port, (int)(sig & mask), (int)val);
return -ENODEV;
}
err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff);
if (err) {
- dev_err(np->device, PFX "NIU Port %d "
- "serdes_init_niu_10g_serdes: "
- "mdio write to ESR2_TI_PLL_CFG_L failed", np->port);
+ netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_CFG_L failed\n",
+ np->port, __func__);
return err;
}
err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
ESR2_TI_PLL_STS_L, pll_sts & 0xffff);
if (err) {
- dev_err(np->device, PFX "NIU Port %d "
- "serdes_init_niu_10g_serdes: "
- "mdio write to ESR2_TI_PLL_STS_L failed", np->port);
+ netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_STS_L failed\n",
+ np->port, __func__);
return err;
}
}
if ((sig & mask) != val) {
- pr_info(PFX "NIU Port %u signal bits [%08x] are not "
- "[%08x] for 10G...trying 1G\n",
- np->port, (int) (sig & mask), (int) val);
+ pr_info("NIU Port %u signal bits [%08x] are not [%08x] for 10G...trying 1G\n",
+ np->port, (int)(sig & mask), (int)val);
/* 10G failed, try initializing at 1G */
err = serdes_init_niu_1g_serdes(np);
np->flags &= ~NIU_FLAGS_10G;
np->mac_xcvr = MAC_XCVR_PCS;
} else {
- dev_err(np->device, PFX "Port %u 10G/1G SERDES "
- "Link Failed \n", np->port);
+ netdev_err(np->dev, "Port %u 10G/1G SERDES Link Failed\n",
+ np->port);
return -ENODEV;
}
}
if (err)
return err;
if (reset != 0) {
- dev_err(np->device, PFX "Port %u ESR_RESET "
- "did not clear [%08x]\n",
- np->port, reset);
+ netdev_err(np->dev, "Port %u ESR_RESET did not clear [%08x]\n",
+ np->port, reset);
return -ENODEV;
}
np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
return 0;
}
- dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
- "[%08x]\n", np->port, (int) (sig & mask), (int) val);
+ netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n",
+ np->port, (int)(sig & mask), (int)val);
return -ENODEV;
}
if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
}
if ((sig & mask) != val) {
- dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
- "[%08x]\n", np->port, (int) (sig & mask), (int) val);
+ netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n",
+ np->port, (int)(sig & mask), (int)val);
return -ENODEV;
}
return 0;
}
+static int link_status_mii(struct niu *np, int *link_up_p)
+{
+ struct niu_link_config *lp = &np->link_config;
+ int err;
+ int bmsr, advert, ctrl1000, stat1000, lpa, bmcr, estatus;
+ int supported, advertising, active_speed, active_duplex;
+
+ err = mii_read(np, np->phy_addr, MII_BMCR);
+ if (unlikely(err < 0))
+ return err;
+ bmcr = err;
+
+ err = mii_read(np, np->phy_addr, MII_BMSR);
+ if (unlikely(err < 0))
+ return err;
+ bmsr = err;
+
+ err = mii_read(np, np->phy_addr, MII_ADVERTISE);
+ if (unlikely(err < 0))
+ return err;
+ advert = err;
+
+ err = mii_read(np, np->phy_addr, MII_LPA);
+ if (unlikely(err < 0))
+ return err;
+ lpa = err;
+
+ if (likely(bmsr & BMSR_ESTATEN)) {
+ err = mii_read(np, np->phy_addr, MII_ESTATUS);
+ if (unlikely(err < 0))
+ return err;
+ estatus = err;
+
+ err = mii_read(np, np->phy_addr, MII_CTRL1000);
+ if (unlikely(err < 0))
+ return err;
+ ctrl1000 = err;
+
+ err = mii_read(np, np->phy_addr, MII_STAT1000);
+ if (unlikely(err < 0))
+ return err;
+ stat1000 = err;
+ } else
+ estatus = ctrl1000 = stat1000 = 0;
+
+ supported = 0;
+ if (bmsr & BMSR_ANEGCAPABLE)
+ supported |= SUPPORTED_Autoneg;
+ if (bmsr & BMSR_10HALF)
+ supported |= SUPPORTED_10baseT_Half;
+ if (bmsr & BMSR_10FULL)
+ supported |= SUPPORTED_10baseT_Full;
+ if (bmsr & BMSR_100HALF)
+ supported |= SUPPORTED_100baseT_Half;
+ if (bmsr & BMSR_100FULL)
+ supported |= SUPPORTED_100baseT_Full;
+ if (estatus & ESTATUS_1000_THALF)
+ supported |= SUPPORTED_1000baseT_Half;
+ if (estatus & ESTATUS_1000_TFULL)
+ supported |= SUPPORTED_1000baseT_Full;
+ lp->supported = supported;
+
+ advertising = 0;
+ if (advert & ADVERTISE_10HALF)
+ advertising |= ADVERTISED_10baseT_Half;
+ if (advert & ADVERTISE_10FULL)
+ advertising |= ADVERTISED_10baseT_Full;
+ if (advert & ADVERTISE_100HALF)
+ advertising |= ADVERTISED_100baseT_Half;
+ if (advert & ADVERTISE_100FULL)
+ advertising |= ADVERTISED_100baseT_Full;
+ if (ctrl1000 & ADVERTISE_1000HALF)
+ advertising |= ADVERTISED_1000baseT_Half;
+ if (ctrl1000 & ADVERTISE_1000FULL)
+ advertising |= ADVERTISED_1000baseT_Full;
+
+ if (bmcr & BMCR_ANENABLE) {
+ int neg, neg1000;
+
+ lp->active_autoneg = 1;
+ advertising |= ADVERTISED_Autoneg;
+
+ neg = advert & lpa;
+ neg1000 = (ctrl1000 << 2) & stat1000;
+
+ if (neg1000 & (LPA_1000FULL | LPA_1000HALF))
+ active_speed = SPEED_1000;
+ else if (neg & LPA_100)
+ active_speed = SPEED_100;
+ else if (neg & (LPA_10HALF | LPA_10FULL))
+ active_speed = SPEED_10;
+ else
+ active_speed = SPEED_INVALID;
+
+ if ((neg1000 & LPA_1000FULL) || (neg & LPA_DUPLEX))
+ active_duplex = DUPLEX_FULL;
+ else if (active_speed != SPEED_INVALID)
+ active_duplex = DUPLEX_HALF;
+ else
+ active_duplex = DUPLEX_INVALID;
+ } else {
+ lp->active_autoneg = 0;
+
+ if ((bmcr & BMCR_SPEED1000) && !(bmcr & BMCR_SPEED100))
+ active_speed = SPEED_1000;
+ else if (bmcr & BMCR_SPEED100)
+ active_speed = SPEED_100;
+ else
+ active_speed = SPEED_10;
+
+ if (bmcr & BMCR_FULLDPLX)
+ active_duplex = DUPLEX_FULL;
+ else
+ active_duplex = DUPLEX_HALF;
+ }
+
+ lp->active_advertising = advertising;
+ lp->active_speed = active_speed;
+ lp->active_duplex = active_duplex;
+ *link_up_p = !!(bmsr & BMSR_LSTATUS);
+
+ return 0;
+}
+
static int link_status_1g_rgmii(struct niu *np, int *link_up_p)
{
struct niu_link_config *lp = &np->link_config;
return err;
}
+static int link_status_1g(struct niu *np, int *link_up_p)
+{
+ struct niu_link_config *lp = &np->link_config;
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&np->lock, flags);
+
+ err = link_status_mii(np, link_up_p);
+ lp->supported |= SUPPORTED_TP;
+ lp->active_advertising |= ADVERTISED_TP;
+
+ spin_unlock_irqrestore(&np->lock, flags);
+ return err;
+}
+
static int bcm8704_reset(struct niu *np)
{
int err, limit;
err = mdio_read(np, np->phy_addr,
BCM8704_PHYXS_DEV_ADDR, MII_BMCR);
- if (err < 0)
+ if (err < 0 || err == 0xffff)
return err;
err |= BMCR_RESET;
err = mdio_write(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
break;
}
if (limit < 0) {
- dev_err(np->device, PFX "Port %u PHY will not reset "
- "(bmcr=%04x)\n", np->port, (err & 0xffff));
+ netdev_err(np->dev, "Port %u PHY will not reset (bmcr=%04x)\n",
+ np->port, (err & 0xffff));
return -ENODEV;
}
return 0;
MII_STAT1000);
if (err < 0)
return err;
- pr_info(PFX "Port %u PMA_PMD(MII_STAT1000) [%04x]\n",
- np->port, err);
+ pr_info("Port %u PMA_PMD(MII_STAT1000) [%04x]\n", np->port, err);
err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR, 0x20);
if (err < 0)
return err;
- pr_info(PFX "Port %u USER_DEV3(0x20) [%04x]\n",
- np->port, err);
+ pr_info("Port %u USER_DEV3(0x20) [%04x]\n", np->port, err);
err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
MII_NWAYTEST);
if (err < 0)
return err;
- pr_info(PFX "Port %u PHYXS(MII_NWAYTEST) [%04x]\n",
- np->port, err);
+ pr_info("Port %u PHYXS(MII_NWAYTEST) [%04x]\n", np->port, err);
#endif
/* XXX dig this out it might not be so useful XXX */
if (analog_stat0 != 0x03fc) {
if ((analog_stat0 == 0x43bc) && (tx_alarm_status != 0)) {
- pr_info(PFX "Port %u cable not connected "
- "or bad cable.\n", np->port);
+ pr_info("Port %u cable not connected or bad cable\n",
+ np->port);
} else if (analog_stat0 == 0x639c) {
- pr_info(PFX "Port %u optical module is bad "
- "or missing.\n", np->port);
+ pr_info("Port %u optical module is bad or missing\n",
+ np->port);
}
}
break;
}
if (limit < 0) {
- dev_err(np->device, PFX "Port %u MII would not reset, "
- "bmcr[%04x]\n", np->port, err);
+ netdev_err(np->dev, "Port %u MII would not reset, bmcr[%04x]\n",
+ np->port, err);
return -ENODEV;
}
return err;
}
- /* XXX configurable XXX */
- /* XXX for now don't advertise half-duplex or asym pause... XXX */
- adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
- if (bmsr & BMSR_10FULL)
- adv |= ADVERTISE_10FULL;
- if (bmsr & BMSR_100FULL)
- adv |= ADVERTISE_100FULL;
- err = mii_write(np, np->phy_addr, MII_ADVERTISE, adv);
- if (err)
- return err;
-
- if (bmsr & BMSR_ESTATEN) {
- u16 ctrl1000 = 0;
-
- if (estat & ESTATUS_1000_TFULL)
- ctrl1000 |= ADVERTISE_1000FULL;
- err = mii_write(np, np->phy_addr, MII_CTRL1000, ctrl1000);
+ if (lp->autoneg) {
+ u16 ctrl1000;
+
+ adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
+ if ((bmsr & BMSR_10HALF) &&
+ (lp->advertising & ADVERTISED_10baseT_Half))
+ adv |= ADVERTISE_10HALF;
+ if ((bmsr & BMSR_10FULL) &&
+ (lp->advertising & ADVERTISED_10baseT_Full))
+ adv |= ADVERTISE_10FULL;
+ if ((bmsr & BMSR_100HALF) &&
+ (lp->advertising & ADVERTISED_100baseT_Half))
+ adv |= ADVERTISE_100HALF;
+ if ((bmsr & BMSR_100FULL) &&
+ (lp->advertising & ADVERTISED_100baseT_Full))
+ adv |= ADVERTISE_100FULL;
+ err = mii_write(np, np->phy_addr, MII_ADVERTISE, adv);
if (err)
return err;
+
+ if (likely(bmsr & BMSR_ESTATEN)) {
+ ctrl1000 = 0;
+ if ((estat & ESTATUS_1000_THALF) &&
+ (lp->advertising & ADVERTISED_1000baseT_Half))
+ ctrl1000 |= ADVERTISE_1000HALF;
+ if ((estat & ESTATUS_1000_TFULL) &&
+ (lp->advertising & ADVERTISED_1000baseT_Full))
+ ctrl1000 |= ADVERTISE_1000FULL;
+ err = mii_write(np, np->phy_addr,
+ MII_CTRL1000, ctrl1000);
+ if (err)
+ return err;
+ }
+
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ } else {
+ /* !lp->autoneg */
+ int fulldpx;
+
+ if (lp->duplex == DUPLEX_FULL) {
+ bmcr |= BMCR_FULLDPLX;
+ fulldpx = 1;
+ } else if (lp->duplex == DUPLEX_HALF)
+ fulldpx = 0;
+ else
+ return -EINVAL;
+
+ if (lp->speed == SPEED_1000) {
+ /* if X-full requested while not supported, or
+ X-half requested while not supported... */
+ if ((fulldpx && !(estat & ESTATUS_1000_TFULL)) ||
+ (!fulldpx && !(estat & ESTATUS_1000_THALF)))
+ return -EINVAL;
+ bmcr |= BMCR_SPEED1000;
+ } else if (lp->speed == SPEED_100) {
+ if ((fulldpx && !(bmsr & BMSR_100FULL)) ||
+ (!fulldpx && !(bmsr & BMSR_100HALF)))
+ return -EINVAL;
+ bmcr |= BMCR_SPEED100;
+ } else if (lp->speed == SPEED_10) {
+ if ((fulldpx && !(bmsr & BMSR_10FULL)) ||
+ (!fulldpx && !(bmsr & BMSR_10HALF)))
+ return -EINVAL;
+ } else
+ return -EINVAL;
}
- bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
err = mii_write(np, np->phy_addr, MII_BMCR, bmcr);
if (err)
return err;
+#if 0
err = mii_read(np, np->phy_addr, MII_BMCR);
if (err < 0)
return err;
+ bmcr = err;
+
err = mii_read(np, np->phy_addr, MII_BMSR);
if (err < 0)
return err;
-#if 0
- pr_info(PFX "Port %u after MII init bmcr[%04x] bmsr[%04x]\n",
+ bmsr = err;
+
+ pr_info("Port %u after MII init bmcr[%04x] bmsr[%04x]\n",
np->port, bmcr, bmsr);
#endif
unsigned long flags;
if (!netif_carrier_ok(dev) && link_up) {
- niuinfo(LINK, "%s: Link is up at %s, %s duplex\n",
- dev->name,
- (lp->active_speed == SPEED_10000 ?
- "10Gb/sec" :
- (lp->active_speed == SPEED_1000 ?
- "1Gb/sec" :
- (lp->active_speed == SPEED_100 ?
- "100Mbit/sec" : "10Mbit/sec"))),
- (lp->active_duplex == DUPLEX_FULL ?
- "full" : "half"));
+ netif_info(np, link, dev, "Link is up at %s, %s duplex\n",
+ lp->active_speed == SPEED_10000 ? "10Gb/sec" :
+ lp->active_speed == SPEED_1000 ? "1Gb/sec" :
+ lp->active_speed == SPEED_100 ? "100Mbit/sec" :
+ "10Mbit/sec",
+ lp->active_duplex == DUPLEX_FULL ? "full" : "half");
spin_lock_irqsave(&np->lock, flags);
niu_init_xif(np);
netif_carrier_on(dev);
} else if (netif_carrier_ok(dev) && !link_up) {
- niuwarn(LINK, "%s: Link is down\n", dev->name);
+ netif_warn(np, link, dev, "Link is down\n");
spin_lock_irqsave(&np->lock, flags);
niu_handle_led(np, 0);
spin_unlock_irqrestore(&np->lock, flags);
err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
BCM8704_PMD_RCV_SIGDET);
- if (err < 0)
+ if (err < 0 || err == 0xffff)
goto out;
if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
err = 0;
out:
*link_up_p = link_up;
- if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
- err = 0;
return err;
}
if (phy_present != phy_present_prev) {
/* state change */
if (phy_present) {
+ /* A NEM was just plugged in */
np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
if (np->phy_ops->xcvr_init)
err = np->phy_ops->xcvr_init(np);
if (err) {
+ err = mdio_read(np, np->phy_addr,
+ BCM8704_PHYXS_DEV_ADDR, MII_BMCR);
+ if (err == 0xffff) {
+ /* No mdio, back-to-back XAUI */
+ goto out;
+ }
/* debounce */
np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
}
} else {
np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
*link_up_p = 0;
- niuwarn(LINK, "%s: Hotplug PHY Removed\n",
- np->dev->name);
+ netif_warn(np, link, np->dev,
+ "Hotplug PHY Removed\n");
}
}
- if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT)
+out:
+ if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) {
err = link_status_10g_bcm8706(np, link_up_p);
- }
-
- spin_unlock_irqrestore(&np->lock, flags);
-
- return err;
-}
-
-static int link_status_1g(struct niu *np, int *link_up_p)
-{
- struct niu_link_config *lp = &np->link_config;
- u16 current_speed, bmsr;
- unsigned long flags;
- u8 current_duplex;
- int err, link_up;
-
- link_up = 0;
- current_speed = SPEED_INVALID;
- current_duplex = DUPLEX_INVALID;
-
- spin_lock_irqsave(&np->lock, flags);
-
- err = -EINVAL;
- if (np->link_config.loopback_mode != LOOPBACK_DISABLED)
- goto out;
-
- err = mii_read(np, np->phy_addr, MII_BMSR);
- if (err < 0)
- goto out;
-
- bmsr = err;
- if (bmsr & BMSR_LSTATUS) {
- u16 adv, lpa, common, estat;
-
- err = mii_read(np, np->phy_addr, MII_ADVERTISE);
- if (err < 0)
- goto out;
- adv = err;
-
- err = mii_read(np, np->phy_addr, MII_LPA);
- if (err < 0)
- goto out;
- lpa = err;
-
- common = adv & lpa;
-
- err = mii_read(np, np->phy_addr, MII_ESTATUS);
- if (err < 0)
- goto out;
- estat = err;
-
- link_up = 1;
- if (estat & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) {
- current_speed = SPEED_1000;
- if (estat & ESTATUS_1000_TFULL)
- current_duplex = DUPLEX_FULL;
- else
- current_duplex = DUPLEX_HALF;
- } else {
- if (common & ADVERTISE_100BASE4) {
- current_speed = SPEED_100;
- current_duplex = DUPLEX_HALF;
- } else if (common & ADVERTISE_100FULL) {
- current_speed = SPEED_100;
- current_duplex = DUPLEX_FULL;
- } else if (common & ADVERTISE_100HALF) {
- current_speed = SPEED_100;
- current_duplex = DUPLEX_HALF;
- } else if (common & ADVERTISE_10FULL) {
- current_speed = SPEED_10;
- current_duplex = DUPLEX_FULL;
- } else if (common & ADVERTISE_10HALF) {
- current_speed = SPEED_10;
- current_duplex = DUPLEX_HALF;
- } else
- link_up = 0;
+ if (err == 0xffff) {
+ /* No mdio, back-to-back XAUI: it is C10NEM */
+ *link_up_p = 1;
+ np->link_config.active_speed = SPEED_10000;
+ np->link_config.active_duplex = DUPLEX_FULL;
+ }
}
}
- lp->active_speed = current_speed;
- lp->active_duplex = current_duplex;
- err = 0;
-out:
spin_unlock_irqrestore(&np->lock, flags);
- *link_up_p = link_up;
- return err;
+ return 0;
}
static int niu_link_status(struct niu *np, int *link_up_p)
.link_status = link_status_10g_hotplug,
};
+static const struct niu_phy_ops phy_ops_niu_10g_hotplug = {
+ .serdes_init = serdes_init_niu_10g_fiber,
+ .xcvr_init = xcvr_init_10g_bcm8706,
+ .link_status = link_status_10g_hotplug,
+};
+
static const struct niu_phy_ops phy_ops_10g_copper = {
.serdes_init = serdes_init_10g,
.link_status = link_status_10g, /* XXX */
.phy_addr_base = 8,
};
+static const struct niu_phy_template phy_template_niu_10g_hotplug = {
+ .ops = &phy_ops_niu_10g_hotplug,
+ .phy_addr_base = 8,
+};
+
static const struct niu_phy_template phy_template_10g_copper = {
.ops = &phy_ops_10g_copper,
.phy_addr_base = 10,
struct niu_link_config *lp = &np->link_config;
unsigned long ctrl_reg, test_cfg_reg, pll_cfg, i;
u64 ctrl_val, test_cfg_val, sig, mask, val;
- int err;
u64 reset_val;
switch (np->port) {
/* Initialize all 4 lanes of the SERDES. */
for (i = 0; i < 4; i++) {
u32 rxtx_ctrl, glue0;
+ int err;
err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl);
if (err)
np->flags &= ~NIU_FLAGS_10G;
np->mac_xcvr = MAC_XCVR_PCS;
} else {
- dev_err(np->device, PFX "Port %u 10G/1G SERDES Link Failed \n",
- np->port);
+ netdev_err(np->dev, "Port %u 10G/1G SERDES Link Failed\n",
+ np->port);
return -ENODEV;
}
}
case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
/* 10G Fiber */
default:
- tp = &phy_template_niu_10g_fiber;
- phy_addr_off += np->port;
+ if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
+ tp = &phy_template_niu_10g_hotplug;
+ if (np->port == 0)
+ phy_addr_off = 8;
+ if (np->port == 1)
+ phy_addr_off = 12;
+ } else {
+ tp = &phy_template_niu_10g_fiber;
+ phy_addr_off += np->port;
+ }
break;
}
} else {
case NIU_FLAGS_10G:
/* 10G copper */
- tp = &phy_template_1g_copper;
+ tp = &phy_template_10g_copper;
break;
case NIU_FLAGS_FIBER:
msleep(200);
}
err = niu_serdes_init(np);
- if (err)
+ if (err && !(np->flags & NIU_FLAGS_HOTPLUG_PHY))
return err;
msleep(200);
err = niu_xcvr_init(np);
- if (!err)
+ if (!err || (np->flags & NIU_FLAGS_HOTPLUG_PHY))
niu_link_status(np, &ignore);
return 0;
}
break;
udelay(1);
}
- if (limit < 0)
+ if (limit <= 0)
return -ENODEV;
return 0;
return 0;
}
-#if 0
static int tcam_user_ip_class_set(struct niu *np, unsigned long class,
int ipv6, u64 protocol_id,
u64 tos_mask, u64 tos_val)
return 0;
}
-#endif
static int tcam_early_init(struct niu *np)
{
parent = np->parent;
err = 0;
if (!(parent->flags & PARENT_FLGS_CLS_HWINIT)) {
- niudbg(PROBE, "fflp_early_init: Initting hw on port %u\n",
- np->port);
if (np->parent->plat_type != PLAT_TYPE_NIU) {
fflp_reset(np);
fflp_set_timings(np);
err = fflp_disable_all_partitions(np);
if (err) {
- niudbg(PROBE, "fflp_disable_all_partitions "
- "failed, err=%d\n", err);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "fflp_disable_all_partitions failed, err=%d\n",
+ err);
goto out;
}
}
err = tcam_early_init(np);
if (err) {
- niudbg(PROBE, "tcam_early_init failed, err=%d\n",
- err);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "tcam_early_init failed, err=%d\n", err);
goto out;
}
fflp_llcsnap_enable(np, 1);
err = tcam_flush_all(np);
if (err) {
- niudbg(PROBE, "tcam_flush_all failed, err=%d\n",
- err);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "tcam_flush_all failed, err=%d\n", err);
goto out;
}
if (np->parent->plat_type != PLAT_TYPE_NIU) {
err = fflp_hash_clear(np);
if (err) {
- niudbg(PROBE, "fflp_hash_clear failed, "
- "err=%d\n", err);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "fflp_hash_clear failed, err=%d\n",
+ err);
goto out;
}
}
vlan_tbl_clear(np);
- niudbg(PROBE, "fflp_early_init: Success\n");
parent->flags |= PARENT_FLGS_CLS_HWINIT;
}
out:
return 0;
}
+/* Entries for the ports are interleaved in the TCAM */
+static u16 tcam_get_index(struct niu *np, u16 idx)
+{
+ /* One entry reserved for IP fragment rule */
+ if (idx >= (np->clas.tcam_sz - 1))
+ idx = 0;
+ return (np->clas.tcam_top + ((idx+1) * np->parent->num_ports));
+}
+
+static u16 tcam_get_size(struct niu *np)
+{
+ /* One entry reserved for IP fragment rule */
+ return np->clas.tcam_sz - 1;
+}
+
+static u16 tcam_get_valid_entry_cnt(struct niu *np)
+{
+ /* One entry reserved for IP fragment rule */
+ return np->clas.tcam_valid_entries - 1;
+}
+
static void niu_rx_skb_append(struct sk_buff *skb, struct page *page,
u32 offset, u32 size)
{
return num_rcr;
}
-static int niu_process_rx_pkt(struct niu *np, struct rx_ring_info *rp)
+static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
+ struct rx_ring_info *rp)
{
unsigned int index = rp->rcr_index;
struct sk_buff *skb;
rp->rcr_index = index;
skb_reserve(skb, NET_IP_ALIGN);
- __pskb_pull_tail(skb, min(len, NIU_RXPULL_MAX));
+ __pskb_pull_tail(skb, min(len, VLAN_ETH_HLEN));
rp->rx_packets++;
rp->rx_bytes += skb->len;
skb->protocol = eth_type_trans(skb, np->dev);
- netif_receive_skb(skb);
+ skb_record_rx_queue(skb, rp->rx_channel);
+ napi_gro_receive(napi, skb);
return num_rcr;
}
cons = rp->cons;
- niudbg(TX_DONE, "%s: niu_tx_work() pkt_cnt[%u] cons[%d]\n",
- np->dev->name, pkt_cnt, cons);
+ netif_printk(np, tx_done, KERN_DEBUG, np->dev,
+ "%s() pkt_cnt[%u] cons[%d]\n", __func__, pkt_cnt, cons);
while (pkt_cnt--)
cons = release_tx_packet(np, rp, cons);
}
}
-static int niu_rx_work(struct niu *np, struct rx_ring_info *rp, int budget)
+static inline void niu_sync_rx_discard_stats(struct niu *np,
+ struct rx_ring_info *rp,
+ const int limit)
+{
+ /* This elaborate scheme is needed for reading the RX discard
+ * counters, as they are only 16-bit and can overflow quickly,
+ * and because the overflow indication bit is not usable as
+ * the counter value does not wrap, but remains at max value
+ * 0xFFFF.
+ *
+ * In theory and in practice counters can be lost in between
+ * reading nr64() and clearing the counter nw64(). For this
+ * reason, the number of counter clearings nw64() is
+ * limited/reduced though the limit parameter.
+ */
+ int rx_channel = rp->rx_channel;
+ u32 misc, wred;
+
+ /* RXMISC (Receive Miscellaneous Discard Count), covers the
+ * following discard events: IPP (Input Port Process),
+ * FFLP/TCAM, Full RCR (Receive Completion Ring) RBR (Receive
+ * Block Ring) prefetch buffer is empty.
+ */
+ misc = nr64(RXMISC(rx_channel));
+ if (unlikely((misc & RXMISC_COUNT) > limit)) {
+ nw64(RXMISC(rx_channel), 0);
+ rp->rx_errors += misc & RXMISC_COUNT;
+
+ if (unlikely(misc & RXMISC_OFLOW))
+ dev_err(np->device, "rx-%d: Counter overflow RXMISC discard\n",
+ rx_channel);
+
+ netif_printk(np, rx_err, KERN_DEBUG, np->dev,
+ "rx-%d: MISC drop=%u over=%u\n",
+ rx_channel, misc, misc-limit);
+ }
+
+ /* WRED (Weighted Random Early Discard) by hardware */
+ wred = nr64(RED_DIS_CNT(rx_channel));
+ if (unlikely((wred & RED_DIS_CNT_COUNT) > limit)) {
+ nw64(RED_DIS_CNT(rx_channel), 0);
+ rp->rx_dropped += wred & RED_DIS_CNT_COUNT;
+
+ if (unlikely(wred & RED_DIS_CNT_OFLOW))
+ dev_err(np->device, "rx-%d: Counter overflow WRED discard\n", rx_channel);
+
+ netif_printk(np, rx_err, KERN_DEBUG, np->dev,
+ "rx-%d: WRED drop=%u over=%u\n",
+ rx_channel, wred, wred-limit);
+ }
+}
+
+static int niu_rx_work(struct napi_struct *napi, struct niu *np,
+ struct rx_ring_info *rp, int budget)
{
int qlen, rcr_done = 0, work_done = 0;
struct rxdma_mailbox *mbox = rp->mbox;
mbox->rx_dma_ctl_stat = 0;
mbox->rcrstat_a = 0;
- niudbg(RX_STATUS, "%s: niu_rx_work(chan[%d]), stat[%llx] qlen=%d\n",
- np->dev->name, rp->rx_channel, (unsigned long long) stat, qlen);
+ netif_printk(np, rx_status, KERN_DEBUG, np->dev,
+ "%s(chan[%d]), stat[%llx] qlen=%d\n",
+ __func__, rp->rx_channel, (unsigned long long)stat, qlen);
rcr_done = work_done = 0;
qlen = min(qlen, budget);
while (work_done < qlen) {
- rcr_done += niu_process_rx_pkt(np, rp);
+ rcr_done += niu_process_rx_pkt(napi, np, rp);
work_done++;
}
nw64(RX_DMA_CTL_STAT(rp->rx_channel), stat);
+ /* Only sync discards stats when qlen indicate potential for drops */
+ if (qlen > 10)
+ niu_sync_rx_discard_stats(np, rp, 0x7FFF);
+
return work_done;
}
u32 rx_vec = (v0 & 0xffffffff);
int i, work_done = 0;
- niudbg(INTR, "%s: niu_poll_core() v0[%016llx]\n",
- np->dev->name, (unsigned long long) v0);
+ netif_printk(np, intr, KERN_DEBUG, np->dev,
+ "%s() v0[%016llx]\n", __func__, (unsigned long long)v0);
for (i = 0; i < np->num_tx_rings; i++) {
struct tx_ring_info *rp = &np->tx_rings[i];
if (rx_vec & (1 << rp->rx_channel)) {
int this_work_done;
- this_work_done = niu_rx_work(np, rp,
+ this_work_done = niu_rx_work(&lp->napi, np, rp,
budget);
budget -= this_work_done;
work_done = niu_poll_core(np, lp, budget);
if (work_done < budget) {
- netif_rx_complete(np->dev, napi);
+ napi_complete(napi);
niu_ldg_rearm(np, lp, 1);
}
return work_done;
static void niu_log_rxchan_errors(struct niu *np, struct rx_ring_info *rp,
u64 stat)
{
- dev_err(np->device, PFX "%s: RX channel %u errors ( ",
- np->dev->name, rp->rx_channel);
+ netdev_err(np->dev, "RX channel %u errors ( ", rp->rx_channel);
if (stat & RX_DMA_CTL_STAT_RBR_TMOUT)
- printk("RBR_TMOUT ");
+ pr_cont("RBR_TMOUT ");
if (stat & RX_DMA_CTL_STAT_RSP_CNT_ERR)
- printk("RSP_CNT ");
+ pr_cont("RSP_CNT ");
if (stat & RX_DMA_CTL_STAT_BYTE_EN_BUS)
- printk("BYTE_EN_BUS ");
+ pr_cont("BYTE_EN_BUS ");
if (stat & RX_DMA_CTL_STAT_RSP_DAT_ERR)
- printk("RSP_DAT ");
+ pr_cont("RSP_DAT ");
if (stat & RX_DMA_CTL_STAT_RCR_ACK_ERR)
- printk("RCR_ACK ");
+ pr_cont("RCR_ACK ");
if (stat & RX_DMA_CTL_STAT_RCR_SHA_PAR)
- printk("RCR_SHA_PAR ");
+ pr_cont("RCR_SHA_PAR ");
if (stat & RX_DMA_CTL_STAT_RBR_PRE_PAR)
- printk("RBR_PRE_PAR ");
+ pr_cont("RBR_PRE_PAR ");
if (stat & RX_DMA_CTL_STAT_CONFIG_ERR)
- printk("CONFIG ");
+ pr_cont("CONFIG ");
if (stat & RX_DMA_CTL_STAT_RCRINCON)
- printk("RCRINCON ");
+ pr_cont("RCRINCON ");
if (stat & RX_DMA_CTL_STAT_RCRFULL)
- printk("RCRFULL ");
+ pr_cont("RCRFULL ");
if (stat & RX_DMA_CTL_STAT_RBRFULL)
- printk("RBRFULL ");
+ pr_cont("RBRFULL ");
if (stat & RX_DMA_CTL_STAT_RBRLOGPAGE)
- printk("RBRLOGPAGE ");
+ pr_cont("RBRLOGPAGE ");
if (stat & RX_DMA_CTL_STAT_CFIGLOGPAGE)
- printk("CFIGLOGPAGE ");
+ pr_cont("CFIGLOGPAGE ");
if (stat & RX_DMA_CTL_STAT_DC_FIFO_ERR)
- printk("DC_FIDO ");
+ pr_cont("DC_FIDO ");
- printk(")\n");
+ pr_cont(")\n");
}
static int niu_rx_error(struct niu *np, struct rx_ring_info *rp)
err = -EINVAL;
if (err) {
- dev_err(np->device, PFX "%s: RX channel %u error, stat[%llx]\n",
- np->dev->name, rp->rx_channel,
- (unsigned long long) stat);
+ netdev_err(np->dev, "RX channel %u error, stat[%llx]\n",
+ rp->rx_channel,
+ (unsigned long long) stat);
niu_log_rxchan_errors(np, rp, stat);
}
static void niu_log_txchan_errors(struct niu *np, struct tx_ring_info *rp,
u64 cs)
{
- dev_err(np->device, PFX "%s: TX channel %u errors ( ",
- np->dev->name, rp->tx_channel);
+ netdev_err(np->dev, "TX channel %u errors ( ", rp->tx_channel);
if (cs & TX_CS_MBOX_ERR)
- printk("MBOX ");
+ pr_cont("MBOX ");
if (cs & TX_CS_PKT_SIZE_ERR)
- printk("PKT_SIZE ");
+ pr_cont("PKT_SIZE ");
if (cs & TX_CS_TX_RING_OFLOW)
- printk("TX_RING_OFLOW ");
+ pr_cont("TX_RING_OFLOW ");
if (cs & TX_CS_PREF_BUF_PAR_ERR)
- printk("PREF_BUF_PAR ");
+ pr_cont("PREF_BUF_PAR ");
if (cs & TX_CS_NACK_PREF)
- printk("NACK_PREF ");
+ pr_cont("NACK_PREF ");
if (cs & TX_CS_NACK_PKT_RD)
- printk("NACK_PKT_RD ");
+ pr_cont("NACK_PKT_RD ");
if (cs & TX_CS_CONF_PART_ERR)
- printk("CONF_PART ");
+ pr_cont("CONF_PART ");
if (cs & TX_CS_PKT_PRT_ERR)
- printk("PKT_PTR ");
+ pr_cont("PKT_PTR ");
- printk(")\n");
+ pr_cont(")\n");
}
static int niu_tx_error(struct niu *np, struct tx_ring_info *rp)
logh = nr64(TX_RNG_ERR_LOGH(rp->tx_channel));
logl = nr64(TX_RNG_ERR_LOGL(rp->tx_channel));
- dev_err(np->device, PFX "%s: TX channel %u error, "
- "cs[%llx] logh[%llx] logl[%llx]\n",
- np->dev->name, rp->tx_channel,
- (unsigned long long) cs,
- (unsigned long long) logh,
- (unsigned long long) logl);
+ netdev_err(np->dev, "TX channel %u error, cs[%llx] logh[%llx] logl[%llx]\n",
+ rp->tx_channel,
+ (unsigned long long)cs,
+ (unsigned long long)logh,
+ (unsigned long long)logl);
niu_log_txchan_errors(np, rp, cs);
phy_mdint = 1;
}
- dev_err(np->device, PFX "%s: MIF interrupt, "
- "stat[%llx] phy_mdint(%d)\n",
- np->dev->name, (unsigned long long) mif_status, phy_mdint);
+ netdev_err(np->dev, "MIF interrupt, stat[%llx] phy_mdint(%d)\n",
+ (unsigned long long)mif_status, phy_mdint);
return -ENODEV;
}
mp->rx_hist_cnt6 += RXMAC_HIST_CNT6_COUNT;
if (val & XRXMAC_STATUS_RXHIST7_CNT_EXP)
mp->rx_hist_cnt7 += RXMAC_HIST_CNT7_COUNT;
- if (val & XRXMAC_STAT_MSK_RXOCTET_CNT_EXP)
+ if (val & XRXMAC_STATUS_RXOCTET_CNT_EXP)
mp->rx_octets += RXMAC_BT_CNT_COUNT;
if (val & XRXMAC_STATUS_CVIOLERR_CNT_EXP)
mp->rx_code_violations += RXMAC_CD_VIO_CNT_COUNT;
static void niu_log_device_error(struct niu *np, u64 stat)
{
- dev_err(np->device, PFX "%s: Core device errors ( ",
- np->dev->name);
+ netdev_err(np->dev, "Core device errors ( ");
if (stat & SYS_ERR_MASK_META2)
- printk("META2 ");
+ pr_cont("META2 ");
if (stat & SYS_ERR_MASK_META1)
- printk("META1 ");
+ pr_cont("META1 ");
if (stat & SYS_ERR_MASK_PEU)
- printk("PEU ");
+ pr_cont("PEU ");
if (stat & SYS_ERR_MASK_TXC)
- printk("TXC ");
+ pr_cont("TXC ");
if (stat & SYS_ERR_MASK_RDMC)
- printk("RDMC ");
+ pr_cont("RDMC ");
if (stat & SYS_ERR_MASK_TDMC)
- printk("TDMC ");
+ pr_cont("TDMC ");
if (stat & SYS_ERR_MASK_ZCP)
- printk("ZCP ");
+ pr_cont("ZCP ");
if (stat & SYS_ERR_MASK_FFLP)
- printk("FFLP ");
+ pr_cont("FFLP ");
if (stat & SYS_ERR_MASK_IPP)
- printk("IPP ");
+ pr_cont("IPP ");
if (stat & SYS_ERR_MASK_MAC)
- printk("MAC ");
+ pr_cont("MAC ");
if (stat & SYS_ERR_MASK_SMX)
- printk("SMX ");
+ pr_cont("SMX ");
- printk(")\n");
+ pr_cont(")\n");
}
static int niu_device_error(struct niu *np)
{
u64 stat = nr64(SYS_ERR_STAT);
- dev_err(np->device, PFX "%s: Core device error, stat[%llx]\n",
- np->dev->name, (unsigned long long) stat);
+ netdev_err(np->dev, "Core device error, stat[%llx]\n",
+ (unsigned long long)stat);
niu_log_device_error(np, stat);
RX_DMA_CTL_STAT_RCRTO);
nw64(RX_DMA_CTL_STAT(rp->rx_channel), stat_write);
- niudbg(INTR, "%s: rxchan_intr stat[%llx]\n",
- np->dev->name, (unsigned long long) stat);
+ netif_printk(np, intr, KERN_DEBUG, np->dev,
+ "%s() stat[%llx]\n", __func__, (unsigned long long)stat);
}
static void niu_txchan_intr(struct niu *np, struct tx_ring_info *rp,
{
rp->tx_cs = nr64(TX_CS(rp->tx_channel));
- niudbg(INTR, "%s: txchan_intr cs[%llx]\n",
- np->dev->name, (unsigned long long) rp->tx_cs);
+ netif_printk(np, intr, KERN_DEBUG, np->dev,
+ "%s() cs[%llx]\n", __func__, (unsigned long long)rp->tx_cs);
}
static void __niu_fastpath_interrupt(struct niu *np, int ldg, u64 v0)
static void niu_schedule_napi(struct niu *np, struct niu_ldg *lp,
u64 v0, u64 v1, u64 v2)
{
- if (likely(netif_rx_schedule_prep(np->dev, &lp->napi))) {
+ if (likely(napi_schedule_prep(&lp->napi))) {
lp->v0 = v0;
lp->v1 = v1;
lp->v2 = v2;
__niu_fastpath_interrupt(np, lp->ldg_num, v0);
- __netif_rx_schedule(np->dev, &lp->napi);
+ __napi_schedule(&lp->napi);
}
}
u64 v0, v1, v2;
if (netif_msg_intr(np))
- printk(KERN_DEBUG PFX "niu_interrupt() ldg[%p](%d) ",
- lp, ldg);
+ printk(KERN_DEBUG KBUILD_MODNAME ": " "%s() ldg[%p](%d)",
+ __func__, lp, ldg);
spin_lock_irqsave(&np->lock, flags);
v2 = nr64(LDSV2(ldg));
if (netif_msg_intr(np))
- printk("v0[%llx] v1[%llx] v2[%llx]\n",
+ pr_cont(" v0[%llx] v1[%llx] v2[%llx]\n",
(unsigned long long) v0,
(unsigned long long) v1,
(unsigned long long) v2);
if (!rp->mbox)
return -ENOMEM;
if ((unsigned long)rp->mbox & (64UL - 1)) {
- dev_err(np->device, PFX "%s: Coherent alloc gives misaligned "
- "RXDMA mailbox %p\n", np->dev->name, rp->mbox);
+ netdev_err(np->dev, "Coherent alloc gives misaligned RXDMA mailbox %p\n",
+ rp->mbox);
return -EINVAL;
}
if (!rp->rcr)
return -ENOMEM;
if ((unsigned long)rp->rcr & (64UL - 1)) {
- dev_err(np->device, PFX "%s: Coherent alloc gives misaligned "
- "RXDMA RCR table %p\n", np->dev->name, rp->rcr);
+ netdev_err(np->dev, "Coherent alloc gives misaligned RXDMA RCR table %p\n",
+ rp->rcr);
return -EINVAL;
}
rp->rcr_table_size = MAX_RCR_RING_SIZE;
if (!rp->rbr)
return -ENOMEM;
if ((unsigned long)rp->rbr & (64UL - 1)) {
- dev_err(np->device, PFX "%s: Coherent alloc gives misaligned "
- "RXDMA RBR table %p\n", np->dev->name, rp->rbr);
+ netdev_err(np->dev, "Coherent alloc gives misaligned RXDMA RBR table %p\n",
+ rp->rbr);
return -EINVAL;
}
rp->rbr_table_size = MAX_RBR_RING_SIZE;
if (!rp->mbox)
return -ENOMEM;
if ((unsigned long)rp->mbox & (64UL - 1)) {
- dev_err(np->device, PFX "%s: Coherent alloc gives misaligned "
- "TXDMA mailbox %p\n", np->dev->name, rp->mbox);
+ netdev_err(np->dev, "Coherent alloc gives misaligned TXDMA mailbox %p\n",
+ rp->mbox);
return -EINVAL;
}
if (!rp->descr)
return -ENOMEM;
if ((unsigned long)rp->descr & (64UL - 1)) {
- dev_err(np->device, PFX "%s: Coherent alloc gives misaligned "
- "TXDMA descr table %p\n", np->dev->name, rp->descr);
+ netdev_err(np->dev, "Coherent alloc gives misaligned TXDMA descr table %p\n",
+ rp->descr);
return -EINVAL;
}
if (rp->descr_dma & ~(TX_RNG_CFIG_STADDR_BASE |
TX_RNG_CFIG_STADDR)) {
- dev_err(np->device, PFX "%s: TX ring channel %d "
- "DMA addr (%llx) is not aligned.\n",
- np->dev->name, channel,
- (unsigned long long) rp->descr_dma);
+ netdev_err(np->dev, "TX ring channel %d DMA addr (%llx) is not aligned\n",
+ channel, (unsigned long long)rp->descr_dma);
return -EINVAL;
}
if (((rp->mbox_dma >> 32) & ~TXDMA_MBH_MBADDR) ||
((u32)rp->mbox_dma & ~TXDMA_MBL_MBADDR)) {
- dev_err(np->device, PFX "%s: TX ring channel %d "
- "MBOX addr (%llx) is has illegal bits.\n",
- np->dev->name, channel,
- (unsigned long long) rp->mbox_dma);
+ netdev_err(np->dev, "TX ring channel %d MBOX addr (%llx) has invalid bits\n",
+ channel, (unsigned long long)rp->mbox_dma);
return -EINVAL;
}
nw64(TXDMA_MBH(channel), rp->mbox_dma >> 32);
{
u64 val = 0;
+ *ret = 0;
switch (rp->rbr_block_size) {
case 4 * 1024:
val |= (RBR_BLKSIZE_4K << RBR_CFIG_B_BLKSIZE_SHIFT);
struct niu_tcam_entry *tp;
int index, err;
- /* XXX fix this allocation scheme XXX */
- index = cp->tcam_index;
+ index = cp->tcam_top;
tp = &parent->tcam[index];
/* Note that the noport bit is the same in both ipv4 and
err = tcam_assoc_write(np, index, tp->assoc_data);
if (err)
return err;
+ tp->valid = 1;
+ cp->tcam_valid_entries++;
return 0;
}
err = niu_wait_bits_clear(np, ZCP_RAM_ACC, ZCP_RAM_ACC_BUSY,
1000, 100);
if (err) {
- dev_err(np->device, PFX "%s: ZCP read busy won't clear, "
- "ZCP_RAM_ACC[%llx]\n", np->dev->name,
- (unsigned long long) nr64(ZCP_RAM_ACC));
+ netdev_err(np->dev, "ZCP read busy won't clear, ZCP_RAM_ACC[%llx]\n",
+ (unsigned long long)nr64(ZCP_RAM_ACC));
return err;
}
err = niu_wait_bits_clear(np, ZCP_RAM_ACC, ZCP_RAM_ACC_BUSY,
1000, 100);
if (err) {
- dev_err(np->device, PFX "%s: ZCP read busy2 won't clear, "
- "ZCP_RAM_ACC[%llx]\n", np->dev->name,
- (unsigned long long) nr64(ZCP_RAM_ACC));
+ netdev_err(np->dev, "ZCP read busy2 won't clear, ZCP_RAM_ACC[%llx]\n",
+ (unsigned long long)nr64(ZCP_RAM_ACC));
return err;
}
if (np->flags & NIU_FLAGS_10G) {
val |= XMAC_CONFIG_MODE_XGMII;
} else {
- if (lp->active_speed == SPEED_100)
- val |= XMAC_CONFIG_MODE_MII;
- else
+ if (lp->active_speed == SPEED_1000)
val |= XMAC_CONFIG_MODE_GMII;
+ else
+ val |= XMAC_CONFIG_MODE_MII;
}
nw64_mac(XMAC_CONFIG, val);
udelay(100);
}
if (limit < 0) {
- dev_err(np->device, PFX "Port %u TX BMAC would not reset, "
- "BTXMAC_SW_RST[%llx]\n",
+ dev_err(np->device, "Port %u TX BMAC would not reset, BTXMAC_SW_RST[%llx]\n",
np->port,
(unsigned long long) nr64_mac(BTXMAC_SW_RST));
return -ENODEV;
/* The XMAC_MIN register only accepts values for TX min which
* have the low 3 bits cleared.
*/
- BUILD_BUG_ON(min & 0x7);
+ BUG_ON(min & 0x7);
if (np->flags & NIU_FLAGS_XMAC)
niu_init_tx_xmac(np, min, max);
while (--limit >= 0) {
if (!(nr64_mac(XRXMAC_SW_RST) & (XRXMAC_SW_RST_REG_RS |
XRXMAC_SW_RST_SOFT_RST)))
- break;
+ break;
udelay(100);
}
if (limit < 0) {
- dev_err(np->device, PFX "Port %u RX XMAC would not reset, "
- "XRXMAC_SW_RST[%llx]\n",
+ dev_err(np->device, "Port %u RX XMAC would not reset, XRXMAC_SW_RST[%llx]\n",
np->port,
(unsigned long long) nr64_mac(XRXMAC_SW_RST));
return -ENODEV;
udelay(100);
}
if (limit < 0) {
- dev_err(np->device, PFX "Port %u RX BMAC would not reset, "
- "BRXMAC_SW_RST[%llx]\n",
+ dev_err(np->device, "Port %u RX BMAC would not reset, BRXMAC_SW_RST[%llx]\n",
np->port,
(unsigned long long) nr64_mac(BRXMAC_SW_RST));
return -ENODEV;
}
if (limit < 0 &&
(rd != 0 && wr != 1)) {
- dev_err(np->device, PFX "%s: IPP would not quiesce, "
- "rd_ptr[%llx] wr_ptr[%llx]\n",
- np->dev->name,
- (unsigned long long) nr64_ipp(IPP_DFIFO_RD_PTR),
- (unsigned long long) nr64_ipp(IPP_DFIFO_WR_PTR));
+ netdev_err(np->dev, "IPP would not quiesce, rd_ptr[%llx] wr_ptr[%llx]\n",
+ (unsigned long long)nr64_ipp(IPP_DFIFO_RD_PTR),
+ (unsigned long long)nr64_ipp(IPP_DFIFO_WR_PTR));
}
val = nr64_ipp(IPP_CFIG);
{
int i, err;
- niudbg(IFUP, "%s: Initialize TXC\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize TXC\n");
niu_txc_enable_port(np, 1);
niu_txc_port_dma_enable(np, 1);
niu_txc_set_imask(np, 0);
- niudbg(IFUP, "%s: Initialize TX channels\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize TX channels\n");
for (i = 0; i < np->num_tx_rings; i++) {
struct tx_ring_info *rp = &np->tx_rings[i];
return err;
}
- niudbg(IFUP, "%s: Initialize RX channels\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize RX channels\n");
err = niu_init_rx_channels(np);
if (err)
goto out_uninit_tx_channels;
- niudbg(IFUP, "%s: Initialize classifier\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize classifier\n");
err = niu_init_classifier_hw(np);
if (err)
goto out_uninit_rx_channels;
- niudbg(IFUP, "%s: Initialize ZCP\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize ZCP\n");
err = niu_init_zcp(np);
if (err)
goto out_uninit_rx_channels;
- niudbg(IFUP, "%s: Initialize IPP\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize IPP\n");
err = niu_init_ipp(np);
if (err)
goto out_uninit_rx_channels;
- niudbg(IFUP, "%s: Initialize MAC\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize MAC\n");
err = niu_init_mac(np);
if (err)
goto out_uninit_ipp;
return 0;
out_uninit_ipp:
- niudbg(IFUP, "%s: Uninit IPP\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Uninit IPP\n");
niu_disable_ipp(np);
out_uninit_rx_channels:
- niudbg(IFUP, "%s: Uninit RX channels\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Uninit RX channels\n");
niu_stop_rx_channels(np);
niu_reset_rx_channels(np);
out_uninit_tx_channels:
- niudbg(IFUP, "%s: Uninit TX channels\n", np->dev->name);
+ netif_printk(np, ifup, KERN_DEBUG, np->dev, "Uninit TX channels\n");
niu_stop_tx_channels(np);
niu_reset_tx_channels(np);
static void niu_stop_hw(struct niu *np)
{
- niudbg(IFDOWN, "%s: Disable interrupts\n", np->dev->name);
+ netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Disable interrupts\n");
niu_enable_interrupts(np, 0);
- niudbg(IFDOWN, "%s: Disable RX MAC\n", np->dev->name);
+ netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Disable RX MAC\n");
niu_enable_rx_mac(np, 0);
- niudbg(IFDOWN, "%s: Disable IPP\n", np->dev->name);
+ netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Disable IPP\n");
niu_disable_ipp(np);
- niudbg(IFDOWN, "%s: Stop TX channels\n", np->dev->name);
+ netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Stop TX channels\n");
niu_stop_tx_channels(np);
- niudbg(IFDOWN, "%s: Stop RX channels\n", np->dev->name);
+ netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Stop RX channels\n");
niu_stop_rx_channels(np);
- niudbg(IFDOWN, "%s: Reset TX channels\n", np->dev->name);
+ netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Reset TX channels\n");
niu_reset_tx_channels(np);
- niudbg(IFDOWN, "%s: Reset RX channels\n", np->dev->name);
+ netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Reset RX channels\n");
niu_reset_rx_channels(np);
}
for (i = 0; i < np->num_rx_rings; i++) {
struct rx_ring_info *rp = &np->rx_rings[i];
+ niu_sync_rx_discard_stats(np, rp, 0);
+
pkts += rp->rx_packets;
bytes += rp->rx_bytes;
dropped += rp->rx_dropped;
struct niu *np = netdev_priv(dev);
int i, alt_cnt, err;
struct dev_addr_list *addr;
+ struct netdev_hw_addr *ha;
unsigned long flags;
u16 hash[16] = { 0, };
np->flags &= ~(NIU_FLAGS_MCAST | NIU_FLAGS_PROMISC);
if (dev->flags & IFF_PROMISC)
np->flags |= NIU_FLAGS_PROMISC;
- if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 0))
+ if ((dev->flags & IFF_ALLMULTI) || (!netdev_mc_empty(dev)))
np->flags |= NIU_FLAGS_MCAST;
- alt_cnt = dev->uc_count;
+ alt_cnt = netdev_uc_count(dev);
if (alt_cnt > niu_num_alt_addr(np)) {
alt_cnt = 0;
np->flags |= NIU_FLAGS_PROMISC;
if (alt_cnt) {
int index = 0;
- for (addr = dev->uc_list; addr; addr = addr->next) {
- err = niu_set_alt_mac(np, index,
- addr->da_addr);
+ netdev_for_each_uc_addr(ha, dev) {
+ err = niu_set_alt_mac(np, index, ha->addr);
if (err)
- printk(KERN_WARNING PFX "%s: Error %d "
- "adding alt mac %d\n",
- dev->name, err, index);
+ netdev_warn(dev, "Error %d adding alt mac %d\n",
+ err, index);
err = niu_enable_alt_mac(np, index, 1);
if (err)
- printk(KERN_WARNING PFX "%s: Error %d "
- "enabling alt mac %d\n",
- dev->name, err, index);
+ netdev_warn(dev, "Error %d enabling alt mac %d\n",
+ err, index);
index++;
}
for (i = alt_start; i < niu_num_alt_addr(np); i++) {
err = niu_enable_alt_mac(np, i, 0);
if (err)
- printk(KERN_WARNING PFX "%s: Error %d "
- "disabling alt mac %d\n",
- dev->name, err, i);
+ netdev_warn(dev, "Error %d disabling alt mac %d\n",
+ err, i);
}
}
if (dev->flags & IFF_ALLMULTI) {
for (i = 0; i < 16; i++)
hash[i] = 0xffff;
- } else if (dev->mc_count > 0) {
- for (addr = dev->mc_list; addr; addr = addr->next) {
+ } else if (!netdev_mc_empty(dev)) {
+ netdev_for_each_mc_addr(addr, dev) {
u32 crc = ether_crc_le(ETH_ALEN, addr->da_addr);
crc >>= 24;
{
struct niu *np = netdev_priv(dev);
- dev_err(np->device, PFX "%s: Transmit timed out, resetting\n",
+ dev_err(np->device, "%s: Transmit timed out, resetting\n",
dev->name);
schedule_work(&np->reset_task);
ipv6 = ihl = 0;
switch (skb->protocol) {
- case __constant_htons(ETH_P_IP):
+ case cpu_to_be16(ETH_P_IP):
ip_proto = ip_hdr(skb)->protocol;
ihl = ip_hdr(skb)->ihl;
break;
- case __constant_htons(ETH_P_IPV6):
+ case cpu_to_be16(ETH_P_IPV6):
ip_proto = ipv6_hdr(skb)->nexthdr;
ihl = (40 >> 2);
ipv6 = 1;
return ret;
}
-static int niu_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t niu_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct niu *np = netdev_priv(dev);
unsigned long align, headroom;
if (niu_tx_avail(rp) <= (skb_shinfo(skb)->nr_frags + 1)) {
netif_tx_stop_queue(txq);
- dev_err(np->device, PFX "%s: BUG! Tx ring full when "
- "queue awake!\n", dev->name);
+ dev_err(np->device, "%s: BUG! Tx ring full when queue awake!\n", dev->name);
rp->tx_errors++;
return NETDEV_TX_BUSY;
}
netif_tx_wake_queue(txq);
}
- dev->trans_start = jiffies;
-
out:
return NETDEV_TX_OK;
memset(cmd, 0, sizeof(*cmd));
cmd->phy_address = np->phy_addr;
cmd->supported = lp->supported;
- cmd->advertising = lp->advertising;
- cmd->autoneg = lp->autoneg;
+ cmd->advertising = lp->active_advertising;
+ cmd->autoneg = lp->active_autoneg;
cmd->speed = lp->active_speed;
cmd->duplex = lp->active_duplex;
+ cmd->port = (np->flags & NIU_FLAGS_FIBER) ? PORT_FIBRE : PORT_TP;
+ cmd->transceiver = (np->flags & NIU_FLAGS_XCVR_SERDES) ?
+ XCVR_EXTERNAL : XCVR_INTERNAL;
return 0;
}
static int niu_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- return -EINVAL;
+ struct niu *np = netdev_priv(dev);
+ struct niu_link_config *lp = &np->link_config;
+
+ lp->advertising = cmd->advertising;
+ lp->speed = cmd->speed;
+ lp->duplex = cmd->duplex;
+ lp->autoneg = cmd->autoneg;
+ return niu_init_link(np);
}
static u32 niu_get_msglevel(struct net_device *dev)
np->msg_enable = value;
}
+static int niu_nway_reset(struct net_device *dev)
+{
+ struct niu *np = netdev_priv(dev);
+
+ if (np->link_config.autoneg)
+ return niu_init_link(np);
+
+ return 0;
+}
+
static int niu_get_eeprom_len(struct net_device *dev)
{
struct niu *np = netdev_priv(dev);
return 0;
}
+static void niu_ethflow_to_l3proto(int flow_type, u8 *pid)
+{
+ switch (flow_type) {
+ case TCP_V4_FLOW:
+ case TCP_V6_FLOW:
+ *pid = IPPROTO_TCP;
+ break;
+ case UDP_V4_FLOW:
+ case UDP_V6_FLOW:
+ *pid = IPPROTO_UDP;
+ break;
+ case SCTP_V4_FLOW:
+ case SCTP_V6_FLOW:
+ *pid = IPPROTO_SCTP;
+ break;
+ case AH_V4_FLOW:
+ case AH_V6_FLOW:
+ *pid = IPPROTO_AH;
+ break;
+ case ESP_V4_FLOW:
+ case ESP_V6_FLOW:
+ *pid = IPPROTO_ESP;
+ break;
+ default:
+ *pid = 0;
+ break;
+ }
+}
+
+static int niu_class_to_ethflow(u64 class, int *flow_type)
+{
+ switch (class) {
+ case CLASS_CODE_TCP_IPV4:
+ *flow_type = TCP_V4_FLOW;
+ break;
+ case CLASS_CODE_UDP_IPV4:
+ *flow_type = UDP_V4_FLOW;
+ break;
+ case CLASS_CODE_AH_ESP_IPV4:
+ *flow_type = AH_V4_FLOW;
+ break;
+ case CLASS_CODE_SCTP_IPV4:
+ *flow_type = SCTP_V4_FLOW;
+ break;
+ case CLASS_CODE_TCP_IPV6:
+ *flow_type = TCP_V6_FLOW;
+ break;
+ case CLASS_CODE_UDP_IPV6:
+ *flow_type = UDP_V6_FLOW;
+ break;
+ case CLASS_CODE_AH_ESP_IPV6:
+ *flow_type = AH_V6_FLOW;
+ break;
+ case CLASS_CODE_SCTP_IPV6:
+ *flow_type = SCTP_V6_FLOW;
+ break;
+ case CLASS_CODE_USER_PROG1:
+ case CLASS_CODE_USER_PROG2:
+ case CLASS_CODE_USER_PROG3:
+ case CLASS_CODE_USER_PROG4:
+ *flow_type = IP_USER_FLOW;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
static int niu_ethflow_to_class(int flow_type, u64 *class)
{
switch (flow_type) {
case UDP_V4_FLOW:
*class = CLASS_CODE_UDP_IPV4;
break;
- case AH_ESP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
*class = CLASS_CODE_AH_ESP_IPV4;
break;
case SCTP_V4_FLOW:
case UDP_V6_FLOW:
*class = CLASS_CODE_UDP_IPV6;
break;
- case AH_ESP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
*class = CLASS_CODE_AH_ESP_IPV6;
break;
case SCTP_V6_FLOW:
{
u64 ethflow = 0;
- if (flow_key & FLOW_KEY_PORT)
- ethflow |= RXH_DEV_PORT;
if (flow_key & FLOW_KEY_L2DA)
ethflow |= RXH_L2DA;
if (flow_key & FLOW_KEY_VLAN)
{
u64 key = 0;
- if (ethflow & RXH_DEV_PORT)
- key |= FLOW_KEY_PORT;
if (ethflow & RXH_L2DA)
key |= FLOW_KEY_L2DA;
if (ethflow & RXH_VLAN)
}
-static int niu_get_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd)
+static int niu_get_hash_opts(struct niu *np, struct ethtool_rxnfc *nfc)
{
- struct niu *np = netdev_priv(dev);
u64 class;
- cmd->data = 0;
+ nfc->data = 0;
- if (!niu_ethflow_to_class(cmd->flow_type, &class))
+ if (!niu_ethflow_to_class(nfc->flow_type, &class))
return -EINVAL;
if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] &
TCAM_KEY_DISC)
- cmd->data = RXH_DISCARD;
+ nfc->data = RXH_DISCARD;
else
-
- cmd->data = niu_flowkey_to_ethflow(np->parent->flow_key[class -
+ nfc->data = niu_flowkey_to_ethflow(np->parent->flow_key[class -
CLASS_CODE_USER_PROG1]);
return 0;
}
-static int niu_set_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd)
+static void niu_get_ip4fs_from_tcam_key(struct niu_tcam_entry *tp,
+ struct ethtool_rx_flow_spec *fsp)
+{
+
+ fsp->h_u.tcp_ip4_spec.ip4src = (tp->key[3] & TCAM_V4KEY3_SADDR) >>
+ TCAM_V4KEY3_SADDR_SHIFT;
+ fsp->h_u.tcp_ip4_spec.ip4dst = (tp->key[3] & TCAM_V4KEY3_DADDR) >>
+ TCAM_V4KEY3_DADDR_SHIFT;
+ fsp->m_u.tcp_ip4_spec.ip4src = (tp->key_mask[3] & TCAM_V4KEY3_SADDR) >>
+ TCAM_V4KEY3_SADDR_SHIFT;
+ fsp->m_u.tcp_ip4_spec.ip4dst = (tp->key_mask[3] & TCAM_V4KEY3_DADDR) >>
+ TCAM_V4KEY3_DADDR_SHIFT;
+
+ fsp->h_u.tcp_ip4_spec.ip4src =
+ cpu_to_be32(fsp->h_u.tcp_ip4_spec.ip4src);
+ fsp->m_u.tcp_ip4_spec.ip4src =
+ cpu_to_be32(fsp->m_u.tcp_ip4_spec.ip4src);
+ fsp->h_u.tcp_ip4_spec.ip4dst =
+ cpu_to_be32(fsp->h_u.tcp_ip4_spec.ip4dst);
+ fsp->m_u.tcp_ip4_spec.ip4dst =
+ cpu_to_be32(fsp->m_u.tcp_ip4_spec.ip4dst);
+
+ fsp->h_u.tcp_ip4_spec.tos = (tp->key[2] & TCAM_V4KEY2_TOS) >>
+ TCAM_V4KEY2_TOS_SHIFT;
+ fsp->m_u.tcp_ip4_spec.tos = (tp->key_mask[2] & TCAM_V4KEY2_TOS) >>
+ TCAM_V4KEY2_TOS_SHIFT;
+
+ switch (fsp->flow_type) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ fsp->h_u.tcp_ip4_spec.psrc =
+ ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
+ fsp->h_u.tcp_ip4_spec.pdst =
+ ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
+ fsp->m_u.tcp_ip4_spec.psrc =
+ ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
+ fsp->m_u.tcp_ip4_spec.pdst =
+ ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
+
+ fsp->h_u.tcp_ip4_spec.psrc =
+ cpu_to_be16(fsp->h_u.tcp_ip4_spec.psrc);
+ fsp->h_u.tcp_ip4_spec.pdst =
+ cpu_to_be16(fsp->h_u.tcp_ip4_spec.pdst);
+ fsp->m_u.tcp_ip4_spec.psrc =
+ cpu_to_be16(fsp->m_u.tcp_ip4_spec.psrc);
+ fsp->m_u.tcp_ip4_spec.pdst =
+ cpu_to_be16(fsp->m_u.tcp_ip4_spec.pdst);
+ break;
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ fsp->h_u.ah_ip4_spec.spi =
+ (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT;
+ fsp->m_u.ah_ip4_spec.spi =
+ (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT;
+
+ fsp->h_u.ah_ip4_spec.spi =
+ cpu_to_be32(fsp->h_u.ah_ip4_spec.spi);
+ fsp->m_u.ah_ip4_spec.spi =
+ cpu_to_be32(fsp->m_u.ah_ip4_spec.spi);
+ break;
+ case IP_USER_FLOW:
+ fsp->h_u.usr_ip4_spec.l4_4_bytes =
+ (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT;
+ fsp->m_u.usr_ip4_spec.l4_4_bytes =
+ (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT;
+
+ fsp->h_u.usr_ip4_spec.l4_4_bytes =
+ cpu_to_be32(fsp->h_u.usr_ip4_spec.l4_4_bytes);
+ fsp->m_u.usr_ip4_spec.l4_4_bytes =
+ cpu_to_be32(fsp->m_u.usr_ip4_spec.l4_4_bytes);
+
+ fsp->h_u.usr_ip4_spec.proto =
+ (tp->key[2] & TCAM_V4KEY2_PROTO) >>
+ TCAM_V4KEY2_PROTO_SHIFT;
+ fsp->m_u.usr_ip4_spec.proto =
+ (tp->key_mask[2] & TCAM_V4KEY2_PROTO) >>
+ TCAM_V4KEY2_PROTO_SHIFT;
+
+ fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
+ break;
+ default:
+ break;
+ }
+}
+
+static int niu_get_ethtool_tcam_entry(struct niu *np,
+ struct ethtool_rxnfc *nfc)
+{
+ struct niu_parent *parent = np->parent;
+ struct niu_tcam_entry *tp;
+ struct ethtool_rx_flow_spec *fsp = &nfc->fs;
+ u16 idx;
+ u64 class;
+ int ret = 0;
+
+ idx = tcam_get_index(np, (u16)nfc->fs.location);
+
+ tp = &parent->tcam[idx];
+ if (!tp->valid) {
+ netdev_info(np->dev, "niu%d: entry [%d] invalid for idx[%d]\n",
+ parent->index, (u16)nfc->fs.location, idx);
+ return -EINVAL;
+ }
+
+ /* fill the flow spec entry */
+ class = (tp->key[0] & TCAM_V4KEY0_CLASS_CODE) >>
+ TCAM_V4KEY0_CLASS_CODE_SHIFT;
+ ret = niu_class_to_ethflow(class, &fsp->flow_type);
+
+ if (ret < 0) {
+ netdev_info(np->dev, "niu%d: niu_class_to_ethflow failed\n",
+ parent->index);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (fsp->flow_type == AH_V4_FLOW || fsp->flow_type == AH_V6_FLOW) {
+ u32 proto = (tp->key[2] & TCAM_V4KEY2_PROTO) >>
+ TCAM_V4KEY2_PROTO_SHIFT;
+ if (proto == IPPROTO_ESP) {
+ if (fsp->flow_type == AH_V4_FLOW)
+ fsp->flow_type = ESP_V4_FLOW;
+ else
+ fsp->flow_type = ESP_V6_FLOW;
+ }
+ }
+
+ switch (fsp->flow_type) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ niu_get_ip4fs_from_tcam_key(tp, fsp);
+ break;
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ /* Not yet implemented */
+ ret = -EINVAL;
+ break;
+ case IP_USER_FLOW:
+ niu_get_ip4fs_from_tcam_key(tp, fsp);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret < 0)
+ goto out;
+
+ if (tp->assoc_data & TCAM_ASSOCDATA_DISC)
+ fsp->ring_cookie = RX_CLS_FLOW_DISC;
+ else
+ fsp->ring_cookie = (tp->assoc_data & TCAM_ASSOCDATA_OFFSET) >>
+ TCAM_ASSOCDATA_OFFSET_SHIFT;
+
+ /* put the tcam size here */
+ nfc->data = tcam_get_size(np);
+out:
+ return ret;
+}
+
+static int niu_get_ethtool_tcam_all(struct niu *np,
+ struct ethtool_rxnfc *nfc,
+ u32 *rule_locs)
+{
+ struct niu_parent *parent = np->parent;
+ struct niu_tcam_entry *tp;
+ int i, idx, cnt;
+ u16 n_entries;
+ unsigned long flags;
+
+
+ /* put the tcam size here */
+ nfc->data = tcam_get_size(np);
+
+ niu_lock_parent(np, flags);
+ n_entries = nfc->rule_cnt;
+ for (cnt = 0, i = 0; i < nfc->data; i++) {
+ idx = tcam_get_index(np, i);
+ tp = &parent->tcam[idx];
+ if (!tp->valid)
+ continue;
+ rule_locs[cnt] = i;
+ cnt++;
+ }
+ niu_unlock_parent(np, flags);
+
+ if (n_entries != cnt) {
+ /* print warning, this should not happen */
+ netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n",
+ np->parent->index, __func__, n_entries, cnt);
+ }
+
+ return 0;
+}
+
+static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ void *rule_locs)
{
struct niu *np = netdev_priv(dev);
+ int ret = 0;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXFH:
+ ret = niu_get_hash_opts(np, cmd);
+ break;
+ case ETHTOOL_GRXRINGS:
+ cmd->data = np->num_rx_rings;
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ cmd->rule_cnt = tcam_get_valid_entry_cnt(np);
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ ret = niu_get_ethtool_tcam_entry(np, cmd);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ ret = niu_get_ethtool_tcam_all(np, cmd, (u32 *)rule_locs);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int niu_set_hash_opts(struct niu *np, struct ethtool_rxnfc *nfc)
+{
u64 class;
u64 flow_key = 0;
unsigned long flags;
- if (!niu_ethflow_to_class(cmd->flow_type, &class))
+ if (!niu_ethflow_to_class(nfc->flow_type, &class))
return -EINVAL;
if (class < CLASS_CODE_USER_PROG1 ||
class > CLASS_CODE_SCTP_IPV6)
return -EINVAL;
- if (cmd->data & RXH_DISCARD) {
+ if (nfc->data & RXH_DISCARD) {
niu_lock_parent(np, flags);
flow_key = np->parent->tcam_key[class -
CLASS_CODE_USER_PROG1];
}
}
- if (!niu_ethflow_to_flowkey(cmd->data, &flow_key))
+ if (!niu_ethflow_to_flowkey(nfc->data, &flow_key))
return -EINVAL;
niu_lock_parent(np, flags);
return 0;
}
+static void niu_get_tcamkey_from_ip4fs(struct ethtool_rx_flow_spec *fsp,
+ struct niu_tcam_entry *tp,
+ int l2_rdc_tab, u64 class)
+{
+ u8 pid = 0;
+ u32 sip, dip, sipm, dipm, spi, spim;
+ u16 sport, dport, spm, dpm;
+
+ sip = be32_to_cpu(fsp->h_u.tcp_ip4_spec.ip4src);
+ sipm = be32_to_cpu(fsp->m_u.tcp_ip4_spec.ip4src);
+ dip = be32_to_cpu(fsp->h_u.tcp_ip4_spec.ip4dst);
+ dipm = be32_to_cpu(fsp->m_u.tcp_ip4_spec.ip4dst);
+
+ tp->key[0] = class << TCAM_V4KEY0_CLASS_CODE_SHIFT;
+ tp->key_mask[0] = TCAM_V4KEY0_CLASS_CODE;
+ tp->key[1] = (u64)l2_rdc_tab << TCAM_V4KEY1_L2RDCNUM_SHIFT;
+ tp->key_mask[1] = TCAM_V4KEY1_L2RDCNUM;
+
+ tp->key[3] = (u64)sip << TCAM_V4KEY3_SADDR_SHIFT;
+ tp->key[3] |= dip;
+
+ tp->key_mask[3] = (u64)sipm << TCAM_V4KEY3_SADDR_SHIFT;
+ tp->key_mask[3] |= dipm;
+
+ tp->key[2] |= ((u64)fsp->h_u.tcp_ip4_spec.tos <<
+ TCAM_V4KEY2_TOS_SHIFT);
+ tp->key_mask[2] |= ((u64)fsp->m_u.tcp_ip4_spec.tos <<
+ TCAM_V4KEY2_TOS_SHIFT);
+ switch (fsp->flow_type) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ sport = be16_to_cpu(fsp->h_u.tcp_ip4_spec.psrc);
+ spm = be16_to_cpu(fsp->m_u.tcp_ip4_spec.psrc);
+ dport = be16_to_cpu(fsp->h_u.tcp_ip4_spec.pdst);
+ dpm = be16_to_cpu(fsp->m_u.tcp_ip4_spec.pdst);
+
+ tp->key[2] |= (((u64)sport << 16) | dport);
+ tp->key_mask[2] |= (((u64)spm << 16) | dpm);
+ niu_ethflow_to_l3proto(fsp->flow_type, &pid);
+ break;
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ spi = be32_to_cpu(fsp->h_u.ah_ip4_spec.spi);
+ spim = be32_to_cpu(fsp->m_u.ah_ip4_spec.spi);
+
+ tp->key[2] |= spi;
+ tp->key_mask[2] |= spim;
+ niu_ethflow_to_l3proto(fsp->flow_type, &pid);
+ break;
+ case IP_USER_FLOW:
+ spi = be32_to_cpu(fsp->h_u.usr_ip4_spec.l4_4_bytes);
+ spim = be32_to_cpu(fsp->m_u.usr_ip4_spec.l4_4_bytes);
+
+ tp->key[2] |= spi;
+ tp->key_mask[2] |= spim;
+ pid = fsp->h_u.usr_ip4_spec.proto;
+ break;
+ default:
+ break;
+ }
+
+ tp->key[2] |= ((u64)pid << TCAM_V4KEY2_PROTO_SHIFT);
+ if (pid) {
+ tp->key_mask[2] |= TCAM_V4KEY2_PROTO;
+ }
+}
+
+static int niu_add_ethtool_tcam_entry(struct niu *np,
+ struct ethtool_rxnfc *nfc)
+{
+ struct niu_parent *parent = np->parent;
+ struct niu_tcam_entry *tp;
+ struct ethtool_rx_flow_spec *fsp = &nfc->fs;
+ struct niu_rdc_tables *rdc_table = &parent->rdc_group_cfg[np->port];
+ int l2_rdc_table = rdc_table->first_table_num;
+ u16 idx;
+ u64 class;
+ unsigned long flags;
+ int err, ret;
+
+ ret = 0;
+
+ idx = nfc->fs.location;
+ if (idx >= tcam_get_size(np))
+ return -EINVAL;
+
+ if (fsp->flow_type == IP_USER_FLOW) {
+ int i;
+ int add_usr_cls = 0;
+ int ipv6 = 0;
+ struct ethtool_usrip4_spec *uspec = &fsp->h_u.usr_ip4_spec;
+ struct ethtool_usrip4_spec *umask = &fsp->m_u.usr_ip4_spec;
+
+ niu_lock_parent(np, flags);
+
+ for (i = 0; i < NIU_L3_PROG_CLS; i++) {
+ if (parent->l3_cls[i]) {
+ if (uspec->proto == parent->l3_cls_pid[i]) {
+ class = parent->l3_cls[i];
+ parent->l3_cls_refcnt[i]++;
+ add_usr_cls = 1;
+ break;
+ }
+ } else {
+ /* Program new user IP class */
+ switch (i) {
+ case 0:
+ class = CLASS_CODE_USER_PROG1;
+ break;
+ case 1:
+ class = CLASS_CODE_USER_PROG2;
+ break;
+ case 2:
+ class = CLASS_CODE_USER_PROG3;
+ break;
+ case 3:
+ class = CLASS_CODE_USER_PROG4;
+ break;
+ default:
+ break;
+ }
+ if (uspec->ip_ver == ETH_RX_NFC_IP6)
+ ipv6 = 1;
+ ret = tcam_user_ip_class_set(np, class, ipv6,
+ uspec->proto,
+ uspec->tos,
+ umask->tos);
+ if (ret)
+ goto out;
+
+ ret = tcam_user_ip_class_enable(np, class, 1);
+ if (ret)
+ goto out;
+ parent->l3_cls[i] = class;
+ parent->l3_cls_pid[i] = uspec->proto;
+ parent->l3_cls_refcnt[i]++;
+ add_usr_cls = 1;
+ break;
+ }
+ }
+ if (!add_usr_cls) {
+ netdev_info(np->dev, "niu%d: %s(): Could not find/insert class for pid %d\n",
+ parent->index, __func__, uspec->proto);
+ ret = -EINVAL;
+ goto out;
+ }
+ niu_unlock_parent(np, flags);
+ } else {
+ if (!niu_ethflow_to_class(fsp->flow_type, &class)) {
+ return -EINVAL;
+ }
+ }
+
+ niu_lock_parent(np, flags);
+
+ idx = tcam_get_index(np, idx);
+ tp = &parent->tcam[idx];
+
+ memset(tp, 0, sizeof(*tp));
+
+ /* fill in the tcam key and mask */
+ switch (fsp->flow_type) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ niu_get_tcamkey_from_ip4fs(fsp, tp, l2_rdc_table, class);
+ break;
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ /* Not yet implemented */
+ netdev_info(np->dev, "niu%d: In %s(): flow %d for IPv6 not implemented\n",
+ parent->index, __func__, fsp->flow_type);
+ ret = -EINVAL;
+ goto out;
+ case IP_USER_FLOW:
+ if (fsp->h_u.usr_ip4_spec.ip_ver == ETH_RX_NFC_IP4) {
+ niu_get_tcamkey_from_ip4fs(fsp, tp, l2_rdc_table,
+ class);
+ } else {
+ /* Not yet implemented */
+ netdev_info(np->dev, "niu%d: In %s(): usr flow for IPv6 not implemented\n",
+ parent->index, __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+ break;
+ default:
+ netdev_info(np->dev, "niu%d: In %s(): Unknown flow type %d\n",
+ parent->index, __func__, fsp->flow_type);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* fill in the assoc data */
+ if (fsp->ring_cookie == RX_CLS_FLOW_DISC) {
+ tp->assoc_data = TCAM_ASSOCDATA_DISC;
+ } else {
+ if (fsp->ring_cookie >= np->num_rx_rings) {
+ netdev_info(np->dev, "niu%d: In %s(): Invalid RX ring %lld\n",
+ parent->index, __func__,
+ (long long)fsp->ring_cookie);
+ ret = -EINVAL;
+ goto out;
+ }
+ tp->assoc_data = (TCAM_ASSOCDATA_TRES_USE_OFFSET |
+ (fsp->ring_cookie <<
+ TCAM_ASSOCDATA_OFFSET_SHIFT));
+ }
+
+ err = tcam_write(np, idx, tp->key, tp->key_mask);
+ if (err) {
+ ret = -EINVAL;
+ goto out;
+ }
+ err = tcam_assoc_write(np, idx, tp->assoc_data);
+ if (err) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* validate the entry */
+ tp->valid = 1;
+ np->clas.tcam_valid_entries++;
+out:
+ niu_unlock_parent(np, flags);
+
+ return ret;
+}
+
+static int niu_del_ethtool_tcam_entry(struct niu *np, u32 loc)
+{
+ struct niu_parent *parent = np->parent;
+ struct niu_tcam_entry *tp;
+ u16 idx;
+ unsigned long flags;
+ u64 class;
+ int ret = 0;
+
+ if (loc >= tcam_get_size(np))
+ return -EINVAL;
+
+ niu_lock_parent(np, flags);
+
+ idx = tcam_get_index(np, loc);
+ tp = &parent->tcam[idx];
+
+ /* if the entry is of a user defined class, then update*/
+ class = (tp->key[0] & TCAM_V4KEY0_CLASS_CODE) >>
+ TCAM_V4KEY0_CLASS_CODE_SHIFT;
+
+ if (class >= CLASS_CODE_USER_PROG1 && class <= CLASS_CODE_USER_PROG4) {
+ int i;
+ for (i = 0; i < NIU_L3_PROG_CLS; i++) {
+ if (parent->l3_cls[i] == class) {
+ parent->l3_cls_refcnt[i]--;
+ if (!parent->l3_cls_refcnt[i]) {
+ /* disable class */
+ ret = tcam_user_ip_class_enable(np,
+ class,
+ 0);
+ if (ret)
+ goto out;
+ parent->l3_cls[i] = 0;
+ parent->l3_cls_pid[i] = 0;
+ }
+ break;
+ }
+ }
+ if (i == NIU_L3_PROG_CLS) {
+ netdev_info(np->dev, "niu%d: In %s(): Usr class 0x%llx not found\n",
+ parent->index, __func__,
+ (unsigned long long)class);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ ret = tcam_flush(np, idx);
+ if (ret)
+ goto out;
+
+ /* invalidate the entry */
+ tp->valid = 0;
+ np->clas.tcam_valid_entries--;
+out:
+ niu_unlock_parent(np, flags);
+
+ return ret;
+}
+
+static int niu_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ struct niu *np = netdev_priv(dev);
+ int ret = 0;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXFH:
+ ret = niu_set_hash_opts(np, cmd);
+ break;
+ case ETHTOOL_SRXCLSRLINS:
+ ret = niu_add_ethtool_tcam_entry(np, cmd);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ ret = niu_del_ethtool_tcam_entry(np, cmd->fs.location);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
static const struct {
const char string[ETH_GSTRING_LEN];
} niu_xmac_stat_keys[] = {
}
}
-static int niu_get_stats_count(struct net_device *dev)
+static int niu_get_sset_count(struct net_device *dev, int stringset)
{
struct niu *np = netdev_priv(dev);
+ if (stringset != ETH_SS_STATS)
+ return -EINVAL;
+
return ((np->flags & NIU_FLAGS_XMAC ?
NUM_XMAC_STAT_KEYS :
NUM_BMAC_STAT_KEYS) +
for (i = 0; i < np->num_rx_rings; i++) {
struct rx_ring_info *rp = &np->rx_rings[i];
+ niu_sync_rx_discard_stats(np, rp, 0);
+
data[0] = rp->rx_channel;
data[1] = rp->rx_packets;
data[2] = rp->rx_bytes;
.get_link = ethtool_op_get_link,
.get_msglevel = niu_get_msglevel,
.set_msglevel = niu_set_msglevel,
+ .nway_reset = niu_nway_reset,
.get_eeprom_len = niu_get_eeprom_len,
.get_eeprom = niu_get_eeprom,
.get_settings = niu_get_settings,
.set_settings = niu_set_settings,
.get_strings = niu_get_strings,
- .get_stats_count = niu_get_stats_count,
+ .get_sset_count = niu_get_sset_count,
.get_ethtool_stats = niu_get_ethtool_stats,
.phys_id = niu_phys_id,
- .get_rxhash = niu_get_hash_opts,
- .set_rxhash = niu_set_hash_opts,
+ .get_rxnfc = niu_get_nfc,
+ .set_rxnfc = niu_set_nfc,
};
static int niu_ldg_assign_ldn(struct niu *np, struct niu_parent *parent,
* won't get any interrupts and that's painful to debug.
*/
if (nr64(LDG_NUM(ldn)) != ldg) {
- dev_err(np->device, PFX "Port %u, mis-matched "
- "LDG assignment "
- "for ldn %d, should be %d is %llu\n",
+ dev_err(np->device, "Port %u, mis-matched LDG assignment for ldn %d, should be %d is %llu\n",
np->port, ldn, ldg,
(unsigned long long) nr64(LDG_NUM(ldn)));
return -EINVAL;
break;
} while (limit--);
if (!(frame & ESPC_PIO_STAT_READ_END)) {
- dev_err(np->device, PFX "EEPROM read timeout frame[%llx]\n",
+ dev_err(np->device, "EEPROM read timeout frame[%llx]\n",
(unsigned long long) frame);
return -ENODEV;
}
break;
} while (limit--);
if (!(frame & ESPC_PIO_STAT_READ_END)) {
- dev_err(np->device, PFX "EEPROM read timeout frame[%llx]\n",
+ dev_err(np->device, "EEPROM read timeout frame[%llx]\n",
(unsigned long long) frame);
return -ENODEV;
}
int i;
for (i = 0; i < len - 5; i++) {
- if (!strncmp(s + i, "FCode ", 5))
+ if (!strncmp(s + i, "FCode ", 6))
break;
}
if (i >= len - 5)
s += i + 5;
sscanf(s, "%d.%d", &vpd->fcode_major, &vpd->fcode_minor);
- niudbg(PROBE, "VPD_SCAN: FCODE major(%d) minor(%d)\n",
- vpd->fcode_major, vpd->fcode_minor);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "VPD_SCAN: FCODE major(%d) minor(%d)\n",
+ vpd->fcode_major, vpd->fcode_minor);
if (vpd->fcode_major > NIU_VPD_MIN_MAJOR ||
(vpd->fcode_major == NIU_VPD_MIN_MAJOR &&
vpd->fcode_minor >= NIU_VPD_MIN_MINOR))
#define FOUND_MASK_PHY 0x00000020
#define FOUND_MASK_ALL 0x0000003f
- niudbg(PROBE, "VPD_SCAN: start[%x] end[%x]\n",
- start, end);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "VPD_SCAN: start[%x] end[%x]\n", start, end);
while (start < end) {
int len, err, instance, type, prop_len;
char namebuf[64];
}
if (max_len && prop_len > max_len) {
- dev_err(np->device, PFX "Property '%s' length (%d) is "
- "too long.\n", namebuf, prop_len);
+ dev_err(np->device, "Property '%s' length (%d) is too long\n", namebuf, prop_len);
return -EINVAL;
}
u32 off = start + 5 + err;
int i;
- niudbg(PROBE, "VPD_SCAN: Reading in property [%s] "
- "len[%d]\n", namebuf, prop_len);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "VPD_SCAN: Reading in property [%s] len[%d]\n",
+ namebuf, prop_len);
for (i = 0; i < prop_len; i++)
*prop_buf++ = niu_pci_eeprom_read(np, off + i);
}
u8 val8;
if (!is_valid_ether_addr(&vpd->local_mac[0])) {
- dev_err(np->device, PFX "VPD MAC invalid, "
- "falling back to SPROM.\n");
+ dev_err(np->device, "VPD MAC invalid, falling back to SPROM\n");
np->flags &= ~NIU_FLAGS_VPD_VALID;
return;
np->flags &= ~NIU_FLAGS_10G;
}
if (np->flags & NIU_FLAGS_10G)
- np->mac_xcvr = MAC_XCVR_XPCS;
+ np->mac_xcvr = MAC_XCVR_XPCS;
} else if (!strcmp(np->vpd.model, NIU_FOXXY_MDL_STR)) {
np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
NIU_FLAGS_HOTPLUG_PHY);
} else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
- dev_err(np->device, PFX "Illegal phy string [%s].\n",
+ dev_err(np->device, "Illegal phy string [%s]\n",
np->vpd.phy_type);
- dev_err(np->device, PFX "Falling back to SPROM.\n");
+ dev_err(np->device, "Falling back to SPROM\n");
np->flags &= ~NIU_FLAGS_VPD_VALID;
return;
}
np->eeprom_len = len;
- niudbg(PROBE, "SPROM: Image size %llu\n", (unsigned long long) val);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "SPROM: Image size %llu\n", (unsigned long long)val);
sum = 0;
for (i = 0; i < len; i++) {
sum += (val >> 16) & 0xff;
sum += (val >> 24) & 0xff;
}
- niudbg(PROBE, "SPROM: Checksum %x\n", (int)(sum & 0xff));
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "SPROM: Checksum %x\n", (int)(sum & 0xff));
if ((sum & 0xff) != 0xab) {
- dev_err(np->device, PFX "Bad SPROM checksum "
- "(%x, should be 0xab)\n", (int) (sum & 0xff));
+ dev_err(np->device, "Bad SPROM checksum (%x, should be 0xab)\n", (int)(sum & 0xff));
return -EINVAL;
}
ESPC_PHY_TYPE_PORT3_SHIFT;
break;
default:
- dev_err(np->device, PFX "Bogus port number %u\n",
+ dev_err(np->device, "Bogus port number %u\n",
np->port);
return -EINVAL;
}
- niudbg(PROBE, "SPROM: PHY type %x\n", val8);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "SPROM: PHY type %x\n", val8);
switch (val8) {
case ESPC_PHY_TYPE_1G_COPPER:
break;
default:
- dev_err(np->device, PFX "Bogus SPROM phy type %u\n", val8);
+ dev_err(np->device, "Bogus SPROM phy type %u\n", val8);
return -EINVAL;
}
val = nr64(ESPC_MAC_ADDR0);
- niudbg(PROBE, "SPROM: MAC_ADDR0[%08llx]\n",
- (unsigned long long) val);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "SPROM: MAC_ADDR0[%08llx]\n", (unsigned long long)val);
dev->perm_addr[0] = (val >> 0) & 0xff;
dev->perm_addr[1] = (val >> 8) & 0xff;
dev->perm_addr[2] = (val >> 16) & 0xff;
dev->perm_addr[3] = (val >> 24) & 0xff;
val = nr64(ESPC_MAC_ADDR1);
- niudbg(PROBE, "SPROM: MAC_ADDR1[%08llx]\n",
- (unsigned long long) val);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "SPROM: MAC_ADDR1[%08llx]\n", (unsigned long long)val);
dev->perm_addr[4] = (val >> 0) & 0xff;
dev->perm_addr[5] = (val >> 8) & 0xff;
if (!is_valid_ether_addr(&dev->perm_addr[0])) {
- dev_err(np->device, PFX "SPROM MAC address invalid\n");
- dev_err(np->device, PFX "[ \n");
- for (i = 0; i < 6; i++)
- printk("%02x ", dev->perm_addr[i]);
- printk("]\n");
+ dev_err(np->device, "SPROM MAC address invalid [ %pM ]\n",
+ dev->perm_addr);
return -EINVAL;
}
memcpy(dev->dev_addr, dev->perm_addr, dev->addr_len);
val = nr64(ESPC_MOD_STR_LEN);
- niudbg(PROBE, "SPROM: MOD_STR_LEN[%llu]\n",
- (unsigned long long) val);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "SPROM: MOD_STR_LEN[%llu]\n", (unsigned long long)val);
if (val >= 8 * 4)
return -EINVAL;
np->vpd.model[val] = '\0';
val = nr64(ESPC_BD_MOD_STR_LEN);
- niudbg(PROBE, "SPROM: BD_MOD_STR_LEN[%llu]\n",
- (unsigned long long) val);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "SPROM: BD_MOD_STR_LEN[%llu]\n", (unsigned long long)val);
if (val >= 4 * 4)
return -EINVAL;
np->vpd.mac_num =
nr64(ESPC_NUM_PORTS_MACS) & ESPC_NUM_PORTS_MACS_VAL;
- niudbg(PROBE, "SPROM: NUM_PORTS_MACS[%d]\n",
- np->vpd.mac_num);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "SPROM: NUM_PORTS_MACS[%d]\n", np->vpd.mac_num);
return 0;
}
}
}
- niudbg(PROBE, "niu_get_and_validate_port: port[%d] num_ports[%d]\n",
- np->port, parent->num_ports);
if (np->port >= parent->num_ports)
return -ENODEV;
pr_info("niu%d: Found PHY %08x type %s at phy_port %u\n",
parent->index, id,
- (type == PHY_TYPE_PMA_PMD ?
- "PMA/PMD" :
- (type == PHY_TYPE_PCS ?
- "PCS" : "MII")),
+ type == PHY_TYPE_PMA_PMD ? "PMA/PMD" :
+ type == PHY_TYPE_PCS ? "PCS" : "MII",
phy_port);
if (p->cur[type] >= NIU_MAX_PORTS) {
- printk(KERN_ERR PFX "Too many PHY ports.\n");
+ pr_err("Too many PHY ports\n");
return -EINVAL;
}
idx = p->cur[type];
parent->rxchan_per_port[i] = (16 / num_ports);
parent->txchan_per_port[i] = (16 / num_ports);
- pr_info(PFX "niu%d: Port %u [%u RX chans] "
- "[%u TX chans]\n",
+ pr_info("niu%d: Port %u [%u RX chans] [%u TX chans]\n",
parent->index, i,
parent->rxchan_per_port[i],
parent->txchan_per_port[i]);
parent->rxchan_per_port[i] = rx_chans_per_1g;
parent->txchan_per_port[i] = tx_chans_per_1g;
}
- pr_info(PFX "niu%d: Port %u [%u RX chans] "
- "[%u TX chans]\n",
+ pr_info("niu%d: Port %u [%u RX chans] [%u TX chans]\n",
parent->index, i,
parent->rxchan_per_port[i],
parent->txchan_per_port[i]);
}
if (tot_rx > NIU_NUM_RXCHAN) {
- printk(KERN_ERR PFX "niu%d: Too many RX channels (%d), "
- "resetting to one per port.\n",
+ pr_err("niu%d: Too many RX channels (%d), resetting to one per port\n",
parent->index, tot_rx);
for (i = 0; i < num_ports; i++)
parent->rxchan_per_port[i] = 1;
}
if (tot_tx > NIU_NUM_TXCHAN) {
- printk(KERN_ERR PFX "niu%d: Too many TX channels (%d), "
- "resetting to one per port.\n",
+ pr_err("niu%d: Too many TX channels (%d), resetting to one per port\n",
parent->index, tot_tx);
for (i = 0; i < num_ports; i++)
parent->txchan_per_port[i] = 1;
}
if (tot_rx < NIU_NUM_RXCHAN || tot_tx < NIU_NUM_TXCHAN) {
- printk(KERN_WARNING PFX "niu%d: Driver bug, wasted channels, "
- "RX[%d] TX[%d]\n",
- parent->index, tot_rx, tot_tx);
+ pr_warning("niu%d: Driver bug, wasted channels, RX[%d] TX[%d]\n",
+ parent->index, tot_rx, tot_tx);
}
}
struct rdc_table *rt = &tp->tables[grp];
int slot;
- pr_info(PFX "niu%d: Port %d RDC tbl(%d) [ ",
+ pr_info("niu%d: Port %d RDC tbl(%d) [ ",
parent->index, i, tp->first_table_num + grp);
for (slot = 0; slot < NIU_RDC_TABLE_SLOTS; slot++) {
rt->rxdma_channel[slot] =
rdc_channel_base + this_channel_offset;
- printk("%d ", rt->rxdma_channel[slot]);
+ pr_cont("%d ", rt->rxdma_channel[slot]);
if (++this_channel_offset == num_channels)
this_channel_offset = 0;
}
- printk("]\n");
+ pr_cont("]\n");
}
parent->rdc_default[i] = rdc_channel_base;
break;
default:
- printk(KERN_ERR PFX "Unsupported port config "
- "10G[%d] 1G[%d]\n",
+ pr_err("Unsupported port config 10G[%d] 1G[%d]\n",
num_10g, num_1g);
return -EINVAL;
}
return 0;
unknown_vg_1g_port:
- printk(KERN_ERR PFX "Cannot identify platform type, 1gport=%d\n",
- lowest_1g);
+ pr_err("Cannot identify platform type, 1gport=%d\n", lowest_1g);
return -EINVAL;
}
struct niu_parent *parent = np->parent;
int err, i;
- niudbg(PROBE, "niu_probe_ports(): port_phy[%08x]\n",
- parent->port_phy);
-
if (parent->port_phy == PORT_PHY_UNKNOWN) {
err = walk_phys(np, parent);
if (err)
{
struct niu_classifier *cp = &np->clas;
- niudbg(PROBE, "niu_classifier_swstate_init: num_tcam(%d)\n",
- np->parent->tcam_num_entries);
-
- cp->tcam_index = (u16) np->port;
+ cp->tcam_top = (u16) np->port;
+ cp->tcam_sz = np->parent->tcam_num_entries / np->parent->num_ports;
cp->h1_init = 0xffffffff;
cp->h2_init = 0xffff;
ADVERTISED_10000baseT_Full |
ADVERTISED_Autoneg);
lp->speed = lp->active_speed = SPEED_INVALID;
- lp->duplex = lp->active_duplex = DUPLEX_INVALID;
+ lp->duplex = DUPLEX_FULL;
+ lp->active_duplex = DUPLEX_INVALID;
+ lp->autoneg = 1;
#if 0
lp->loopback_mode = LOOPBACK_MAC;
lp->active_speed = SPEED_10000;
break;
default:
- dev_err(np->device, PFX "Port %u is invalid, cannot "
- "compute MAC block offset.\n", np->port);
+ dev_err(np->device, "Port %u is invalid, cannot compute MAC block offset\n", np->port);
return -EINVAL;
}
phy_type = of_get_property(dp, "phy-type", &prop_len);
if (!phy_type) {
- dev_err(np->device, PFX "%s: OF node lacks "
- "phy-type property\n",
- dp->full_name);
+ netdev_err(dev, "%s: OF node lacks phy-type property\n",
+ dp->full_name);
return -EINVAL;
}
strcpy(np->vpd.phy_type, phy_type);
if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
- dev_err(np->device, PFX "%s: Illegal phy string [%s].\n",
- dp->full_name, np->vpd.phy_type);
+ netdev_err(dev, "%s: Illegal phy string [%s]\n",
+ dp->full_name, np->vpd.phy_type);
return -EINVAL;
}
mac_addr = of_get_property(dp, "local-mac-address", &prop_len);
if (!mac_addr) {
- dev_err(np->device, PFX "%s: OF node lacks "
- "local-mac-address property\n",
- dp->full_name);
+ netdev_err(dev, "%s: OF node lacks local-mac-address property\n",
+ dp->full_name);
return -EINVAL;
}
if (prop_len != dev->addr_len) {
- dev_err(np->device, PFX "%s: OF MAC address prop len (%d) "
- "is wrong.\n",
- dp->full_name, prop_len);
+ netdev_err(dev, "%s: OF MAC address prop len (%d) is wrong\n",
+ dp->full_name, prop_len);
}
memcpy(dev->perm_addr, mac_addr, dev->addr_len);
if (!is_valid_ether_addr(&dev->perm_addr[0])) {
- int i;
-
- dev_err(np->device, PFX "%s: OF MAC address is invalid\n",
- dp->full_name);
- dev_err(np->device, PFX "%s: [ \n",
- dp->full_name);
- for (i = 0; i < 6; i++)
- printk("%02x ", dev->perm_addr[i]);
- printk("]\n");
+ netdev_err(dev, "%s: OF MAC address is invalid\n",
+ dp->full_name);
+ netdev_err(dev, "%s: [ %pM ]\n", dp->full_name, dev->perm_addr);
return -EINVAL;
}
if (model)
strcpy(np->vpd.model, model);
+ if (of_find_property(dp, "hot-swappable-phy", &prop_len)) {
+ np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
+ NIU_FLAGS_HOTPLUG_PHY);
+ }
+
return 0;
#else
return -EINVAL;
nw64(ESPC_PIO_EN, ESPC_PIO_EN_ENABLE);
offset = niu_pci_vpd_offset(np);
- niudbg(PROBE, "niu_get_invariants: VPD offset [%08x]\n",
- offset);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "%s() VPD offset [%08x]\n", __func__, offset);
if (offset)
niu_pci_vpd_fetch(np, offset);
nw64(ESPC_PIO_EN, 0);
struct niu_parent *p;
int i;
- niudbg(PROBE, "niu_new_parent: Creating new parent.\n");
-
plat_dev = platform_device_register_simple("niu", niu_parent_index,
NULL, 0);
- if (!plat_dev)
+ if (IS_ERR(plat_dev))
return NULL;
for (i = 0; attr_name(niu_parent_attributes[i]); i++) {
struct niu_parent *p, *tmp;
int port = np->port;
- niudbg(PROBE, "niu_get_parent: platform_type[%u] port[%u]\n",
- ptype, port);
-
mutex_lock(&niu_parent_lock);
p = NULL;
list_for_each_entry(tmp, &niu_parent_list, list) {
BUG_ON(!p || p->ports[port] != np);
- niudbg(PROBE, "niu_put_parent: port[%u]\n", port);
+ netif_printk(np, probe, KERN_DEBUG, np->dev,
+ "%s() port[%u]\n", __func__, port);
sprintf(port_name, "port%d", port);
static void niu_pci_unmap_page(struct device *dev, u64 dma_address,
size_t size, enum dma_data_direction direction)
{
- return dma_unmap_page(dev, dma_address, size, direction);
+ dma_unmap_page(dev, dma_address, size, direction);
}
static u64 niu_pci_map_single(struct device *dev, void *cpu_addr,
dev = alloc_etherdev_mq(sizeof(struct niu), NIU_NUM_TXCHAN);
if (!dev) {
- dev_err(gen_dev, PFX "Etherdev alloc failed, aborting.\n");
+ dev_err(gen_dev, "Etherdev alloc failed, aborting\n");
return NULL;
}
err = pci_enable_device(pdev);
if (err) {
- dev_err(&pdev->dev, PFX "Cannot enable PCI device, "
- "aborting.\n");
+ dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
return err;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
- dev_err(&pdev->dev, PFX "Cannot find proper PCI device "
- "base addresses, aborting.\n");
+ dev_err(&pdev->dev, "Cannot find proper PCI device base addresses, aborting\n");
err = -ENODEV;
goto err_out_disable_pdev;
}
err = pci_request_regions(pdev, DRV_MODULE_NAME);
if (err) {
- dev_err(&pdev->dev, PFX "Cannot obtain PCI resources, "
- "aborting.\n");
+ dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
goto err_out_disable_pdev;
}
pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
if (pos <= 0) {
- dev_err(&pdev->dev, PFX "Cannot find PCI Express capability, "
- "aborting.\n");
+ dev_err(&pdev->dev, "Cannot find PCI Express capability, aborting\n");
goto err_out_free_res;
}
PCI_EXP_DEVCTL_RELAX_EN);
pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16);
- dma_mask = DMA_44BIT_MASK;
+ dma_mask = DMA_BIT_MASK(44);
err = pci_set_dma_mask(pdev, dma_mask);
if (!err) {
dev->features |= NETIF_F_HIGHDMA;
err = pci_set_consistent_dma_mask(pdev, dma_mask);
if (err) {
- dev_err(&pdev->dev, PFX "Unable to obtain 44 bit "
- "DMA for consistent allocations, "
- "aborting.\n");
+ dev_err(&pdev->dev, "Unable to obtain 44 bit DMA for consistent allocations, aborting\n");
goto err_out_release_parent;
}
}
- if (err || dma_mask == DMA_32BIT_MASK) {
- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err || dma_mask == DMA_BIT_MASK(32)) {
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (err) {
- dev_err(&pdev->dev, PFX "No usable DMA configuration, "
- "aborting.\n");
+ dev_err(&pdev->dev, "No usable DMA configuration, aborting\n");
goto err_out_release_parent;
}
}
np->regs = pci_ioremap_bar(pdev, 0);
if (!np->regs) {
- dev_err(&pdev->dev, PFX "Cannot map device registers, "
- "aborting.\n");
+ dev_err(&pdev->dev, "Cannot map device registers, aborting\n");
err = -ENOMEM;
goto err_out_release_parent;
}
err = niu_get_invariants(np);
if (err) {
if (err != -ENODEV)
- dev_err(&pdev->dev, PFX "Problem fetching invariants "
- "of chip, aborting.\n");
+ dev_err(&pdev->dev, "Problem fetching invariants of chip, aborting\n");
goto err_out_iounmap;
}
err = register_netdev(dev);
if (err) {
- dev_err(&pdev->dev, PFX "Cannot register net device, "
- "aborting.\n");
+ dev_err(&pdev->dev, "Cannot register net device, aborting\n");
goto err_out_iounmap;
}
.unmap_single = niu_phys_unmap_single,
};
-static unsigned long res_size(struct resource *r)
-{
- return r->end - r->start + 1UL;
-}
-
static int __devinit niu_of_probe(struct of_device *op,
const struct of_device_id *match)
{
reg = of_get_property(op->node, "reg", NULL);
if (!reg) {
- dev_err(&op->dev, PFX "%s: No 'reg' property, aborting.\n",
+ dev_err(&op->dev, "%s: No 'reg' property, aborting\n",
op->node->full_name);
return -ENODEV;
}
dev->features |= (NETIF_F_SG | NETIF_F_HW_CSUM);
np->regs = of_ioremap(&op->resource[1], 0,
- res_size(&op->resource[1]),
+ resource_size(&op->resource[1]),
"niu regs");
if (!np->regs) {
- dev_err(&op->dev, PFX "Cannot map device registers, "
- "aborting.\n");
+ dev_err(&op->dev, "Cannot map device registers, aborting\n");
err = -ENOMEM;
goto err_out_release_parent;
}
np->vir_regs_1 = of_ioremap(&op->resource[2], 0,
- res_size(&op->resource[2]),
+ resource_size(&op->resource[2]),
"niu vregs-1");
if (!np->vir_regs_1) {
- dev_err(&op->dev, PFX "Cannot map device vir registers 1, "
- "aborting.\n");
+ dev_err(&op->dev, "Cannot map device vir registers 1, aborting\n");
err = -ENOMEM;
goto err_out_iounmap;
}
np->vir_regs_2 = of_ioremap(&op->resource[3], 0,
- res_size(&op->resource[3]),
+ resource_size(&op->resource[3]),
"niu vregs-2");
if (!np->vir_regs_2) {
- dev_err(&op->dev, PFX "Cannot map device vir registers 2, "
- "aborting.\n");
+ dev_err(&op->dev, "Cannot map device vir registers 2, aborting\n");
err = -ENOMEM;
goto err_out_iounmap;
}
err = niu_get_invariants(np);
if (err) {
if (err != -ENODEV)
- dev_err(&op->dev, PFX "Problem fetching invariants "
- "of chip, aborting.\n");
+ dev_err(&op->dev, "Problem fetching invariants of chip, aborting\n");
goto err_out_iounmap;
}
err = register_netdev(dev);
if (err) {
- dev_err(&op->dev, PFX "Cannot register net device, "
- "aborting.\n");
+ dev_err(&op->dev, "Cannot register net device, aborting\n");
goto err_out_iounmap;
}
err_out_iounmap:
if (np->vir_regs_1) {
of_iounmap(&op->resource[2], np->vir_regs_1,
- res_size(&op->resource[2]));
+ resource_size(&op->resource[2]));
np->vir_regs_1 = NULL;
}
if (np->vir_regs_2) {
of_iounmap(&op->resource[3], np->vir_regs_2,
- res_size(&op->resource[3]));
+ resource_size(&op->resource[3]));
np->vir_regs_2 = NULL;
}
if (np->regs) {
of_iounmap(&op->resource[1], np->regs,
- res_size(&op->resource[1]));
+ resource_size(&op->resource[1]));
np->regs = NULL;
}
if (np->vir_regs_1) {
of_iounmap(&op->resource[2], np->vir_regs_1,
- res_size(&op->resource[2]));
+ resource_size(&op->resource[2]));
np->vir_regs_1 = NULL;
}
if (np->vir_regs_2) {
of_iounmap(&op->resource[3], np->vir_regs_2,
- res_size(&op->resource[3]));
+ resource_size(&op->resource[3]));
np->vir_regs_2 = NULL;
}
if (np->regs) {
of_iounmap(&op->resource[1], np->regs,
- res_size(&op->resource[1]));
+ resource_size(&op->resource[1]));
np->regs = NULL;
}