aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/via
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/via')
-rw-r--r--drivers/net/ethernet/via/Kconfig7
-rw-r--r--drivers/net/ethernet/via/via-rhine.c645
-rw-r--r--drivers/net/ethernet/via/via-velocity.c576
-rw-r--r--drivers/net/ethernet/via/via-velocity.h8
4 files changed, 785 insertions, 451 deletions
diff --git a/drivers/net/ethernet/via/Kconfig b/drivers/net/ethernet/via/Kconfig
index 68a9ba66feb..f66ddaee0c8 100644
--- a/drivers/net/ethernet/via/Kconfig
+++ b/drivers/net/ethernet/via/Kconfig
@@ -5,7 +5,6 @@
config NET_VENDOR_VIA
bool "VIA devices"
default y
- depends on PCI
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -20,9 +19,8 @@ if NET_VENDOR_VIA
config VIA_RHINE
tristate "VIA Rhine support"
- depends on PCI
+ depends on (PCI || USE_OF)
select CRC32
- select NET_CORE
select MII
---help---
If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A),
@@ -45,10 +43,9 @@ config VIA_RHINE_MMIO
config VIA_VELOCITY
tristate "VIA Velocity support"
- depends on PCI
+ depends on (PCI || USE_OF)
select CRC32
select CRC_CCITT
- select NET_CORE
select MII
---help---
If you have a VIA "Velocity" based network card say Y here.
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 10b18eb63d2..2d72f96a9e2 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -32,7 +32,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define DRV_NAME "via-rhine"
-#define DRV_VERSION "1.5.0"
+#define DRV_VERSION "1.5.1"
#define DRV_RELDATE "2010-10-09"
#include <linux/types.h>
@@ -94,6 +94,10 @@ static const int multicast_filter_limit = 32;
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -113,16 +117,9 @@ static const int multicast_filter_limit = 32;
#include <linux/dmi.h>
/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
"v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker";
-/* This driver was written to use PCI memory space. Some early versions
- of the Rhine may only work correctly with I/O space accesses. */
-#ifdef CONFIG_VIA_RHINE_MMIO
-#define USE_MMIO
-#else
-#endif
-
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
MODULE_LICENSE("GPL");
@@ -260,6 +257,12 @@ enum rhine_quirks {
rq6patterns = 0x0040, /* 6 instead of 4 patterns for WOL */
rqStatusWBRace = 0x0080, /* Tx Status Writeback Error possible */
rqRhineI = 0x0100, /* See comment below */
+ rqIntPHY = 0x0200, /* Integrated PHY */
+ rqMgmt = 0x0400, /* Management adapter */
+ rqNeedEnMMIO = 0x0800, /* Whether the core needs to be
+ * switched from PIO mode to MMIO
+ * (only applies to PCI)
+ */
};
/*
* rqRhineI: VT86C100A (aka Rhine-I) uses different bits to enable
@@ -279,6 +282,15 @@ static DEFINE_PCI_DEVICE_TABLE(rhine_pci_tbl) = {
};
MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);
+/* OpenFirmware identifiers for platform-bus devices
+ * The .data field is currently only used to store quirks
+ */
+static u32 vt8500_quirks = rqWOL | rqForceReset | rq6patterns;
+static struct of_device_id rhine_of_tbl[] = {
+ { .compatible = "via,vt8500-rhine", .data = &vt8500_quirks },
+ { } /* terminate list */
+};
+MODULE_DEVICE_TABLE(of, rhine_of_tbl);
/* Offsets to the device registers. */
enum register_offsets {
@@ -338,13 +350,11 @@ enum bcr1_bits {
BCR1_MED1=0x80, /* for VT6102 */
};
-#ifdef USE_MMIO
/* Registers we check that mmio and reg are the same. */
static const int mmio_verify_registers[] = {
RxConfig, TxConfig, IntrEnable, ConfigA, ConfigB, ConfigC, ConfigD,
0
};
-#endif
/* Bits in the interrupt status/mask registers. */
enum intr_status_bits {
@@ -417,6 +427,12 @@ enum chip_cmd_bits {
Cmd1NoTxPoll=0x08, Cmd1Reset=0x80,
};
+struct rhine_stats {
+ u64 packets;
+ u64 bytes;
+ struct u64_stats_sync syncp;
+};
+
struct rhine_private {
/* Bit mask for configured VLAN ids */
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
@@ -440,7 +456,7 @@ struct rhine_private {
unsigned char *tx_bufs;
dma_addr_t tx_bufs_dma;
- struct pci_dev *pdev;
+ int irq;
long pioaddr;
struct net_device *dev;
struct napi_struct napi;
@@ -458,6 +474,8 @@ struct rhine_private {
unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
unsigned int cur_tx, dirty_tx;
unsigned int rx_buf_sz; /* Based on MTU+slack. */
+ struct rhine_stats rx_stats;
+ struct rhine_stats tx_stats;
u8 wolopts;
u8 tx_thresh, rx_thresh;
@@ -495,38 +513,43 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance);
static void rhine_tx(struct net_device *dev);
static int rhine_rx(struct net_device *dev, int limit);
static void rhine_set_rx_mode(struct net_device *dev);
-static struct net_device_stats *rhine_get_stats(struct net_device *dev);
+static struct rtnl_link_stats64 *rhine_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats);
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static const struct ethtool_ops netdev_ethtool_ops;
static int rhine_close(struct net_device *dev);
-static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid);
-static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
+static int rhine_vlan_rx_add_vid(struct net_device *dev,
+ __be16 proto, u16 vid);
+static int rhine_vlan_rx_kill_vid(struct net_device *dev,
+ __be16 proto, u16 vid);
static void rhine_restart_tx(struct net_device *dev);
-static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool high)
+static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool low)
{
void __iomem *ioaddr = rp->base;
int i;
for (i = 0; i < 1024; i++) {
- if (high ^ !!(ioread8(ioaddr + reg) & mask))
+ bool has_mask_bits = !!(ioread8(ioaddr + reg) & mask);
+
+ if (low ^ has_mask_bits)
break;
udelay(10);
}
if (i > 64) {
netif_dbg(rp, hw, rp->dev, "%s bit wait (%02x/%02x) cycle "
- "count: %04d\n", high ? "high" : "low", reg, mask, i);
+ "count: %04d\n", low ? "low" : "high", reg, mask, i);
}
}
static void rhine_wait_bit_high(struct rhine_private *rp, u8 reg, u8 mask)
{
- rhine_wait_bit(rp, reg, mask, true);
+ rhine_wait_bit(rp, reg, mask, false);
}
static void rhine_wait_bit_low(struct rhine_private *rp, u8 reg, u8 mask)
{
- rhine_wait_bit(rp, reg, mask, false);
+ rhine_wait_bit(rp, reg, mask, true);
}
static u32 rhine_get_events(struct rhine_private *rp)
@@ -636,26 +659,52 @@ static void rhine_chip_reset(struct net_device *dev)
"failed" : "succeeded");
}
-#ifdef USE_MMIO
static void enable_mmio(long pioaddr, u32 quirks)
{
int n;
- if (quirks & rqRhineI) {
- /* More recent docs say that this bit is reserved ... */
- n = inb(pioaddr + ConfigA) | 0x20;
- outb(n, pioaddr + ConfigA);
- } else {
- n = inb(pioaddr + ConfigD) | 0x80;
- outb(n, pioaddr + ConfigD);
+
+ if (quirks & rqNeedEnMMIO) {
+ if (quirks & rqRhineI) {
+ /* More recent docs say that this bit is reserved */
+ n = inb(pioaddr + ConfigA) | 0x20;
+ outb(n, pioaddr + ConfigA);
+ } else {
+ n = inb(pioaddr + ConfigD) | 0x80;
+ outb(n, pioaddr + ConfigD);
+ }
}
}
-#endif
+
+static inline int verify_mmio(struct device *hwdev,
+ long pioaddr,
+ void __iomem *ioaddr,
+ u32 quirks)
+{
+ if (quirks & rqNeedEnMMIO) {
+ int i = 0;
+
+ /* Check that selected MMIO registers match the PIO ones */
+ while (mmio_verify_registers[i]) {
+ int reg = mmio_verify_registers[i++];
+ unsigned char a = inb(pioaddr+reg);
+ unsigned char b = readb(ioaddr+reg);
+
+ if (a != b) {
+ dev_err(hwdev,
+ "MMIO do not match PIO [%02x] (%02x != %02x)\n",
+ reg, a, b);
+ return -EIO;
+ }
+ }
+ }
+ return 0;
+}
/*
* Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM
* (plus 0x6C for Rhine-I/II)
*/
-static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
+static void rhine_reload_eeprom(long pioaddr, struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
@@ -669,14 +718,12 @@ static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
if (i > 512)
pr_info("%4d cycles used @ %s:%d\n", i, __func__, __LINE__);
-#ifdef USE_MMIO
/*
* Reloading from EEPROM overwrites ConfigA-D, so we must re-enable
* MMIO. If reloading EEPROM was done first this could be avoided, but
* it is not known if that still works with the "win98-reboot" problem.
*/
enable_mmio(pioaddr, rp->quirks);
-#endif
/* Turn off EEPROM-controlled wake-up (magic packet) */
if (rp->quirks & rqWOL)
@@ -687,9 +734,12 @@ static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void rhine_poll(struct net_device *dev)
{
- disable_irq(dev->irq);
- rhine_interrupt(dev->irq, (void *)dev);
- enable_irq(dev->irq);
+ struct rhine_private *rp = netdev_priv(dev);
+ const int irq = rp->irq;
+
+ disable_irq(irq);
+ rhine_interrupt(irq, dev);
+ enable_irq(irq);
}
#endif
@@ -818,7 +868,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget)
return work_done;
}
-static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
+static void rhine_hw_init(struct net_device *dev, long pioaddr)
{
struct rhine_private *rp = netdev_priv(dev);
@@ -830,14 +880,15 @@ static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
msleep(5);
/* Reload EEPROM controlled bytes cleared by soft reset */
- rhine_reload_eeprom(pioaddr, dev);
+ if (dev_is_pci(dev->dev.parent))
+ rhine_reload_eeprom(pioaddr, dev);
}
static const struct net_device_ops rhine_netdev_ops = {
.ndo_open = rhine_open,
.ndo_stop = rhine_close,
.ndo_start_xmit = rhine_start_tx,
- .ndo_get_stats = rhine_get_stats,
+ .ndo_get_stats64 = rhine_get_stats64,
.ndo_set_rx_mode = rhine_set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
@@ -851,128 +902,40 @@ static const struct net_device_ops rhine_netdev_ops = {
#endif
};
-static int __devinit rhine_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int rhine_init_one_common(struct device *hwdev, u32 quirks,
+ long pioaddr, void __iomem *ioaddr, int irq)
{
struct net_device *dev;
struct rhine_private *rp;
- int i, rc;
- u32 quirks;
- long pioaddr;
- long memaddr;
- void __iomem *ioaddr;
- int io_size, phy_id;
+ int i, rc, phy_id;
const char *name;
-#ifdef USE_MMIO
- int bar = 1;
-#else
- int bar = 0;
-#endif
-
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
- pr_info_once("%s\n", version);
-#endif
-
- io_size = 256;
- phy_id = 0;
- quirks = 0;
- name = "Rhine";
- if (pdev->revision < VTunknown0) {
- quirks = rqRhineI;
- io_size = 128;
- }
- else if (pdev->revision >= VT6102) {
- quirks = rqWOL | rqForceReset;
- if (pdev->revision < VT6105) {
- name = "Rhine II";
- quirks |= rqStatusWBRace; /* Rhine-II exclusive */
- }
- else {
- phy_id = 1; /* Integrated PHY, phy_id fixed to 1 */
- if (pdev->revision >= VT6105_B0)
- quirks |= rq6patterns;
- if (pdev->revision < VT6105M)
- name = "Rhine III";
- else
- name = "Rhine III (Management Adapter)";
- }
- }
-
- rc = pci_enable_device(pdev);
- if (rc)
- goto err_out;
/* this should always be supported */
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ rc = dma_set_mask(hwdev, DMA_BIT_MASK(32));
if (rc) {
- dev_err(&pdev->dev,
- "32-bit PCI DMA addresses not supported by the card!?\n");
- goto err_out;
- }
-
- /* sanity check */
- if ((pci_resource_len(pdev, 0) < io_size) ||
- (pci_resource_len(pdev, 1) < io_size)) {
- rc = -EIO;
- dev_err(&pdev->dev, "Insufficient PCI resources, aborting\n");
+ dev_err(hwdev, "32-bit DMA addresses not supported by the card!?\n");
goto err_out;
}
- pioaddr = pci_resource_start(pdev, 0);
- memaddr = pci_resource_start(pdev, 1);
-
- pci_set_master(pdev);
-
dev = alloc_etherdev(sizeof(struct rhine_private));
if (!dev) {
rc = -ENOMEM;
- dev_err(&pdev->dev, "alloc_etherdev failed\n");
goto err_out;
}
- SET_NETDEV_DEV(dev, &pdev->dev);
+ SET_NETDEV_DEV(dev, hwdev);
rp = netdev_priv(dev);
rp->dev = dev;
rp->quirks = quirks;
rp->pioaddr = pioaddr;
- rp->pdev = pdev;
+ rp->base = ioaddr;
+ rp->irq = irq;
rp->msg_enable = netif_msg_init(debug, RHINE_MSG_DEFAULT);
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
- goto err_out_free_netdev;
+ phy_id = rp->quirks & rqIntPHY ? 1 : 0;
- ioaddr = pci_iomap(pdev, bar, io_size);
- if (!ioaddr) {
- rc = -EIO;
- dev_err(&pdev->dev,
- "ioremap failed for device %s, region 0x%X @ 0x%lX\n",
- pci_name(pdev), io_size, memaddr);
- goto err_out_free_res;
- }
-
-#ifdef USE_MMIO
- enable_mmio(pioaddr, quirks);
-
- /* Check that selected MMIO registers match the PIO ones */
- i = 0;
- while (mmio_verify_registers[i]) {
- int reg = mmio_verify_registers[i++];
- unsigned char a = inb(pioaddr+reg);
- unsigned char b = readb(ioaddr+reg);
- if (a != b) {
- rc = -EIO;
- dev_err(&pdev->dev,
- "MMIO do not match PIO [%02x] (%02x != %02x)\n",
- reg, a, b);
- goto err_out_unmap;
- }
- }
-#endif /* USE_MMIO */
-
- dev->base_addr = (unsigned long)ioaddr;
- rp->base = ioaddr;
+ u64_stats_init(&rp->tx_stats.syncp);
+ u64_stats_init(&rp->rx_stats.syncp);
/* Get chip registers into a sane state */
rhine_power_init(dev);
@@ -984,18 +947,15 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (!is_valid_ether_addr(dev->dev_addr)) {
/* Report it and use a random ethernet address instead */
netdev_err(dev, "Invalid MAC address: %pM\n", dev->dev_addr);
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
netdev_info(dev, "Using random MAC address: %pM\n",
dev->dev_addr);
}
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* For Rhine-I/II, phy_id is loaded from EEPROM */
if (!phy_id)
phy_id = ioread8(ioaddr + 0x6C);
- dev->irq = pdev->irq;
-
spin_lock_init(&rp->lock);
mutex_init(&rp->task_lock);
INIT_WORK(&rp->reset_task, rhine_reset_task);
@@ -1009,7 +969,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
/* The chip-specific entries in the device structure. */
dev->netdev_ops = &rhine_netdev_ops;
- dev->ethtool_ops = &netdev_ethtool_ops,
+ dev->ethtool_ops = &netdev_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
netif_napi_add(dev, &rp->napi, rhine_napipoll, 64);
@@ -1017,25 +977,29 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (rp->quirks & rqRhineI)
dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
- if (pdev->revision >= VT6105M)
- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
- NETIF_F_HW_VLAN_FILTER;
+ if (rp->quirks & rqMgmt)
+ dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_FILTER;
/* dev->name not defined before register_netdev()! */
rc = register_netdev(dev);
if (rc)
- goto err_out_unmap;
+ goto err_out_free_netdev;
+
+ if (rp->quirks & rqRhineI)
+ name = "Rhine";
+ else if (rp->quirks & rqStatusWBRace)
+ name = "Rhine II";
+ else if (rp->quirks & rqMgmt)
+ name = "Rhine III (Management Adapter)";
+ else
+ name = "Rhine III";
netdev_info(dev, "VIA %s at 0x%lx, %pM, IRQ %d\n",
- name,
-#ifdef USE_MMIO
- memaddr,
-#else
- (long)ioaddr,
-#endif
- dev->dev_addr, pdev->irq);
+ name, (long)ioaddr, dev->dev_addr, rp->irq);
- pci_set_drvdata(pdev, dev);
+ dev_set_drvdata(hwdev, dev);
{
u16 mii_cmd;
@@ -1064,39 +1028,158 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
return 0;
+err_out_free_netdev:
+ free_netdev(dev);
+err_out:
+ return rc;
+}
+
+static int rhine_init_one_pci(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct device *hwdev = &pdev->dev;
+ int rc;
+ long pioaddr, memaddr;
+ void __iomem *ioaddr;
+ int io_size = pdev->revision < VTunknown0 ? 128 : 256;
+
+/* This driver was written to use PCI memory space. Some early versions
+ * of the Rhine may only work correctly with I/O space accesses.
+ * TODO: determine for which revisions this is true and assign the flag
+ * in code as opposed to this Kconfig option (???)
+ */
+#ifdef CONFIG_VIA_RHINE_MMIO
+ u32 quirks = rqNeedEnMMIO;
+#else
+ u32 quirks = 0;
+#endif
+
+/* when built into the kernel, we only print version if device is found */
+#ifndef MODULE
+ pr_info_once("%s\n", version);
+#endif
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ goto err_out;
+
+ if (pdev->revision < VTunknown0) {
+ quirks |= rqRhineI;
+ } else if (pdev->revision >= VT6102) {
+ quirks |= rqWOL | rqForceReset;
+ if (pdev->revision < VT6105) {
+ quirks |= rqStatusWBRace;
+ } else {
+ quirks |= rqIntPHY;
+ if (pdev->revision >= VT6105_B0)
+ quirks |= rq6patterns;
+ if (pdev->revision >= VT6105M)
+ quirks |= rqMgmt;
+ }
+ }
+
+ /* sanity check */
+ if ((pci_resource_len(pdev, 0) < io_size) ||
+ (pci_resource_len(pdev, 1) < io_size)) {
+ rc = -EIO;
+ dev_err(hwdev, "Insufficient PCI resources, aborting\n");
+ goto err_out_pci_disable;
+ }
+
+ pioaddr = pci_resource_start(pdev, 0);
+ memaddr = pci_resource_start(pdev, 1);
+
+ pci_set_master(pdev);
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out_pci_disable;
+
+ ioaddr = pci_iomap(pdev, (quirks & rqNeedEnMMIO ? 1 : 0), io_size);
+ if (!ioaddr) {
+ rc = -EIO;
+ dev_err(hwdev,
+ "ioremap failed for device %s, region 0x%X @ 0x%lX\n",
+ dev_name(hwdev), io_size, memaddr);
+ goto err_out_free_res;
+ }
+
+ enable_mmio(pioaddr, quirks);
+
+ rc = verify_mmio(hwdev, pioaddr, ioaddr, quirks);
+ if (rc)
+ goto err_out_unmap;
+
+ rc = rhine_init_one_common(&pdev->dev, quirks,
+ pioaddr, ioaddr, pdev->irq);
+ if (!rc)
+ return 0;
+
err_out_unmap:
pci_iounmap(pdev, ioaddr);
err_out_free_res:
pci_release_regions(pdev);
-err_out_free_netdev:
- free_netdev(dev);
+err_out_pci_disable:
+ pci_disable_device(pdev);
err_out:
return rc;
}
+static int rhine_init_one_platform(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ const u32 *quirks;
+ int irq;
+ struct resource *res;
+ void __iomem *ioaddr;
+
+ match = of_match_device(rhine_of_tbl, &pdev->dev);
+ if (!match)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ioaddr))
+ return PTR_ERR(ioaddr);
+
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ if (!irq)
+ return -EINVAL;
+
+ quirks = match->data;
+ if (!quirks)
+ return -EINVAL;
+
+ return rhine_init_one_common(&pdev->dev, *quirks,
+ (long)ioaddr, ioaddr, irq);
+}
+
static int alloc_ring(struct net_device* dev)
{
struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
void *ring;
dma_addr_t ring_dma;
- ring = pci_alloc_consistent(rp->pdev,
- RX_RING_SIZE * sizeof(struct rx_desc) +
- TX_RING_SIZE * sizeof(struct tx_desc),
- &ring_dma);
+ ring = dma_alloc_coherent(hwdev,
+ RX_RING_SIZE * sizeof(struct rx_desc) +
+ TX_RING_SIZE * sizeof(struct tx_desc),
+ &ring_dma,
+ GFP_ATOMIC);
if (!ring) {
netdev_err(dev, "Could not allocate DMA memory\n");
return -ENOMEM;
}
if (rp->quirks & rqRhineI) {
- rp->tx_bufs = pci_alloc_consistent(rp->pdev,
- PKT_BUF_SZ * TX_RING_SIZE,
- &rp->tx_bufs_dma);
+ rp->tx_bufs = dma_alloc_coherent(hwdev,
+ PKT_BUF_SZ * TX_RING_SIZE,
+ &rp->tx_bufs_dma,
+ GFP_ATOMIC);
if (rp->tx_bufs == NULL) {
- pci_free_consistent(rp->pdev,
- RX_RING_SIZE * sizeof(struct rx_desc) +
- TX_RING_SIZE * sizeof(struct tx_desc),
- ring, ring_dma);
+ dma_free_coherent(hwdev,
+ RX_RING_SIZE * sizeof(struct rx_desc) +
+ TX_RING_SIZE * sizeof(struct tx_desc),
+ ring, ring_dma);
return -ENOMEM;
}
}
@@ -1112,16 +1195,17 @@ static int alloc_ring(struct net_device* dev)
static void free_ring(struct net_device* dev)
{
struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
- pci_free_consistent(rp->pdev,
- RX_RING_SIZE * sizeof(struct rx_desc) +
- TX_RING_SIZE * sizeof(struct tx_desc),
- rp->rx_ring, rp->rx_ring_dma);
+ dma_free_coherent(hwdev,
+ RX_RING_SIZE * sizeof(struct rx_desc) +
+ TX_RING_SIZE * sizeof(struct tx_desc),
+ rp->rx_ring, rp->rx_ring_dma);
rp->tx_ring = NULL;
if (rp->tx_bufs)
- pci_free_consistent(rp->pdev, PKT_BUF_SZ * TX_RING_SIZE,
- rp->tx_bufs, rp->tx_bufs_dma);
+ dma_free_coherent(hwdev, PKT_BUF_SZ * TX_RING_SIZE,
+ rp->tx_bufs, rp->tx_bufs_dma);
rp->tx_bufs = NULL;
@@ -1130,6 +1214,7 @@ static void free_ring(struct net_device* dev)
static void alloc_rbufs(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
dma_addr_t next;
int i;
@@ -1156,12 +1241,15 @@ static void alloc_rbufs(struct net_device *dev)
rp->rx_skbuff[i] = skb;
if (skb == NULL)
break;
- skb->dev = dev; /* Mark as being used by this device. */
rp->rx_skbuff_dma[i] =
- pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
-
+ dma_map_single(hwdev, skb->data, rp->rx_buf_sz,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(hwdev, rp->rx_skbuff_dma[i])) {
+ rp->rx_skbuff_dma[i] = 0;
+ dev_kfree_skb(skb);
+ break;
+ }
rp->rx_ring[i].addr = cpu_to_le32(rp->rx_skbuff_dma[i]);
rp->rx_ring[i].rx_status = cpu_to_le32(DescOwn);
}
@@ -1171,6 +1259,7 @@ static void alloc_rbufs(struct net_device *dev)
static void free_rbufs(struct net_device* dev)
{
struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
int i;
/* Free all the skbuffs in the Rx queue. */
@@ -1178,9 +1267,9 @@ static void free_rbufs(struct net_device* dev)
rp->rx_ring[i].rx_status = 0;
rp->rx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
if (rp->rx_skbuff[i]) {
- pci_unmap_single(rp->pdev,
+ dma_unmap_single(hwdev,
rp->rx_skbuff_dma[i],
- rp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ rp->rx_buf_sz, DMA_FROM_DEVICE);
dev_kfree_skb(rp->rx_skbuff[i]);
}
rp->rx_skbuff[i] = NULL;
@@ -1211,6 +1300,7 @@ static void alloc_tbufs(struct net_device* dev)
static void free_tbufs(struct net_device* dev)
{
struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
int i;
for (i = 0; i < TX_RING_SIZE; i++) {
@@ -1219,10 +1309,10 @@ static void free_tbufs(struct net_device* dev)
rp->tx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
if (rp->tx_skbuff[i]) {
if (rp->tx_skbuff_dma[i]) {
- pci_unmap_single(rp->pdev,
+ dma_unmap_single(hwdev,
rp->tx_skbuff_dma[i],
rp->tx_skbuff[i]->len,
- PCI_DMA_TODEVICE);
+ DMA_TO_DEVICE);
}
dev_kfree_skb(rp->tx_skbuff[i]);
}
@@ -1259,8 +1349,9 @@ static void rhine_set_carrier(struct mii_if_info *mii)
/* autoneg is off: Link is always assumed to be up */
if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
- } else /* Let MMI library update carrier status */
- rhine_check_media(dev, 0);
+ }
+
+ rhine_check_media(dev, 0);
netif_info(rp, link, dev, "force_media %d, carrier %d\n",
mii->force_media, netif_carrier_ok(dev));
@@ -1407,7 +1498,7 @@ static void rhine_update_vcam(struct net_device *dev)
rhine_set_vlan_cam_mask(ioaddr, vCAMmask);
}
-static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+static int rhine_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
{
struct rhine_private *rp = netdev_priv(dev);
@@ -1418,7 +1509,7 @@ static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
return 0;
}
-static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+static int rhine_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
{
struct rhine_private *rp = netdev_priv(dev);
@@ -1450,7 +1541,7 @@ static void init_registers(struct net_device *dev)
rhine_set_rx_mode(dev);
- if (rp->pdev->revision >= VT6105M)
+ if (rp->quirks & rqMgmt)
rhine_init_cam_filter(dev);
napi_enable(&rp->napi);
@@ -1562,16 +1653,15 @@ static int rhine_open(struct net_device *dev)
void __iomem *ioaddr = rp->base;
int rc;
- rc = request_irq(rp->pdev->irq, rhine_interrupt, IRQF_SHARED, dev->name,
- dev);
+ rc = request_irq(rp->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev);
if (rc)
return rc;
- netif_dbg(rp, ifup, dev, "%s() irq %d\n", __func__, rp->pdev->irq);
+ netif_dbg(rp, ifup, dev, "%s() irq %d\n", __func__, rp->irq);
rc = alloc_ring(dev);
if (rc) {
- free_irq(rp->pdev->irq, dev);
+ free_irq(rp->irq, dev);
return rc;
}
alloc_rbufs(dev);
@@ -1601,6 +1691,7 @@ static void rhine_reset_task(struct work_struct *work)
goto out_unlock;
napi_disable(&rp->napi);
+ netif_tx_disable(dev);
spin_lock_bh(&rp->lock);
/* clear all descriptors */
@@ -1639,6 +1730,7 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
void __iomem *ioaddr = rp->base;
unsigned entry;
@@ -1658,7 +1750,7 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
/* Must use alignment buffer. */
if (skb->len > PKT_BUF_SZ) {
/* packet too long, drop it */
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
rp->tx_skbuff[entry] = NULL;
dev->stats.tx_dropped++;
return NETDEV_TX_OK;
@@ -1675,8 +1767,14 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
rp->tx_bufs));
} else {
rp->tx_skbuff_dma[entry] =
- pci_map_single(rp->pdev, skb->data, skb->len,
- PCI_DMA_TODEVICE);
+ dma_map_single(hwdev, skb->data, skb->len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(hwdev, rp->tx_skbuff_dma[entry])) {
+ dev_kfree_skb_any(skb);
+ rp->tx_skbuff_dma[entry] = 0;
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_skbuff_dma[entry]);
}
@@ -1684,7 +1782,12 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
if (unlikely(vlan_tx_tag_present(skb))) {
- rp->tx_ring[entry].tx_status = cpu_to_le32((vlan_tx_tag_get(skb)) << 16);
+ u16 vid_pcp = vlan_tx_tag_get(skb);
+
+ /* drop CFI/DEI bit, register needs VID and PCP */
+ vid_pcp = (vid_pcp & VLAN_VID_MASK) |
+ ((vid_pcp & VLAN_PRIO_MASK) >> 1);
+ rp->tx_ring[entry].tx_status = cpu_to_le32((vid_pcp) << 16);
/* request tagging */
rp->tx_ring[entry].desc_length |= cpu_to_le32(0x020000);
}
@@ -1757,6 +1860,7 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
static void rhine_tx(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
/* find and cleanup dirty tx descriptors */
@@ -1792,17 +1896,20 @@ static void rhine_tx(struct net_device *dev)
dev->stats.collisions += txstatus & 0x0F;
netif_dbg(rp, tx_done, dev, "collisions: %1.1x:%1.1x\n",
(txstatus >> 3) & 0xF, txstatus & 0xF);
- dev->stats.tx_bytes += rp->tx_skbuff[entry]->len;
- dev->stats.tx_packets++;
+
+ u64_stats_update_begin(&rp->tx_stats.syncp);
+ rp->tx_stats.bytes += rp->tx_skbuff[entry]->len;
+ rp->tx_stats.packets++;
+ u64_stats_update_end(&rp->tx_stats.syncp);
}
/* Free the original skb. */
if (rp->tx_skbuff_dma[entry]) {
- pci_unmap_single(rp->pdev,
+ dma_unmap_single(hwdev,
rp->tx_skbuff_dma[entry],
rp->tx_skbuff[entry]->len,
- PCI_DMA_TODEVICE);
+ DMA_TO_DEVICE);
}
- dev_kfree_skb_irq(rp->tx_skbuff[entry]);
+ dev_consume_skb_any(rp->tx_skbuff[entry]);
rp->tx_skbuff[entry] = NULL;
entry = (++rp->dirty_tx) % TX_RING_SIZE;
}
@@ -1829,6 +1936,7 @@ static inline u16 rhine_get_vlan_tci(struct sk_buff *skb, int data_size)
static int rhine_rx(struct net_device *dev, int limit)
{
struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
int count;
int entry = rp->cur_rx % RX_RING_SIZE;
@@ -1890,19 +1998,19 @@ static int rhine_rx(struct net_device *dev, int limit)
if (pkt_len < rx_copybreak)
skb = netdev_alloc_skb_ip_align(dev, pkt_len);
if (skb) {
- pci_dma_sync_single_for_cpu(rp->pdev,
- rp->rx_skbuff_dma[entry],
- rp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
+ dma_sync_single_for_cpu(hwdev,
+ rp->rx_skbuff_dma[entry],
+ rp->rx_buf_sz,
+ DMA_FROM_DEVICE);
skb_copy_to_linear_data(skb,
rp->rx_skbuff[entry]->data,
pkt_len);
skb_put(skb, pkt_len);
- pci_dma_sync_single_for_device(rp->pdev,
- rp->rx_skbuff_dma[entry],
- rp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
+ dma_sync_single_for_device(hwdev,
+ rp->rx_skbuff_dma[entry],
+ rp->rx_buf_sz,
+ DMA_FROM_DEVICE);
} else {
skb = rp->rx_skbuff[entry];
if (skb == NULL) {
@@ -1911,10 +2019,10 @@ static int rhine_rx(struct net_device *dev, int limit)
}
rp->rx_skbuff[entry] = NULL;
skb_put(skb, pkt_len);
- pci_unmap_single(rp->pdev,
+ dma_unmap_single(hwdev,
rp->rx_skbuff_dma[entry],
rp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
+ DMA_FROM_DEVICE);
}
if (unlikely(desc_length & DescTag))
@@ -1923,10 +2031,13 @@ static int rhine_rx(struct net_device *dev, int limit)
skb->protocol = eth_type_trans(skb, dev);
if (unlikely(desc_length & DescTag))
- __vlan_hwaccel_put_tag(skb, vlan_tci);
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
netif_receive_skb(skb);
- dev->stats.rx_bytes += pkt_len;
- dev->stats.rx_packets++;
+
+ u64_stats_update_begin(&rp->rx_stats.syncp);
+ rp->rx_stats.bytes += pkt_len;
+ rp->rx_stats.packets++;
+ u64_stats_update_end(&rp->rx_stats.syncp);
}
entry = (++rp->cur_rx) % RX_RING_SIZE;
rp->rx_head_desc = &rp->rx_ring[entry];
@@ -1941,11 +2052,16 @@ static int rhine_rx(struct net_device *dev, int limit)
rp->rx_skbuff[entry] = skb;
if (skb == NULL)
break; /* Better luck next round. */
- skb->dev = dev; /* Mark as being used by this device. */
rp->rx_skbuff_dma[entry] =
- pci_map_single(rp->pdev, skb->data,
+ dma_map_single(hwdev, skb->data,
rp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(hwdev,
+ rp->rx_skbuff_dma[entry])) {
+ dev_kfree_skb(skb);
+ rp->rx_skbuff_dma[entry] = 0;
+ break;
+ }
rp->rx_ring[entry].addr = cpu_to_le32(rp->rx_skbuff_dma[entry]);
}
rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
@@ -2012,25 +2128,37 @@ static void rhine_slow_event_task(struct work_struct *work)
if (intr_status & IntrPCIErr)
netif_warn(rp, hw, dev, "PCI error\n");
- napi_disable(&rp->napi);
- rhine_irq_disable(rp);
- /* Slow and safe. Consider __napi_schedule as a replacement ? */
- napi_enable(&rp->napi);
- napi_schedule(&rp->napi);
+ iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable);
out_unlock:
mutex_unlock(&rp->task_lock);
}
-static struct net_device_stats *rhine_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *
+rhine_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
struct rhine_private *rp = netdev_priv(dev);
+ unsigned int start;
spin_lock_bh(&rp->lock);
rhine_update_rx_crc_and_missed_errord(rp);
spin_unlock_bh(&rp->lock);
- return &dev->stats;
+ netdev_stats_to_stats64(stats, &dev->stats);
+
+ do {
+ start = u64_stats_fetch_begin_irq(&rp->rx_stats.syncp);
+ stats->rx_packets = rp->rx_stats.packets;
+ stats->rx_bytes = rp->rx_stats.bytes;
+ } while (u64_stats_fetch_retry_irq(&rp->rx_stats.syncp, start));
+
+ do {
+ start = u64_stats_fetch_begin_irq(&rp->tx_stats.syncp);
+ stats->tx_packets = rp->tx_stats.packets;
+ stats->tx_bytes = rp->tx_stats.bytes;
+ } while (u64_stats_fetch_retry_irq(&rp->tx_stats.syncp, start));
+
+ return stats;
}
static void rhine_set_rx_mode(struct net_device *dev)
@@ -2050,7 +2178,7 @@ static void rhine_set_rx_mode(struct net_device *dev)
/* Too many to match, or accept all multicasts. */
iowrite32(0xffffffff, ioaddr + MulticastFilter0);
iowrite32(0xffffffff, ioaddr + MulticastFilter1);
- } else if (rp->pdev->revision >= VT6105M) {
+ } else if (rp->quirks & rqMgmt) {
int i = 0;
u32 mCAMmask = 0; /* 32 mCAMs (6105M and better) */
netdev_for_each_mc_addr(ha, dev) {
@@ -2072,7 +2200,7 @@ static void rhine_set_rx_mode(struct net_device *dev)
iowrite32(mc_filter[1], ioaddr + MulticastFilter1);
}
/* enable/disable VLAN receive filtering */
- if (rp->pdev->revision >= VT6105M) {
+ if (rp->quirks & rqMgmt) {
if (dev->flags & IFF_PROMISC)
BYTE_REG_BITS_OFF(BCR1_VIDFR, ioaddr + PCIBusConfig1);
else
@@ -2083,11 +2211,11 @@ static void rhine_set_rx_mode(struct net_device *dev)
static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct rhine_private *rp = netdev_priv(dev);
+ struct device *hwdev = dev->dev.parent;
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, pci_name(rp->pdev), sizeof(info->bus_info));
+ strlcpy(info->bus_info, dev_name(hwdev), sizeof(info->bus_info));
}
static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -2224,7 +2352,7 @@ static int rhine_close(struct net_device *dev)
/* Stop the chip's Tx and Rx processes. */
iowrite16(CmdStop, ioaddr + ChipCmd);
- free_irq(rp->pdev->irq, dev);
+ free_irq(rp->irq, dev);
free_rbufs(dev);
free_tbufs(dev);
free_ring(dev);
@@ -2233,7 +2361,7 @@ static int rhine_close(struct net_device *dev)
}
-static void __devexit rhine_remove_one(struct pci_dev *pdev)
+static void rhine_remove_one_pci(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rhine_private *rp = netdev_priv(dev);
@@ -2245,10 +2373,23 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev)
free_netdev(dev);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
}
-static void rhine_shutdown (struct pci_dev *pdev)
+static int rhine_remove_one_platform(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct rhine_private *rp = netdev_priv(dev);
+
+ unregister_netdev(dev);
+
+ iounmap(rp->base);
+
+ free_netdev(dev);
+
+ return 0;
+}
+
+static void rhine_shutdown_pci(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rhine_private *rp = netdev_priv(dev);
@@ -2302,8 +2443,7 @@ static void rhine_shutdown (struct pci_dev *pdev)
#ifdef CONFIG_PM_SLEEP
static int rhine_suspend(struct device *device)
{
- struct pci_dev *pdev = to_pci_dev(device);
- struct net_device *dev = pci_get_drvdata(pdev);
+ struct net_device *dev = dev_get_drvdata(device);
struct rhine_private *rp = netdev_priv(dev);
if (!netif_running(dev))
@@ -2315,23 +2455,21 @@ static int rhine_suspend(struct device *device)
netif_device_detach(dev);
- rhine_shutdown(pdev);
+ if (dev_is_pci(device))
+ rhine_shutdown_pci(to_pci_dev(device));
return 0;
}
static int rhine_resume(struct device *device)
{
- struct pci_dev *pdev = to_pci_dev(device);
- struct net_device *dev = pci_get_drvdata(pdev);
+ struct net_device *dev = dev_get_drvdata(device);
struct rhine_private *rp = netdev_priv(dev);
if (!netif_running(dev))
return 0;
-#ifdef USE_MMIO
enable_mmio(rp->pioaddr, rp->quirks);
-#endif
rhine_power_init(dev);
free_tbufs(dev);
free_rbufs(dev);
@@ -2356,16 +2494,27 @@ static SIMPLE_DEV_PM_OPS(rhine_pm_ops, rhine_suspend, rhine_resume);
#endif /* !CONFIG_PM_SLEEP */
-static struct pci_driver rhine_driver = {
+static struct pci_driver rhine_driver_pci = {
.name = DRV_NAME,
.id_table = rhine_pci_tbl,
- .probe = rhine_init_one,
- .remove = __devexit_p(rhine_remove_one),
- .shutdown = rhine_shutdown,
+ .probe = rhine_init_one_pci,
+ .remove = rhine_remove_one_pci,
+ .shutdown = rhine_shutdown_pci,
.driver.pm = RHINE_PM_OPS,
};
-static struct dmi_system_id __initdata rhine_dmi_table[] = {
+static struct platform_driver rhine_driver_platform = {
+ .probe = rhine_init_one_platform,
+ .remove = rhine_remove_one_platform,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = rhine_of_tbl,
+ .pm = RHINE_PM_OPS,
+ }
+};
+
+static struct dmi_system_id rhine_dmi_table[] __initdata = {
{
.ident = "EPIA-M",
.matches = {
@@ -2385,6 +2534,8 @@ static struct dmi_system_id __initdata rhine_dmi_table[] = {
static int __init rhine_init(void)
{
+ int ret_pci, ret_platform;
+
/* when a module, this is printed whether or not devices are found in probe */
#ifdef MODULE
pr_info("%s\n", version);
@@ -2397,13 +2548,19 @@ static int __init rhine_init(void)
else if (avoid_D3)
pr_info("avoid_D3 set\n");
- return pci_register_driver(&rhine_driver);
+ ret_pci = pci_register_driver(&rhine_driver_pci);
+ ret_platform = platform_driver_register(&rhine_driver_platform);
+ if ((ret_pci < 0) && (ret_platform < 0))
+ return ret_pci;
+
+ return 0;
}
static void __exit rhine_cleanup(void)
{
- pci_unregister_driver(&rhine_driver);
+ platform_driver_unregister(&rhine_driver_platform);
+ pci_unregister_driver(&rhine_driver_pci);
}
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index cb35b14b73b..de08e86db20 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -46,6 +46,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/init.h>
+#include <linux/dma-mapping.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ioport.h>
@@ -64,7 +65,11 @@
#include <linux/if.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/inetdevice.h>
+#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
@@ -79,10 +84,24 @@
#include "via-velocity.h"
+enum velocity_bus_type {
+ BUS_PCI,
+ BUS_PLATFORM,
+};
static int velocity_nics;
static int msglevel = MSG_LEVEL_INFO;
+static void velocity_set_power_state(struct velocity_info *vptr, char state)
+{
+ void *addr = vptr->mac_regs;
+
+ if (vptr->pdev)
+ pci_set_power_state(vptr->pdev, state);
+ else
+ writeb(state, addr + 0x154);
+}
+
/**
* mac_get_cam_mask - Read a CAM mask
* @regs: register block for this velocity
@@ -361,12 +380,23 @@ static struct velocity_info_tbl chip_info_table[] = {
* Describe the PCI device identifiers that we support in this
* device driver. Used for hotplug autoloading.
*/
-static DEFINE_PCI_DEVICE_TABLE(velocity_id_table) = {
+
+static DEFINE_PCI_DEVICE_TABLE(velocity_pci_id_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
{ }
};
-MODULE_DEVICE_TABLE(pci, velocity_id_table);
+MODULE_DEVICE_TABLE(pci, velocity_pci_id_table);
+
+/**
+ * Describe the OF device identifiers that we support in this
+ * device driver. Used for devicetree nodes.
+ */
+static struct of_device_id velocity_of_ids[] = {
+ { .compatible = "via,velocity-vt6110", .data = &chip_info_table[0] },
+ { /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, velocity_of_ids);
/**
* get_chip_name - identifier to name
@@ -375,7 +405,7 @@ MODULE_DEVICE_TABLE(pci, velocity_id_table);
* Given a chip identifier return a suitable description. Returns
* a pointer a static string valid while the driver is loaded.
*/
-static const char __devinit *get_chip_name(enum chip_type chip_id)
+static const char *get_chip_name(enum chip_type chip_id)
{
int i;
for (i = 0; chip_info_table[i].name != NULL; i++)
@@ -385,29 +415,6 @@ static const char __devinit *get_chip_name(enum chip_type chip_id)
}
/**
- * velocity_remove1 - device unplug
- * @pdev: PCI device being removed
- *
- * Device unload callback. Called on an unplug or on module
- * unload for each active device that is present. Disconnects
- * the device from the network layer and frees all the resources
- */
-static void __devexit velocity_remove1(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct velocity_info *vptr = netdev_priv(dev);
-
- unregister_netdev(dev);
- iounmap(vptr->mac_regs);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
- free_netdev(dev);
-
- velocity_nics--;
-}
-
-/**
* velocity_set_int_opt - parser for integer options
* @opt: pointer to option value
* @val: value the user requested (or -1 for default)
@@ -421,7 +428,8 @@ static void __devexit velocity_remove1(struct pci_dev *pdev)
* all the verification and checking as well as reporting so that
* we don't duplicate code for each option.
*/
-static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, const char *devname)
+static void velocity_set_int_opt(int *opt, int val, int min, int max, int def,
+ char *name, const char *devname)
{
if (val == -1)
*opt = def;
@@ -449,7 +457,8 @@ static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max,
* all the verification and checking as well as reporting so that
* we don't duplicate code for each option.
*/
-static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag, char *name, const char *devname)
+static void velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag,
+ char *name, const char *devname)
{
(*opt) &= (~flag);
if (val == -1)
@@ -474,7 +483,8 @@ static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag
* Turn the module and command options into a single structure
* for the current device
*/
-static void __devinit velocity_get_options(struct velocity_opt *opts, int index, const char *devname)
+static void velocity_get_options(struct velocity_opt *opts, int index,
+ const char *devname)
{
velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname);
@@ -486,7 +496,7 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname);
velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);
velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);
- velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
+ velocity_set_int_opt(&opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
opts->numrx = (opts->numrx & ~3);
}
@@ -522,7 +532,8 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
}
-static int velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+static int velocity_vlan_rx_add_vid(struct net_device *dev,
+ __be16 proto, u16 vid)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -533,7 +544,8 @@ static int velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
return 0;
}
-static int velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+static int velocity_vlan_rx_kill_vid(struct net_device *dev,
+ __be16 proto, u16 vid)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -993,9 +1005,9 @@ static void velocity_print_link_status(struct velocity_info *vptr)
{
if (vptr->mii_status & VELOCITY_LINK_FAIL) {
- VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
+ VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->netdev->name);
} else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
- VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name);
+ VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->netdev->name);
if (vptr->mii_status & VELOCITY_SPEED_1000)
VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
@@ -1009,7 +1021,7 @@ static void velocity_print_link_status(struct velocity_info *vptr)
else
VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n");
} else {
- VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
+ VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->netdev->name);
switch (vptr->options.spd_dpx) {
case SPD_DPX_1000_FULL:
VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n");
@@ -1175,6 +1187,17 @@ static void mii_init(struct velocity_info *vptr, u32 mii_status)
u16 BMCR;
switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
+ case PHYID_ICPLUS_IP101A:
+ MII_REG_BITS_ON((ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP),
+ MII_ADVERTISE, vptr->mac_regs);
+ if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+ MII_REG_BITS_ON(TCSR_ECHODIS, MII_SREVISION,
+ vptr->mac_regs);
+ else
+ MII_REG_BITS_OFF(TCSR_ECHODIS, MII_SREVISION,
+ vptr->mac_regs);
+ MII_REG_BITS_ON(PLED_LALBE, MII_TPISTATUS, vptr->mac_regs);
+ break;
case PHYID_CICADA_CS8201:
/*
* Reset to hardware default
@@ -1306,6 +1329,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
enum velocity_init_type type)
{
struct mac_regs __iomem *regs = vptr->mac_regs;
+ struct net_device *netdev = vptr->netdev;
int i, mii_status;
mac_wol_reset(regs);
@@ -1314,7 +1338,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
case VELOCITY_INIT_RESET:
case VELOCITY_INIT_WOL:
- netif_stop_queue(vptr->dev);
+ netif_stop_queue(netdev);
/*
* Reset RX to prevent RX pointer not on the 4X location
@@ -1327,7 +1351,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
velocity_print_link_status(vptr);
if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
- netif_wake_queue(vptr->dev);
+ netif_wake_queue(netdev);
}
enable_flow_control_ability(vptr);
@@ -1347,9 +1371,11 @@ static void velocity_init_registers(struct velocity_info *vptr,
velocity_soft_reset(vptr);
mdelay(5);
- mac_eeprom_reload(regs);
- for (i = 0; i < 6; i++)
- writeb(vptr->dev->dev_addr[i], &(regs->PAR[i]));
+ if (!vptr->no_eeprom) {
+ mac_eeprom_reload(regs);
+ for (i = 0; i < 6; i++)
+ writeb(netdev->dev_addr[i], regs->PAR + i);
+ }
/*
* clear Pre_ACPI bit.
@@ -1372,7 +1398,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
/*
* Set packet filter: Receive directed and broadcast address
*/
- velocity_set_multi(vptr->dev);
+ velocity_set_multi(netdev);
/*
* Enable MII auto-polling
@@ -1399,14 +1425,14 @@ static void velocity_init_registers(struct velocity_info *vptr,
writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), &regs->CR0Set);
mii_status = velocity_get_opt_media_mode(vptr);
- netif_stop_queue(vptr->dev);
+ netif_stop_queue(netdev);
mii_init(vptr, mii_status);
if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
velocity_print_link_status(vptr);
if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
- netif_wake_queue(vptr->dev);
+ netif_wake_queue(netdev);
}
enable_flow_control_ability(vptr);
@@ -1454,7 +1480,6 @@ static int velocity_init_dma_rings(struct velocity_info *vptr)
struct velocity_opt *opt = &vptr->options;
const unsigned int rx_ring_size = opt->numrx * sizeof(struct rx_desc);
const unsigned int tx_ring_size = opt->numtx * sizeof(struct tx_desc);
- struct pci_dev *pdev = vptr->pdev;
dma_addr_t pool_dma;
void *pool;
unsigned int i;
@@ -1462,14 +1487,14 @@ static int velocity_init_dma_rings(struct velocity_info *vptr)
/*
* Allocate all RD/TD rings a single pool.
*
- * pci_alloc_consistent() fulfills the requirement for 64 bytes
+ * dma_alloc_coherent() fulfills the requirement for 64 bytes
* alignment
*/
- pool = pci_alloc_consistent(pdev, tx_ring_size * vptr->tx.numq +
- rx_ring_size, &pool_dma);
+ pool = dma_alloc_coherent(vptr->dev, tx_ring_size * vptr->tx.numq +
+ rx_ring_size, &pool_dma, GFP_ATOMIC);
if (!pool) {
- dev_err(&pdev->dev, "%s : DMA memory allocation failed.\n",
- vptr->dev->name);
+ dev_err(vptr->dev, "%s : DMA memory allocation failed.\n",
+ vptr->netdev->name);
return -ENOMEM;
}
@@ -1509,7 +1534,7 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
struct rx_desc *rd = &(vptr->rx.ring[idx]);
struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
- rd_info->skb = dev_alloc_skb(vptr->rx.buf_sz + 64);
+ rd_info->skb = netdev_alloc_skb(vptr->netdev, vptr->rx.buf_sz + 64);
if (rd_info->skb == NULL)
return -ENOMEM;
@@ -1519,8 +1544,8 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
*/
skb_reserve(rd_info->skb,
64 - ((unsigned long) rd_info->skb->data & 63));
- rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->data,
- vptr->rx.buf_sz, PCI_DMA_FROMDEVICE);
+ rd_info->skb_dma = dma_map_single(vptr->dev, rd_info->skb->data,
+ vptr->rx.buf_sz, DMA_FROM_DEVICE);
/*
* Fill in the descriptor to match
@@ -1583,8 +1608,8 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
if (!rd_info->skb)
continue;
- pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz,
- PCI_DMA_FROMDEVICE);
+ dma_unmap_single(vptr->dev, rd_info->skb_dma, vptr->rx.buf_sz,
+ DMA_FROM_DEVICE);
rd_info->skb_dma = 0;
dev_kfree_skb(rd_info->skb);
@@ -1615,7 +1640,7 @@ static int velocity_init_rd_ring(struct velocity_info *vptr)
if (velocity_rx_refill(vptr) != vptr->options.numrx) {
VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
- "%s: failed to allocate RX buffer.\n", vptr->dev->name);
+ "%s: failed to allocate RX buffer.\n", vptr->netdev->name);
velocity_free_rd_ring(vptr);
goto out;
}
@@ -1665,7 +1690,7 @@ static void velocity_free_dma_rings(struct velocity_info *vptr)
const int size = vptr->options.numrx * sizeof(struct rx_desc) +
vptr->options.numtx * sizeof(struct tx_desc) * vptr->tx.numq;
- pci_free_consistent(vptr->pdev, size, vptr->rx.ring, vptr->rx.pool_dma);
+ dma_free_coherent(vptr->dev, size, vptr->rx.ring, vptr->rx.pool_dma);
}
static int velocity_init_rings(struct velocity_info *vptr, int mtu)
@@ -1722,8 +1747,8 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
pktlen = max_t(size_t, pktlen,
td->td_buf[i].size & ~TD_QUEUE);
- pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i],
- le16_to_cpu(pktlen), PCI_DMA_TODEVICE);
+ dma_unmap_single(vptr->dev, tdinfo->skb_dma[i],
+ le16_to_cpu(pktlen), DMA_TO_DEVICE);
}
}
dev_kfree_skb_irq(skb);
@@ -1745,8 +1770,8 @@ static void velocity_free_td_ring_entry(struct velocity_info *vptr,
if (td_info->skb) {
for (i = 0; i < td_info->nskb_dma; i++) {
if (td_info->skb_dma[i]) {
- pci_unmap_single(vptr->pdev, td_info->skb_dma[i],
- td_info->skb->len, PCI_DMA_TODEVICE);
+ dma_unmap_single(vptr->dev, td_info->skb_dma[i],
+ td_info->skb->len, DMA_TO_DEVICE);
td_info->skb_dma[i] = 0;
}
}
@@ -1804,7 +1829,7 @@ static void velocity_error(struct velocity_info *vptr, int status)
printk(KERN_ERR "TD structure error TDindex=%hx\n", readw(&regs->TDIdx[0]));
BYTE_REG_BITS_ON(TXESR_TDSTR, &regs->TXESR);
writew(TRDCSR_RUN, &regs->TDCSRClr);
- netif_stop_queue(vptr->dev);
+ netif_stop_queue(vptr->netdev);
/* FIXME: port over the pci_device_failed code and use it
here */
@@ -1845,10 +1870,10 @@ static void velocity_error(struct velocity_info *vptr, int status)
if (linked) {
vptr->mii_status &= ~VELOCITY_LINK_FAIL;
- netif_carrier_on(vptr->dev);
+ netif_carrier_on(vptr->netdev);
} else {
vptr->mii_status |= VELOCITY_LINK_FAIL;
- netif_carrier_off(vptr->dev);
+ netif_carrier_off(vptr->netdev);
}
velocity_print_link_status(vptr);
@@ -1862,9 +1887,9 @@ static void velocity_error(struct velocity_info *vptr, int status)
enable_mii_autopoll(regs);
if (vptr->mii_status & VELOCITY_LINK_FAIL)
- netif_stop_queue(vptr->dev);
+ netif_stop_queue(vptr->netdev);
else
- netif_wake_queue(vptr->dev);
+ netif_wake_queue(vptr->netdev);
}
if (status & ISR_MIBFI)
@@ -1889,7 +1914,7 @@ static int velocity_tx_srv(struct velocity_info *vptr)
int idx;
int works = 0;
struct velocity_td_info *tdinfo;
- struct net_device_stats *stats = &vptr->dev->stats;
+ struct net_device_stats *stats = &vptr->netdev->stats;
for (qnum = 0; qnum < vptr->tx.numq; qnum++) {
for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0;
@@ -1934,9 +1959,9 @@ static int velocity_tx_srv(struct velocity_info *vptr)
* Look to see if we should kick the transmit network
* layer for more work.
*/
- if (netif_queue_stopped(vptr->dev) && (full == 0) &&
+ if (netif_queue_stopped(vptr->netdev) && (full == 0) &&
(!(vptr->mii_status & VELOCITY_LINK_FAIL))) {
- netif_wake_queue(vptr->dev);
+ netif_wake_queue(vptr->netdev);
}
return works;
}
@@ -1984,7 +2009,7 @@ static int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size,
if (pkt_size < rx_copybreak) {
struct sk_buff *new_skb;
- new_skb = netdev_alloc_skb_ip_align(vptr->dev, pkt_size);
+ new_skb = netdev_alloc_skb_ip_align(vptr->netdev, pkt_size);
if (new_skb) {
new_skb->ip_summed = rx_skb[0]->ip_summed;
skb_copy_from_linear_data(*rx_skb, new_skb->data, pkt_size);
@@ -2024,15 +2049,14 @@ static inline void velocity_iph_realign(struct velocity_info *vptr,
*/
static int velocity_receive_frame(struct velocity_info *vptr, int idx)
{
- void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int);
- struct net_device_stats *stats = &vptr->dev->stats;
+ struct net_device_stats *stats = &vptr->netdev->stats;
struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
struct rx_desc *rd = &(vptr->rx.ring[idx]);
int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff;
struct sk_buff *skb;
if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
- VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->dev->name);
+ VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->netdev->name);
stats->rx_length_errors++;
return -EINVAL;
}
@@ -2042,8 +2066,8 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
skb = rd_info->skb;
- pci_dma_sync_single_for_cpu(vptr->pdev, rd_info->skb_dma,
- vptr->rx.buf_sz, PCI_DMA_FROMDEVICE);
+ dma_sync_single_for_cpu(vptr->dev, rd_info->skb_dma,
+ vptr->rx.buf_sz, DMA_FROM_DEVICE);
/*
* Drop frame not meeting IEEE 802.3
@@ -2056,28 +2080,27 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
}
}
- pci_action = pci_dma_sync_single_for_device;
-
velocity_rx_csum(rd, skb);
if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {
velocity_iph_realign(vptr, skb, pkt_len);
- pci_action = pci_unmap_single;
rd_info->skb = NULL;
+ dma_unmap_single(vptr->dev, rd_info->skb_dma, vptr->rx.buf_sz,
+ DMA_FROM_DEVICE);
+ } else {
+ dma_sync_single_for_device(vptr->dev, rd_info->skb_dma,
+ vptr->rx.buf_sz, DMA_FROM_DEVICE);
}
- pci_action(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz,
- PCI_DMA_FROMDEVICE);
-
skb_put(skb, pkt_len - 4);
- skb->protocol = eth_type_trans(skb, vptr->dev);
+ skb->protocol = eth_type_trans(skb, vptr->netdev);
if (rd->rdesc0.RSR & RSR_DETAG) {
u16 vid = swab16(le16_to_cpu(rd->rdesc1.PQTAG));
- __vlan_hwaccel_put_tag(skb, vid);
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
}
- netif_rx(skb);
+ netif_receive_skb(skb);
stats->rx_bytes += pkt_len;
stats->rx_packets++;
@@ -2095,7 +2118,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
*/
static int velocity_rx_srv(struct velocity_info *vptr, int budget_left)
{
- struct net_device_stats *stats = &vptr->dev->stats;
+ struct net_device_stats *stats = &vptr->netdev->stats;
int rd_curr = vptr->rx.curr;
int works = 0;
@@ -2149,16 +2172,13 @@ static int velocity_poll(struct napi_struct *napi, int budget)
unsigned int rx_done;
unsigned long flags;
- spin_lock_irqsave(&vptr->lock, flags);
/*
* Do rx and tx twice for performance (taken from the VIA
* out-of-tree driver).
*/
- rx_done = velocity_rx_srv(vptr, budget / 2);
- velocity_tx_srv(vptr);
- rx_done += velocity_rx_srv(vptr, budget - rx_done);
+ rx_done = velocity_rx_srv(vptr, budget);
+ spin_lock_irqsave(&vptr->lock, flags);
velocity_tx_srv(vptr);
-
/* If budget not fully consumed, exit the polling mode */
if (rx_done < budget) {
napi_complete(napi);
@@ -2230,15 +2250,15 @@ static int velocity_open(struct net_device *dev)
goto out;
/* Ensure chip is running */
- pci_set_power_state(vptr->pdev, PCI_D0);
+ velocity_set_power_state(vptr, PCI_D0);
velocity_init_registers(vptr, VELOCITY_INIT_COLD);
- ret = request_irq(vptr->pdev->irq, velocity_intr, IRQF_SHARED,
+ ret = request_irq(dev->irq, velocity_intr, IRQF_SHARED,
dev->name, dev);
if (ret < 0) {
/* Power down the chip */
- pci_set_power_state(vptr->pdev, PCI_D3hot);
+ velocity_set_power_state(vptr, PCI_D3hot);
velocity_free_rings(vptr);
goto out;
}
@@ -2287,7 +2307,7 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) {
VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n",
- vptr->dev->name);
+ vptr->netdev->name);
ret = -EINVAL;
goto out_0;
}
@@ -2309,8 +2329,9 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
goto out_0;
}
- tmp_vptr->dev = dev;
+ tmp_vptr->netdev = dev;
tmp_vptr->pdev = vptr->pdev;
+ tmp_vptr->dev = vptr->dev;
tmp_vptr->options = vptr->options;
tmp_vptr->tx.numq = vptr->tx.numq;
@@ -2318,6 +2339,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
if (ret < 0)
goto out_free_tmp_vptr_1;
+ napi_disable(&vptr->napi);
+
spin_lock_irqsave(&vptr->lock, flags);
netif_stop_queue(dev);
@@ -2338,6 +2361,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
velocity_give_many_rx_descs(vptr);
+ napi_enable(&vptr->napi);
+
mac_enable_int(vptr->mac_regs);
netif_start_queue(dev);
@@ -2352,6 +2377,23 @@ out_0:
return ret;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * velocity_poll_controller - Velocity Poll controller function
+ * @dev: network device
+ *
+ *
+ * Used by NETCONSOLE and other diagnostic tools to allow network I/P
+ * with interrupts disabled.
+ */
+static void velocity_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ velocity_intr(dev->irq, dev);
+ enable_irq(dev->irq);
+}
+#endif
+
/**
* velocity_mii_ioctl - MII ioctl handler
* @dev: network device
@@ -2410,7 +2452,7 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
saving then we need to bring the device back up to talk to it */
if (!netif_running(dev))
- pci_set_power_state(vptr->pdev, PCI_D0);
+ velocity_set_power_state(vptr, PCI_D0);
switch (cmd) {
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
@@ -2423,7 +2465,7 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ret = -EOPNOTSUPP;
}
if (!netif_running(dev))
- pci_set_power_state(vptr->pdev, PCI_D3hot);
+ velocity_set_power_state(vptr, PCI_D3hot);
return ret;
@@ -2488,8 +2530,8 @@ static int velocity_close(struct net_device *dev)
if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED)
velocity_get_ip(vptr);
- if (dev->irq != 0)
- free_irq(dev->irq, dev);
+
+ free_irq(dev->irq, dev);
velocity_free_rings(vptr);
@@ -2523,7 +2565,7 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
/* The hardware can handle at most 7 memory segments, so merge
* the skb if there are more */
if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
- kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -2545,7 +2587,8 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
* add it to the transmit ring.
*/
tdinfo->skb = skb;
- tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE);
+ tdinfo->skb_dma[0] = dma_map_single(vptr->dev, skb->data, pktlen,
+ DMA_TO_DEVICE);
td_ptr->tdesc0.len = cpu_to_le16(pktlen);
td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
td_ptr->td_buf[0].pa_high = 0;
@@ -2555,7 +2598,7 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- tdinfo->skb_dma[i + 1] = skb_frag_dma_map(&vptr->pdev->dev,
+ tdinfo->skb_dma[i + 1] = skb_frag_dma_map(vptr->dev,
frag, 0,
skb_frag_size(frag),
DMA_TO_DEVICE);
@@ -2616,6 +2659,9 @@ static const struct net_device_ops velocity_netdev_ops = {
.ndo_do_ioctl = velocity_ioctl,
.ndo_vlan_rx_add_vid = velocity_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = velocity_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = velocity_poll_controller,
+#endif
};
/**
@@ -2627,13 +2673,9 @@ static const struct net_device_ops velocity_netdev_ops = {
* Set up the initial velocity_info struct for the device that has been
* discovered.
*/
-static void __devinit velocity_init_info(struct pci_dev *pdev,
- struct velocity_info *vptr,
- const struct velocity_info_tbl *info)
+static void velocity_init_info(struct velocity_info *vptr,
+ const struct velocity_info_tbl *info)
{
- memset(vptr, 0, sizeof(struct velocity_info));
-
- vptr->pdev = pdev;
vptr->chip_id = info->chip_id;
vptr->tx.numq = info->txqueue;
vptr->multicast_limit = MCAM_SIZE;
@@ -2648,9 +2690,9 @@ static void __devinit velocity_init_info(struct pci_dev *pdev,
* Retrieve the PCI configuration space data that interests us from
* the kernel PCI layer
*/
-static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
+static int velocity_get_pci_info(struct velocity_info *vptr)
{
- vptr->rev_id = pdev->revision;
+ struct pci_dev *pdev = vptr->pdev;
pci_set_master(pdev);
@@ -2673,7 +2715,37 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc
dev_err(&pdev->dev, "region #1 is too small.\n");
return -EINVAL;
}
- vptr->pdev = pdev;
+
+ return 0;
+}
+
+/**
+ * velocity_get_platform_info - retrieve platform info for device
+ * @vptr: velocity device
+ * @pdev: platform device it matches
+ *
+ * Retrieve the Platform configuration data that interests us
+ */
+static int velocity_get_platform_info(struct velocity_info *vptr)
+{
+ struct resource res;
+ int ret;
+
+ if (of_get_property(vptr->dev->of_node, "no-eeprom", NULL))
+ vptr->no_eeprom = 1;
+
+ ret = of_address_to_resource(vptr->dev->of_node, 0, &res);
+ if (ret) {
+ dev_err(vptr->dev, "unable to find memory address\n");
+ return ret;
+ }
+
+ vptr->memaddr = res.start;
+
+ if (resource_size(&res) < VELOCITY_IO_SIZE) {
+ dev_err(vptr->dev, "memory region is too small.\n");
+ return -EINVAL;
+ }
return 0;
}
@@ -2685,9 +2757,9 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc
* Print per driver data as the kernel driver finds Velocity
* hardware
*/
-static void __devinit velocity_print_info(struct velocity_info *vptr)
+static void velocity_print_info(struct velocity_info *vptr)
{
- struct net_device *dev = vptr->dev;
+ struct net_device *dev = vptr->netdev;
printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id));
printk(KERN_INFO "%s: Ethernet Address: %pM\n",
@@ -2702,20 +2774,22 @@ static u32 velocity_get_link(struct net_device *dev)
}
/**
- * velocity_found1 - set up discovered velocity card
+ * velocity_probe - set up discovered velocity device
* @pdev: PCI device
* @ent: PCI device table entry that matched
+ * @bustype: bus that device is connected to
*
* Configure a discovered adapter from scratch. Return a negative
* errno error code on failure paths.
*/
-static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int velocity_probe(struct device *dev, int irq,
+ const struct velocity_info_tbl *info,
+ enum velocity_bus_type bustype)
{
static int first = 1;
- struct net_device *dev;
+ struct net_device *netdev;
int i;
const char *drv_string;
- const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];
struct velocity_info *vptr;
struct mac_regs __iomem *regs;
int ret = -ENOMEM;
@@ -2724,22 +2798,18 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
* can support more than MAX_UNITS.
*/
if (velocity_nics >= MAX_UNITS) {
- dev_notice(&pdev->dev, "already found %d NICs.\n",
- velocity_nics);
+ dev_notice(dev, "already found %d NICs.\n", velocity_nics);
return -ENODEV;
}
- dev = alloc_etherdev(sizeof(struct velocity_info));
- if (!dev) {
- dev_err(&pdev->dev, "allocate net device failed.\n");
+ netdev = alloc_etherdev(sizeof(struct velocity_info));
+ if (!netdev)
goto out;
- }
/* Chain it all together */
- SET_NETDEV_DEV(dev, &pdev->dev);
- vptr = netdev_priv(dev);
-
+ SET_NETDEV_DEV(netdev, dev);
+ vptr = netdev_priv(netdev);
if (first) {
printk(KERN_INFO "%s Ver. %s\n",
@@ -2749,45 +2819,41 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
first = 0;
}
- velocity_init_info(pdev, vptr, info);
-
+ netdev->irq = irq;
+ vptr->netdev = netdev;
vptr->dev = dev;
- ret = pci_enable_device(pdev);
- if (ret < 0)
- goto err_free_dev;
-
- dev->irq = pdev->irq;
+ velocity_init_info(vptr, info);
- ret = velocity_get_pci_info(vptr, pdev);
- if (ret < 0) {
- /* error message already printed */
- goto err_disable;
- }
+ if (bustype == BUS_PCI) {
+ vptr->pdev = to_pci_dev(dev);
- ret = pci_request_regions(pdev, VELOCITY_NAME);
- if (ret < 0) {
- dev_err(&pdev->dev, "No PCI resources.\n");
- goto err_disable;
+ ret = velocity_get_pci_info(vptr);
+ if (ret < 0)
+ goto err_free_dev;
+ } else {
+ vptr->pdev = NULL;
+ ret = velocity_get_platform_info(vptr);
+ if (ret < 0)
+ goto err_free_dev;
}
regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
if (regs == NULL) {
ret = -EIO;
- goto err_release_res;
+ goto err_free_dev;
}
vptr->mac_regs = regs;
+ vptr->rev_id = readb(&regs->rev_id);
mac_wol_reset(regs);
- dev->base_addr = vptr->ioaddr;
-
for (i = 0; i < 6; i++)
- dev->dev_addr[i] = readb(&regs->PAR[i]);
+ netdev->dev_addr[i] = readb(&regs->PAR[i]);
- drv_string = dev_driver_string(&pdev->dev);
+ drv_string = dev_driver_string(dev);
velocity_get_options(&vptr->options, velocity_nics, drv_string);
@@ -2808,46 +2874,127 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
- dev->irq = pdev->irq;
- dev->netdev_ops = &velocity_netdev_ops;
- dev->ethtool_ops = &velocity_ethtool_ops;
- netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
+ netdev->netdev_ops = &velocity_netdev_ops;
+ netdev->ethtool_ops = &velocity_ethtool_ops;
+ netif_napi_add(netdev, &vptr->napi, velocity_poll,
+ VELOCITY_NAPI_WEIGHT);
- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HW_VLAN_TX;
- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
- NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM;
+ netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
+ NETIF_F_HW_VLAN_CTAG_TX;
+ netdev->features |= NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_IP_CSUM;
- ret = register_netdev(dev);
+ ret = register_netdev(netdev);
if (ret < 0)
goto err_iounmap;
- if (!velocity_get_link(dev)) {
- netif_carrier_off(dev);
+ if (!velocity_get_link(netdev)) {
+ netif_carrier_off(netdev);
vptr->mii_status |= VELOCITY_LINK_FAIL;
}
velocity_print_info(vptr);
- pci_set_drvdata(pdev, dev);
+ dev_set_drvdata(vptr->dev, netdev);
/* and leave the chip powered down */
- pci_set_power_state(pdev, PCI_D3hot);
+ velocity_set_power_state(vptr, PCI_D3hot);
velocity_nics++;
out:
return ret;
err_iounmap:
+ netif_napi_del(&vptr->napi);
iounmap(regs);
-err_release_res:
- pci_release_regions(pdev);
-err_disable:
- pci_disable_device(pdev);
err_free_dev:
- free_netdev(dev);
+ free_netdev(netdev);
goto out;
}
-#ifdef CONFIG_PM
+/**
+ * velocity_remove - device unplug
+ * @dev: device being removed
+ *
+ * Device unload callback. Called on an unplug or on module
+ * unload for each active device that is present. Disconnects
+ * the device from the network layer and frees all the resources
+ */
+static int velocity_remove(struct device *dev)
+{
+ struct net_device *netdev = dev_get_drvdata(dev);
+ struct velocity_info *vptr = netdev_priv(netdev);
+
+ unregister_netdev(netdev);
+ netif_napi_del(&vptr->napi);
+ iounmap(vptr->mac_regs);
+ free_netdev(netdev);
+ velocity_nics--;
+
+ return 0;
+}
+
+static int velocity_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ const struct velocity_info_tbl *info =
+ &chip_info_table[ent->driver_data];
+ int ret;
+
+ ret = pci_enable_device(pdev);
+ if (ret < 0)
+ return ret;
+
+ ret = pci_request_regions(pdev, VELOCITY_NAME);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "No PCI resources.\n");
+ goto fail1;
+ }
+
+ ret = velocity_probe(&pdev->dev, pdev->irq, info, BUS_PCI);
+ if (ret == 0)
+ return 0;
+
+ pci_release_regions(pdev);
+fail1:
+ pci_disable_device(pdev);
+ return ret;
+}
+
+static void velocity_pci_remove(struct pci_dev *pdev)
+{
+ velocity_remove(&pdev->dev);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static int velocity_platform_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *of_id;
+ const struct velocity_info_tbl *info;
+ int irq;
+
+ of_id = of_match_device(velocity_of_ids, &pdev->dev);
+ if (!of_id)
+ return -EINVAL;
+ info = of_id->data;
+
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ if (!irq)
+ return -EINVAL;
+
+ return velocity_probe(&pdev->dev, irq, info, BUS_PLATFORM);
+}
+
+static int velocity_platform_remove(struct platform_device *pdev)
+{
+ velocity_remove(&pdev->dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
/**
* wol_calc_crc - WOL CRC
* @pattern: data pattern
@@ -3004,32 +3151,35 @@ static void velocity_save_context(struct velocity_info *vptr, struct velocity_co
}
-static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
+static int velocity_suspend(struct device *dev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct velocity_info *vptr = netdev_priv(dev);
+ struct net_device *netdev = dev_get_drvdata(dev);
+ struct velocity_info *vptr = netdev_priv(netdev);
unsigned long flags;
- if (!netif_running(vptr->dev))
+ if (!netif_running(vptr->netdev))
return 0;
- netif_device_detach(vptr->dev);
+ netif_device_detach(vptr->netdev);
spin_lock_irqsave(&vptr->lock, flags);
- pci_save_state(pdev);
+ if (vptr->pdev)
+ pci_save_state(vptr->pdev);
if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
velocity_get_ip(vptr);
velocity_save_context(vptr, &vptr->context);
velocity_shutdown(vptr);
velocity_set_wol(vptr);
- pci_enable_wake(pdev, PCI_D3hot, 1);
- pci_set_power_state(pdev, PCI_D3hot);
+ if (vptr->pdev)
+ pci_enable_wake(vptr->pdev, PCI_D3hot, 1);
+ velocity_set_power_state(vptr, PCI_D3hot);
} else {
velocity_save_context(vptr, &vptr->context);
velocity_shutdown(vptr);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (vptr->pdev)
+ pci_disable_device(vptr->pdev);
+ velocity_set_power_state(vptr, PCI_D3hot);
}
spin_unlock_irqrestore(&vptr->lock, flags);
@@ -3071,19 +3221,22 @@ static void velocity_restore_context(struct velocity_info *vptr, struct velocity
writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
}
-static int velocity_resume(struct pci_dev *pdev)
+static int velocity_resume(struct device *dev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct velocity_info *vptr = netdev_priv(dev);
+ struct net_device *netdev = dev_get_drvdata(dev);
+ struct velocity_info *vptr = netdev_priv(netdev);
unsigned long flags;
int i;
- if (!netif_running(vptr->dev))
+ if (!netif_running(vptr->netdev))
return 0;
- pci_set_power_state(pdev, PCI_D0);
- pci_enable_wake(pdev, 0, 0);
- pci_restore_state(pdev);
+ velocity_set_power_state(vptr, PCI_D0);
+
+ if (vptr->pdev) {
+ pci_enable_wake(vptr->pdev, PCI_D0, 0);
+ pci_restore_state(vptr->pdev);
+ }
mac_wol_reset(vptr->mac_regs);
@@ -3101,27 +3254,38 @@ static int velocity_resume(struct pci_dev *pdev)
mac_enable_int(vptr->mac_regs);
spin_unlock_irqrestore(&vptr->lock, flags);
- netif_device_attach(vptr->dev);
+ netif_device_attach(vptr->netdev);
return 0;
}
-#endif
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(velocity_pm_ops, velocity_suspend, velocity_resume);
/*
* Definition for our device driver. The PCI layer interface
* uses this to handle all our card discover and plugging
*/
-static struct pci_driver velocity_driver = {
+static struct pci_driver velocity_pci_driver = {
.name = VELOCITY_NAME,
- .id_table = velocity_id_table,
- .probe = velocity_found1,
- .remove = __devexit_p(velocity_remove1),
-#ifdef CONFIG_PM
- .suspend = velocity_suspend,
- .resume = velocity_resume,
-#endif
+ .id_table = velocity_pci_id_table,
+ .probe = velocity_pci_probe,
+ .remove = velocity_pci_remove,
+ .driver = {
+ .pm = &velocity_pm_ops,
+ },
};
+static struct platform_driver velocity_platform_driver = {
+ .probe = velocity_platform_probe,
+ .remove = velocity_platform_remove,
+ .driver = {
+ .name = "via-velocity",
+ .owner = THIS_MODULE,
+ .of_match_table = velocity_of_ids,
+ .pm = &velocity_pm_ops,
+ },
+};
/**
* velocity_ethtool_up - pre hook for ethtool
@@ -3134,7 +3298,7 @@ static int velocity_ethtool_up(struct net_device *dev)
{
struct velocity_info *vptr = netdev_priv(dev);
if (!netif_running(dev))
- pci_set_power_state(vptr->pdev, PCI_D0);
+ velocity_set_power_state(vptr, PCI_D0);
return 0;
}
@@ -3149,7 +3313,7 @@ static void velocity_ethtool_down(struct net_device *dev)
{
struct velocity_info *vptr = netdev_priv(dev);
if (!netif_running(dev))
- pci_set_power_state(vptr->pdev, PCI_D3hot);
+ velocity_set_power_state(vptr, PCI_D3hot);
}
static int velocity_get_settings(struct net_device *dev,
@@ -3269,9 +3433,14 @@ static int velocity_set_settings(struct net_device *dev,
static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct velocity_info *vptr = netdev_priv(dev);
+
strlcpy(info->driver, VELOCITY_NAME, sizeof(info->driver));
strlcpy(info->version, VELOCITY_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, pci_name(vptr->pdev), sizeof(info->bus_info));
+ if (vptr->pdev)
+ strlcpy(info->bus_info, pci_name(vptr->pdev),
+ sizeof(info->bus_info));
+ else
+ strlcpy(info->bus_info, "platform", sizeof(info->bus_info));
}
static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -3561,13 +3730,20 @@ static void velocity_unregister_notifier(void)
*/
static int __init velocity_init_module(void)
{
- int ret;
+ int ret_pci, ret_platform;
velocity_register_notifier();
- ret = pci_register_driver(&velocity_driver);
- if (ret < 0)
+
+ ret_pci = pci_register_driver(&velocity_pci_driver);
+ ret_platform = platform_driver_register(&velocity_platform_driver);
+
+ /* if both_registers failed, remove the notifier */
+ if ((ret_pci < 0) && (ret_platform < 0)) {
velocity_unregister_notifier();
- return ret;
+ return ret_pci;
+ }
+
+ return 0;
}
/**
@@ -3581,7 +3757,9 @@ static int __init velocity_init_module(void)
static void __exit velocity_cleanup_module(void)
{
velocity_unregister_notifier();
- pci_unregister_driver(&velocity_driver);
+
+ pci_unregister_driver(&velocity_pci_driver);
+ platform_driver_unregister(&velocity_platform_driver);
}
module_init(velocity_init_module);
diff --git a/drivers/net/ethernet/via/via-velocity.h b/drivers/net/ethernet/via/via-velocity.h
index 4cb9f13485e..9453bfa9324 100644
--- a/drivers/net/ethernet/via/via-velocity.h
+++ b/drivers/net/ethernet/via/via-velocity.h
@@ -1265,7 +1265,7 @@ struct velocity_context {
#define PHYID_VT3216_64BIT 0x000FC600UL
#define PHYID_MARVELL_1000 0x01410C50UL
#define PHYID_MARVELL_1000S 0x01410C40UL
-
+#define PHYID_ICPLUS_IP101A 0x02430C54UL
#define PHYID_REV_ID_MASK 0x0000000FUL
#define PHYID_GET_PHY_ID(i) ((i) & ~PHYID_REV_ID_MASK)
@@ -1434,8 +1434,10 @@ struct velocity_opt {
#define GET_RD_BY_IDX(vptr, idx) (vptr->rd_ring[idx])
struct velocity_info {
+ struct device *dev;
struct pci_dev *pdev;
- struct net_device *dev;
+ struct net_device *netdev;
+ int no_eeprom;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u8 ip_addr[4];
@@ -1514,7 +1516,7 @@ static inline int velocity_get_ip(struct velocity_info *vptr)
int res = -ENOENT;
rcu_read_lock();
- in_dev = __in_dev_get_rcu(vptr->dev);
+ in_dev = __in_dev_get_rcu(vptr->netdev);
if (in_dev != NULL) {
ifa = (struct in_ifaddr *) in_dev->ifa_list;
if (ifa != NULL) {