diff options
Diffstat (limited to 'drivers/net/8139too.c')
-rw-r--r-- | drivers/net/8139too.c | 138 |
1 files changed, 74 insertions, 64 deletions
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 75317a14ad1..8a5b0d293f7 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -98,7 +98,6 @@ #include <linux/compiler.h> #include <linux/pci.h> #include <linux/init.h> -#include <linux/ioport.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> @@ -120,11 +119,6 @@ NETIF_MSG_LINK) -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - /* define to 1, 2 or 3 to enable copious debugging info */ #define RTL8139_DEBUG 0 @@ -156,6 +150,13 @@ static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +/* Whether to use MMIO or PIO. Default to MMIO. */ +#ifdef CONFIG_8139TOO_PIO +static int use_io = 1; +#else +static int use_io = 0; +#endif + /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). The RTL chips use a 64 element hash table based on the Ethernet CRC. */ static int multicast_filter_limit = 32; @@ -614,6 +615,8 @@ MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +module_param(use_io, int, 0); +MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); module_param(multicast_filter_limit, int, 0); module_param_array(media, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); @@ -709,13 +712,8 @@ static void __rtl8139_cleanup_dev (struct net_device *dev) assert (tp->pci_dev != NULL); pdev = tp->pci_dev; -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else if (tp->mmio_addr) pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ /* it's ok to call this even if we have no regions to free */ pci_release_regions (pdev); @@ -790,32 +788,33 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev, DPRINTK("PIO region size == 0x%02X\n", pio_len); DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; +retry: + if (use_io) { + /* make sure PCI base addr 0 is PIO */ + if (!(pio_flags & IORESOURCE_IO)) { + dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); + rc = -ENODEV; + goto err_out; + } + /* check for weird/broken PCI region reporting */ + if (pio_len < RTL_MIN_IO_SIZE) { + dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); + rc = -ENODEV; + goto err_out; + } + } else { + /* make sure PCI base addr 1 is MMIO */ + if (!(mmio_flags & IORESOURCE_MEM)) { + dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); + rc = -ENODEV; + goto err_out; + } + if (mmio_len < RTL_MIN_IO_SIZE) { + dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); + rc = -ENODEV; + goto err_out; + } } -#endif rc = pci_request_regions (pdev, DRV_NAME); if (rc) @@ -825,28 +824,28 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev, /* enable PCI bus-mastering */ pci_set_master (pdev); -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; + if (use_io) { + ioaddr = pci_iomap(pdev, 0, 0); + if (!ioaddr) { + dev_err(&pdev->dev, "cannot map PIO, aborting\n"); + rc = -EIO; + goto err_out; + } + dev->base_addr = pio_start; + tp->regs_len = pio_len; + } else { + /* ioremap MMIO region */ + ioaddr = pci_iomap(pdev, 1, 0); + if (ioaddr == NULL) { + dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); + pci_release_regions(pdev); + use_io = 1; + goto retry; + } + dev->base_addr = (long) ioaddr; + tp->regs_len = mmio_len; } - dev->base_addr = (long) ioaddr; tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ /* Bring old chips out of low-power mode. */ RTL_W8 (HltClk, 'R'); @@ -952,6 +951,14 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, "Use the \"8139cp\" driver for improved performance and stability.\n"); } + if (pdev->vendor == PCI_VENDOR_ID_REALTEK && + pdev->device == PCI_DEVICE_ID_REALTEK_8139 && + pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && + pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { + printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n"); + use_io = 1; + } + i = rtl8139_init_board (pdev, &dev); if (i < 0) return i; @@ -2381,20 +2388,24 @@ static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) np->msg_enable = datum; } -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else static int rtl8139_get_regs_len(struct net_device *dev) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *np; + /* TODO: we are too slack to do reg dumping for pio, for now */ + if (use_io) + return 0; + np = netdev_priv(dev); return np->regs_len; } static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *np; + + /* TODO: we are too slack to do reg dumping for pio, for now */ + if (use_io) + return; + np = netdev_priv(dev); regs->version = RTL_REGS_VER; @@ -2402,7 +2413,6 @@ static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, memcpy_fromio(regbuf, np->mmio_addr, regs->len); spin_unlock_irq(&np->lock); } -#endif /* CONFIG_8139TOO_MMIO */ static int rtl8139_get_sset_count(struct net_device *dev, int sset) { |