* Re: [patch 2.6.13 2/2] 3c59x: add option for using memory-mapped PCI I/O resources
From: Andrew Morton @ 2005-09-06 23:13 UTC (permalink / raw)
To: John W. Linville; +Cc: hch, linux-kernel, netdev, jgarzik
In-Reply-To: <20050906225744.GB26003@tuxdriver.com>
"John W. Linville" <linville@tuxdriver.com> wrote:
>
> On Tue, Sep 06, 2005 at 03:15:46PM -0700, Andrew Morton wrote:
> > "John W. Linville" <linville@tuxdriver.com> wrote:
> > >
> > > I fully intend to have have a flag in the private data set based on
> > > the PCI ID when I accumulate some data on which devices support this
> > > and which don't. So far I've only got a short list... Do you think
> > > such a flag should be based on which ones work, or which ones break?
> >
> > The ones which are known to work.
> >
> > Bear in mind that this is an old, messy and relatively stable driver which
> > handles a huge number of different NICs. Caution is the rule here.
>
> I definitely agree. That is another part of why I defaulted to "use_mmio=0".
>
> I'll post PCI ID based patches as I determine supported cards.
>
What I'd suggest you do is to look at enabling the feature for, say,
IS_CYCLONE and IS_TORNADO NICs. Do that as a separate -mm patch, make sure
that an explicit `use_mmio=0' will still turn it off.
So in the style of that driver, something like:
static int use_mmio[MAX_UNITS] = { [ 0 .. MAX_UNITS-1 ] = -1, };
Then:
if (module parm given)
use_mmio[unit] = 1 or 0
...
/* Determine the default if the user didn't override us */
if (use_mmio[unit] == -1 && (IS_CYCLONE || IS_TORNADO))
use_mmio[unit] = 1;
priv->use_mmio = use_mmio[unit]; (maybe)
....
if (priv->use_mmio == 1)
do mmio stuff
There's a bit to be done here, so I'll drop your initial set of patches.
btw, Donald Becker's 3c59x.c has done mmio for ages. Suggest you take a
look in there. http://www.scyld.com/vortex.html
^ permalink raw reply
* Re: proto_unregister sleeps while atomic
From: David S. Miller @ 2005-09-06 23:07 UTC (permalink / raw)
To: kaber; +Cc: daniele, linux-kernel, netdev
In-Reply-To: <431E1FE9.7030405@trash.net>
From: Patrick McHardy <kaber@trash.net>
Date: Wed, 07 Sep 2005 01:02:01 +0200
> You're right, good catch. This patch fixes it by moving the lock
> down to the list-operation which it is supposed to protect.
I think we need to unlink from the list first if you're
going to do it this way. Otherwise someone can find the
protocol via lookup, and then bogusly try to use the SLAB
cache we're freeing up.
Or does something else prevent this?
^ permalink raw reply
* Re: proto_unregister sleeps while atomic
From: Patrick McHardy @ 2005-09-06 23:02 UTC (permalink / raw)
To: Daniele Orlandi; +Cc: linux-kernel, Kernel Netdev Mailing List, David S. Miller
In-Reply-To: <200509070026.34999.daniele@orlandi.com>
[-- Attachment #1: Type: text/plain, Size: 650 bytes --]
Daniele Orlandi wrote:
> I'm looking at proto_unregister() in linux-2.6.13:
>
> Il calls kmem_cache_destroy() while holding proto_list_lock:
>
> void proto_unregister(struct proto *prot)
> {
> write_lock(&proto_list_lock);
>
> if (prot->slab != NULL) {
> kmem_cache_destroy(prot->slab);
>
>
> However, kmem_cache_destroy() may sleep:
>
> /* Find the cache in the chain of caches. */
> down(&cache_chain_sem);
> ^^^^^^^^^^^^^^^^^^^^^^^
>
> Am I seeing it right?
You're right, good catch. This patch fixes it by moving the lock
down to the list-operation which it is supposed to protect.
[-- Attachment #2: x --]
[-- Type: text/plain, Size: 1111 bytes --]
[NET]: proto_unregister: fix sleeping while atomic
proto_unregister holds a lock while calling kmem_cache_destroy, which can
sleep.
Noticed by Daniele Orlandi <daniele@orlandi.com>.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit 90fdf8bc78b52d40190766c5496a3d8c24903be8
tree 54048218d981ab263b37e0de09ad52f4bd49a000
parent 591bd554f58b7d363167760a606d2a84696772da
author Patrick McHardy <kaber@trash.net> Wed, 07 Sep 2005 01:00:00 +0200
committer Patrick McHardy <kaber@trash.net> Wed, 07 Sep 2005 01:00:00 +0200
net/core/sock.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1528,8 +1528,6 @@ EXPORT_SYMBOL(proto_register);
void proto_unregister(struct proto *prot)
{
- write_lock(&proto_list_lock);
-
if (prot->slab != NULL) {
kmem_cache_destroy(prot->slab);
prot->slab = NULL;
@@ -1551,6 +1549,7 @@ void proto_unregister(struct proto *prot
prot->twsk_slab = NULL;
}
+ write_lock(&proto_list_lock);
list_del(&prot->node);
write_unlock(&proto_list_lock);
}
^ permalink raw reply
* Re: [patch 2.6.13 2/2] 3c59x: add option for using memory-mapped PCI I/O resources
From: John W. Linville @ 2005-09-06 22:57 UTC (permalink / raw)
To: Andrew Morton; +Cc: hch, linux-kernel, netdev, jgarzik
In-Reply-To: <20050906151546.4d5ed4db.akpm@osdl.org>
On Tue, Sep 06, 2005 at 03:15:46PM -0700, Andrew Morton wrote:
> "John W. Linville" <linville@tuxdriver.com> wrote:
> >
> > I fully intend to have have a flag in the private data set based on
> > the PCI ID when I accumulate some data on which devices support this
> > and which don't. So far I've only got a short list... Do you think
> > such a flag should be based on which ones work, or which ones break?
>
> The ones which are known to work.
>
> Bear in mind that this is an old, messy and relatively stable driver which
> handles a huge number of different NICs. Caution is the rule here.
I definitely agree. That is another part of why I defaulted to "use_mmio=0".
I'll post PCI ID based patches as I determine supported cards.
Thanks,
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: [patch 2.6.13 2/2] 3c59x: add option for using memory-mapped PCI I/O resources
From: Andrew Morton @ 2005-09-06 22:15 UTC (permalink / raw)
To: John W. Linville; +Cc: hch, linux-kernel, netdev, jgarzik
In-Reply-To: <20050906220922.GA26003@tuxdriver.com>
"John W. Linville" <linville@tuxdriver.com> wrote:
>
> I fully intend to have have a flag in the private data set based on
> the PCI ID when I accumulate some data on which devices support this
> and which don't. So far I've only got a short list... Do you think
> such a flag should be based on which ones work, or which ones break?
The ones which are known to work.
Bear in mind that this is an old, messy and relatively stable driver which
handles a huge number of different NICs. Caution is the rule here.
^ permalink raw reply
* Re: [patch 2.6.13 2/2] 3c59x: add option for using memory-mapped PCI I/O resources
From: Andrew Morton @ 2005-09-06 21:04 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-kernel, netdev, jgarzik
In-Reply-To: <20050906205429.GA19319@infradead.org>
Christoph Hellwig <hch@infradead.org> wrote:
>
> On Tue, Sep 06, 2005 at 04:44:00PM -0400, John W. Linville wrote:
> > Add module option to enable 3c59x driver to use memory-mapped PCI I/O
> > resources. This may improve performance for those devices so equipped.
> >
> > Add "use_mmio=1" to the 3c59x module options in order to enable this
> > functionality.
>
> I'm not sure a module option makes sense for this setting, except maybe
> as a debugging aid. You should rather have a flag in the PCI IDs private
> data that can be used to enable mmio for those cards that support it.
I guess it's OK for the initial testing. Plus we should make the new
feature default to "on" during initial public testing. I'll make that
change.
^ permalink raw reply
* Re: [patch 2.6.13 2/2] 3c59x: add option for using memory-mapped PCI I/O resources
From: Christoph Hellwig @ 2005-09-06 20:54 UTC (permalink / raw)
To: linux-kernel, netdev, akpm, jgarzik
In-Reply-To: <20050906204400.GD20145@tuxdriver.com>
On Tue, Sep 06, 2005 at 04:44:00PM -0400, John W. Linville wrote:
> Add module option to enable 3c59x driver to use memory-mapped PCI I/O
> resources. This may improve performance for those devices so equipped.
>
> Add "use_mmio=1" to the 3c59x module options in order to enable this
> functionality.
I'm not sure a module option makes sense for this setting, except maybe
as a debugging aid. You should rather have a flag in the PCI IDs private
data that can be used to enable mmio for those cards that support it.
^ permalink raw reply
* [patch 2.6.13 2/2] 3c59x: add option for using memory-mapped PCI I/O resources
From: John W. Linville @ 2005-09-06 20:44 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, akpm, jgarzik
In-Reply-To: <20050906204147.GC20145@tuxdriver.com>
Add module option to enable 3c59x driver to use memory-mapped PCI I/O
resources. This may improve performance for those devices so equipped.
Add "use_mmio=1" to the 3c59x module options in order to enable this
functionality.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
Ideally this option will eventually go away. First we need a good list
of which devices "work" and which ones do not.
drivers/net/3c59x.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -918,6 +918,9 @@ static int global_enable_wol = -1;
static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900;
static struct net_device *compaq_net_device;
+/* Flag to enable use of memory-mapped PCI I/O resource */
+static int use_mmio;
+
static int vortex_cards_found;
module_param(debug, int, 0);
@@ -935,6 +938,7 @@ module_param(compaq_ioaddr, int, 0);
module_param(compaq_irq, int, 0);
module_param(compaq_device_id, int, 0);
module_param(watchdog, int, 0);
+module_param(use_mmio, int, 0);
MODULE_PARM_DESC(debug, "3c59x debug level (0-6)");
MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex");
MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset");
@@ -950,6 +954,7 @@ MODULE_PARM_DESC(compaq_ioaddr, "3c59x P
MODULE_PARM_DESC(compaq_irq, "3c59x PCI IRQ number (Compaq BIOS problem workaround)");
MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem workaround)");
MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds");
+MODULE_PARM_DESC(use_mmio, "3c59x: use memory-mapped PCI I/O resource");
#ifdef CONFIG_NET_POLL_CONTROLLER
static void poll_vortex(struct net_device *dev)
@@ -1093,14 +1098,16 @@ static int __init vortex_eisa_init (void
static int __devinit vortex_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- int rc;
+ int rc, pci_bar;
/* wake up and enable device */
rc = pci_enable_device (pdev);
if (rc < 0)
goto out;
- rc = vortex_probe1 (&pdev->dev, pci_iomap(pdev, 0, 0),
+ pci_bar = use_mmio ? 1 : 0;
+
+ rc = vortex_probe1 (&pdev->dev, pci_iomap(pdev, pci_bar, 0),
pdev->irq, ent->driver_data, vortex_cards_found);
if (rc < 0) {
pci_disable_device (pdev);
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* [patch 2.6.13 1/2] 3c59x: convert to use of pci_iomap API
From: John W. Linville @ 2005-09-06 20:41 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, akpm, jgarzik
Convert 3c59x driver to use pci_iomap API. This makes it easier to
enable the use of memory-mapped PCI I/O resources.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/3c59x.c | 507 ++++++++++++++++++++++++++--------------------------
1 files changed, 260 insertions(+), 247 deletions(-)
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -602,7 +602,7 @@ MODULE_DEVICE_TABLE(pci, vortex_pci_tbl)
First the windows. There are eight register windows, with the command
and status registers available in each.
*/
-#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+#define EL3WINDOW(win_num) iowrite16(SelectWindow + (win_num), ioaddr + EL3_CMD)
#define EL3_CMD 0x0e
#define EL3_STATUS 0x0e
@@ -776,7 +776,8 @@ struct vortex_private {
/* PCI configuration space information. */
struct device *gendev;
- char __iomem *cb_fn_base; /* CardBus function status addr space. */
+ void __iomem *ioaddr; /* IO address space */
+ void __iomem *cb_fn_base; /* CardBus function status addr space. */
/* Some values here only for performance evaluation and path-coverage */
int rx_nocopy, rx_copy, queued_packet, rx_csumhits;
@@ -869,12 +870,12 @@ static struct {
/* number of ETHTOOL_GSTATS u64's */
#define VORTEX_NUM_STATS 3
-static int vortex_probe1(struct device *gendev, long ioaddr, int irq,
+static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
int chip_idx, int card_idx);
static void vortex_up(struct net_device *dev);
static void vortex_down(struct net_device *dev, int final);
static int vortex_open(struct net_device *dev);
-static void mdio_sync(long ioaddr, int bits);
+static void mdio_sync(void __iomem *ioaddr, int bits);
static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *vp, int phy_id, int location, int value);
static void vortex_timer(unsigned long arg);
@@ -887,7 +888,7 @@ static irqreturn_t vortex_interrupt(int
static irqreturn_t boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int vortex_close(struct net_device *dev);
static void dump_tx_ring(struct net_device *dev);
-static void update_stats(long ioaddr, struct net_device *dev);
+static void update_stats(void __iomem *ioaddr, struct net_device *dev);
static struct net_device_stats *vortex_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
#ifdef CONFIG_PCI
@@ -1013,18 +1014,19 @@ static struct eisa_driver vortex_eisa_dr
static int vortex_eisa_probe (struct device *device)
{
- long ioaddr;
+ void __iomem *ioaddr;
struct eisa_device *edev;
edev = to_eisa_device (device);
- ioaddr = edev->base_addr;
- if (!request_region(ioaddr, VORTEX_TOTAL_SIZE, DRV_NAME))
+ if (!request_region(edev->base_addr, VORTEX_TOTAL_SIZE, DRV_NAME))
return -EBUSY;
- if (vortex_probe1(device, ioaddr, inw(ioaddr + 0xC88) >> 12,
+ ioaddr = ioport_map(edev->base_addr, VORTEX_TOTAL_SIZE);
+
+ if (vortex_probe1(device, ioaddr, ioread16(ioaddr + 0xC88) >> 12,
edev->id.driver_data, vortex_cards_found)) {
- release_region (ioaddr, VORTEX_TOTAL_SIZE);
+ release_region (edev->base_addr, VORTEX_TOTAL_SIZE);
return -ENODEV;
}
@@ -1038,7 +1040,7 @@ static int vortex_eisa_remove (struct de
struct eisa_device *edev;
struct net_device *dev;
struct vortex_private *vp;
- long ioaddr;
+ void __iomem *ioaddr;
edev = to_eisa_device (device);
dev = eisa_get_drvdata (edev);
@@ -1049,11 +1051,11 @@ static int vortex_eisa_remove (struct de
}
vp = netdev_priv(dev);
- ioaddr = dev->base_addr;
+ ioaddr = vp->ioaddr;
unregister_netdev (dev);
- outw (TotalReset|0x14, ioaddr + EL3_CMD);
- release_region (ioaddr, VORTEX_TOTAL_SIZE);
+ iowrite16 (TotalReset|0x14, ioaddr + EL3_CMD);
+ release_region (dev->base_addr, VORTEX_TOTAL_SIZE);
free_netdev (dev);
return 0;
@@ -1080,8 +1082,8 @@ static int __init vortex_eisa_init (void
/* Special code to work-around the Compaq PCI BIOS32 problem. */
if (compaq_ioaddr) {
- vortex_probe1(NULL, compaq_ioaddr, compaq_irq,
- compaq_device_id, vortex_cards_found++);
+ vortex_probe1(NULL, ioport_map(compaq_ioaddr, VORTEX_TOTAL_SIZE),
+ compaq_irq, compaq_device_id, vortex_cards_found++);
}
return vortex_cards_found - orig_cards_found + eisa_found;
@@ -1098,8 +1100,8 @@ static int __devinit vortex_init_one (st
if (rc < 0)
goto out;
- rc = vortex_probe1 (&pdev->dev, pci_resource_start (pdev, 0),
- pdev->irq, ent->driver_data, vortex_cards_found);
+ rc = vortex_probe1 (&pdev->dev, pci_iomap(pdev, 0, 0),
+ pdev->irq, ent->driver_data, vortex_cards_found);
if (rc < 0) {
pci_disable_device (pdev);
goto out;
@@ -1118,7 +1120,7 @@ out:
* NOTE: pdev can be NULL, for the case of a Compaq device
*/
static int __devinit vortex_probe1(struct device *gendev,
- long ioaddr, int irq,
+ void __iomem *ioaddr, int irq,
int chip_idx, int card_idx)
{
struct vortex_private *vp;
@@ -1186,15 +1188,16 @@ static int __devinit vortex_probe1(struc
if (print_info)
printk (KERN_INFO "See Documentation/networking/vortex.txt\n");
- printk(KERN_INFO "%s: 3Com %s %s at 0x%lx. Vers " DRV_VERSION "\n",
+ printk(KERN_INFO "%s: 3Com %s %s at %p. Vers " DRV_VERSION "\n",
print_name,
pdev ? "PCI" : "EISA",
vci->name,
ioaddr);
- dev->base_addr = ioaddr;
+ dev->base_addr = (unsigned long)ioaddr;
dev->irq = irq;
dev->mtu = mtu;
+ vp->ioaddr = ioaddr;
vp->large_frames = mtu > 1500;
vp->drv_flags = vci->drv_flags;
vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
@@ -1210,7 +1213,7 @@ static int __devinit vortex_probe1(struc
if (pdev) {
/* EISA resources already marked, so only PCI needs to do this here */
/* Ignore return value, because Cardbus drivers already allocate for us */
- if (request_region(ioaddr, vci->io_size, print_name) != NULL)
+ if (request_region(dev->base_addr, vci->io_size, print_name) != NULL)
vp->must_free_region = 1;
/* enable bus-mastering if necessary */
@@ -1300,14 +1303,14 @@ static int __devinit vortex_probe1(struc
for (i = 0; i < 0x40; i++) {
int timer;
- outw(base + i, ioaddr + Wn0EepromCmd);
+ iowrite16(base + i, ioaddr + Wn0EepromCmd);
/* Pause for at least 162 us. for the read to take place. */
for (timer = 10; timer >= 0; timer--) {
udelay(162);
- if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
+ if ((ioread16(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
break;
}
- eeprom[i] = inw(ioaddr + Wn0EepromData);
+ eeprom[i] = ioread16(ioaddr + Wn0EepromData);
}
}
for (i = 0; i < 0x18; i++)
@@ -1335,7 +1338,7 @@ static int __devinit vortex_probe1(struc
}
EL3WINDOW(2);
for (i = 0; i < 6; i++)
- outb(dev->dev_addr[i], ioaddr + i);
+ iowrite8(dev->dev_addr[i], ioaddr + i);
#ifdef __sparc__
if (print_info)
@@ -1350,7 +1353,7 @@ static int __devinit vortex_probe1(struc
#endif
EL3WINDOW(4);
- step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
+ step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
if (print_info) {
printk(KERN_INFO " product code %02x%02x rev %02x.%d date %02d-"
"%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
@@ -1359,31 +1362,30 @@ static int __devinit vortex_probe1(struc
if (pdev && vci->drv_flags & HAS_CB_FNS) {
- unsigned long fn_st_addr; /* Cardbus function status space */
unsigned short n;
- fn_st_addr = pci_resource_start (pdev, 2);
- if (fn_st_addr) {
- vp->cb_fn_base = ioremap(fn_st_addr, 128);
+ vp->cb_fn_base = pci_iomap(pdev, 2, 0);
+ if (!vp->cb_fn_base) {
retval = -ENOMEM;
- if (!vp->cb_fn_base)
- goto free_ring;
+ goto free_ring;
}
+
if (print_info) {
printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n",
- print_name, fn_st_addr, vp->cb_fn_base);
+ print_name, pci_resource_start(pdev, 2),
+ vp->cb_fn_base);
}
EL3WINDOW(2);
- n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;
+ n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010;
if (vp->drv_flags & INVERT_LED_PWR)
n |= 0x10;
if (vp->drv_flags & INVERT_MII_PWR)
n |= 0x4000;
- outw(n, ioaddr + Wn2_ResetOptions);
+ iowrite16(n, ioaddr + Wn2_ResetOptions);
if (vp->drv_flags & WNO_XCVR_PWR) {
EL3WINDOW(0);
- outw(0x0800, ioaddr);
+ iowrite16(0x0800, ioaddr);
}
}
@@ -1402,13 +1404,13 @@ static int __devinit vortex_probe1(struc
static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
unsigned int config;
EL3WINDOW(3);
- vp->available_media = inw(ioaddr + Wn3_Options);
+ vp->available_media = ioread16(ioaddr + Wn3_Options);
if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */
vp->available_media = 0x40;
- config = inl(ioaddr + Wn3_Config);
+ config = ioread32(ioaddr + Wn3_Config);
if (print_info) {
printk(KERN_DEBUG " Internal config register is %4.4x, "
- "transceivers %#x.\n", config, inw(ioaddr + Wn3_Options));
+ "transceivers %#x.\n", config, ioread16(ioaddr + Wn3_Options));
printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
8 << RAM_SIZE(config),
RAM_WIDTH(config) ? "word" : "byte",
@@ -1539,7 +1541,7 @@ free_ring:
vp->rx_ring_dma);
free_region:
if (vp->must_free_region)
- release_region(ioaddr, vci->io_size);
+ release_region(dev->base_addr, vci->io_size);
free_netdev(dev);
printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval);
out:
@@ -1549,17 +1551,19 @@ out:
static void
issue_and_wait(struct net_device *dev, int cmd)
{
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
int i;
- outw(cmd, dev->base_addr + EL3_CMD);
+ iowrite16(cmd, ioaddr + EL3_CMD);
for (i = 0; i < 2000; i++) {
- if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))
+ if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress))
return;
}
/* OK, that didn't work. Do it the slow way. One second */
for (i = 0; i < 100000; i++) {
- if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) {
+ if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) {
if (vortex_debug > 1)
printk(KERN_INFO "%s: command 0x%04x took %d usecs\n",
dev->name, cmd, i * 10);
@@ -1568,14 +1572,14 @@ issue_and_wait(struct net_device *dev, i
udelay(10);
}
printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n",
- dev->name, cmd, inw(dev->base_addr + EL3_STATUS));
+ dev->name, cmd, ioread16(ioaddr + EL3_STATUS));
}
static void
vortex_up(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
unsigned int config;
int i;
@@ -1588,7 +1592,7 @@ vortex_up(struct net_device *dev)
/* Before initializing select the active media port. */
EL3WINDOW(3);
- config = inl(ioaddr + Wn3_Config);
+ config = ioread32(ioaddr + Wn3_Config);
if (vp->media_override != 7) {
printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",
@@ -1635,7 +1639,7 @@ vortex_up(struct net_device *dev)
config = BFINS(config, dev->if_port, 20, 4);
if (vortex_debug > 6)
printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config);
- outl(config, ioaddr + Wn3_Config);
+ iowrite32(config, ioaddr + Wn3_Config);
if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
int mii_reg1, mii_reg5;
@@ -1663,7 +1667,7 @@ vortex_up(struct net_device *dev)
}
/* Set the full-duplex bit. */
- outw( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
+ iowrite16( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
(vp->large_frames ? 0x40 : 0) |
((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
ioaddr + Wn3_MAC_Ctrl);
@@ -1679,51 +1683,51 @@ vortex_up(struct net_device *dev)
*/
issue_and_wait(dev, RxReset|0x04);
- outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+ iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
if (vortex_debug > 1) {
EL3WINDOW(4);
printk(KERN_DEBUG "%s: vortex_up() irq %d media status %4.4x.\n",
- dev->name, dev->irq, inw(ioaddr + Wn4_Media));
+ dev->name, dev->irq, ioread16(ioaddr + Wn4_Media));
}
/* Set the station address and mask in window 2 each time opened. */
EL3WINDOW(2);
for (i = 0; i < 6; i++)
- outb(dev->dev_addr[i], ioaddr + i);
+ iowrite8(dev->dev_addr[i], ioaddr + i);
for (; i < 12; i+=2)
- outw(0, ioaddr + i);
+ iowrite16(0, ioaddr + i);
if (vp->cb_fn_base) {
- unsigned short n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;
+ unsigned short n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010;
if (vp->drv_flags & INVERT_LED_PWR)
n |= 0x10;
if (vp->drv_flags & INVERT_MII_PWR)
n |= 0x4000;
- outw(n, ioaddr + Wn2_ResetOptions);
+ iowrite16(n, ioaddr + Wn2_ResetOptions);
}
if (dev->if_port == XCVR_10base2)
/* Start the thinnet transceiver. We should really wait 50ms...*/
- outw(StartCoax, ioaddr + EL3_CMD);
+ iowrite16(StartCoax, ioaddr + EL3_CMD);
if (dev->if_port != XCVR_NWAY) {
EL3WINDOW(4);
- outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
+ iowrite16((ioread16(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
}
/* Switch to the stats window, and clear all stats by reading. */
- outw(StatsDisable, ioaddr + EL3_CMD);
+ iowrite16(StatsDisable, ioaddr + EL3_CMD);
EL3WINDOW(6);
for (i = 0; i < 10; i++)
- inb(ioaddr + i);
- inw(ioaddr + 10);
- inw(ioaddr + 12);
+ ioread8(ioaddr + i);
+ ioread16(ioaddr + 10);
+ ioread16(ioaddr + 12);
/* New: On the Vortex we must also clear the BadSSD counter. */
EL3WINDOW(4);
- inb(ioaddr + 12);
+ ioread8(ioaddr + 12);
/* ..and on the Boomerang we enable the extra statistics bits. */
- outw(0x0040, ioaddr + Wn4_NetDiag);
+ iowrite16(0x0040, ioaddr + Wn4_NetDiag);
/* Switch to register set 7 for normal use. */
EL3WINDOW(7);
@@ -1731,30 +1735,30 @@ vortex_up(struct net_device *dev)
if (vp->full_bus_master_rx) { /* Boomerang bus master. */
vp->cur_rx = vp->dirty_rx = 0;
/* Initialize the RxEarly register as recommended. */
- outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
- outl(0x0020, ioaddr + PktStatus);
- outl(vp->rx_ring_dma, ioaddr + UpListPtr);
+ iowrite16(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ iowrite32(0x0020, ioaddr + PktStatus);
+ iowrite32(vp->rx_ring_dma, ioaddr + UpListPtr);
}
if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
vp->cur_tx = vp->dirty_tx = 0;
if (vp->drv_flags & IS_BOOMERANG)
- outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
+ iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
/* Clear the Rx, Tx rings. */
for (i = 0; i < RX_RING_SIZE; i++) /* AKPM: this is done in vortex_open, too */
vp->rx_ring[i].status = 0;
for (i = 0; i < TX_RING_SIZE; i++)
vp->tx_skbuff[i] = NULL;
- outl(0, ioaddr + DownListPtr);
+ iowrite32(0, ioaddr + DownListPtr);
}
/* Set receiver mode: presumably accept b-case and phys addr only. */
set_rx_mode(dev);
/* enable 802.1q tagged frames */
set_8021q_mode(dev, 1);
- outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+ iowrite16(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
// issue_and_wait(dev, SetTxStart|0x07ff);
- outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
- outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+ iowrite16(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+ iowrite16(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
/* Allow status bits to be seen. */
vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete|
(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
@@ -1764,13 +1768,13 @@ vortex_up(struct net_device *dev)
(vp->full_bus_master_rx ? 0 : RxComplete) |
StatsFull | HostError | TxComplete | IntReq
| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
- outw(vp->status_enable, ioaddr + EL3_CMD);
+ iowrite16(vp->status_enable, ioaddr + EL3_CMD);
/* Ack all pending events, and set active indicator mask. */
- outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+ iowrite16(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
ioaddr + EL3_CMD);
- outw(vp->intr_enable, ioaddr + EL3_CMD);
+ iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
- writel(0x8000, vp->cb_fn_base + 4);
+ iowrite32(0x8000, vp->cb_fn_base + 4);
netif_start_queue (dev);
}
@@ -1836,7 +1840,7 @@ vortex_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int next_tick = 60*HZ;
int ok = 0;
int media_status, mii_status, old_window;
@@ -1850,9 +1854,9 @@ vortex_timer(unsigned long data)
if (vp->medialock)
goto leave_media_alone;
disable_irq(dev->irq);
- old_window = inw(ioaddr + EL3_CMD) >> 13;
+ old_window = ioread16(ioaddr + EL3_CMD) >> 13;
EL3WINDOW(4);
- media_status = inw(ioaddr + Wn4_Media);
+ media_status = ioread16(ioaddr + Wn4_Media);
switch (dev->if_port) {
case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
if (media_status & Media_LnkBeat) {
@@ -1892,7 +1896,7 @@ vortex_timer(unsigned long data)
vp->phys[0], mii_reg5);
/* Set the full-duplex bit. */
EL3WINDOW(3);
- outw( (vp->full_duplex ? 0x20 : 0) |
+ iowrite16( (vp->full_duplex ? 0x20 : 0) |
(vp->large_frames ? 0x40 : 0) |
((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
ioaddr + Wn3_MAC_Ctrl);
@@ -1933,15 +1937,15 @@ vortex_timer(unsigned long data)
dev->name, media_tbl[dev->if_port].name);
next_tick = media_tbl[dev->if_port].wait;
}
- outw((media_status & ~(Media_10TP|Media_SQE)) |
+ iowrite16((media_status & ~(Media_10TP|Media_SQE)) |
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
EL3WINDOW(3);
- config = inl(ioaddr + Wn3_Config);
+ config = ioread32(ioaddr + Wn3_Config);
config = BFINS(config, dev->if_port, 20, 4);
- outl(config, ioaddr + Wn3_Config);
+ iowrite32(config, ioaddr + Wn3_Config);
- outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
+ iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
ioaddr + EL3_CMD);
if (vortex_debug > 1)
printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config);
@@ -1957,29 +1961,29 @@ leave_media_alone:
mod_timer(&vp->timer, RUN_AT(next_tick));
if (vp->deferred)
- outw(FakeIntr, ioaddr + EL3_CMD);
+ iowrite16(FakeIntr, ioaddr + EL3_CMD);
return;
}
static void vortex_tx_timeout(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
- dev->name, inb(ioaddr + TxStatus),
- inw(ioaddr + EL3_STATUS));
+ dev->name, ioread8(ioaddr + TxStatus),
+ ioread16(ioaddr + EL3_STATUS));
EL3WINDOW(4);
printk(KERN_ERR " diagnostics: net %04x media %04x dma %08x fifo %04x\n",
- inw(ioaddr + Wn4_NetDiag),
- inw(ioaddr + Wn4_Media),
- inl(ioaddr + PktStatus),
- inw(ioaddr + Wn4_FIFODiag));
+ ioread16(ioaddr + Wn4_NetDiag),
+ ioread16(ioaddr + Wn4_Media),
+ ioread32(ioaddr + PktStatus),
+ ioread16(ioaddr + Wn4_FIFODiag));
/* Slight code bloat to be user friendly. */
- if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
+ if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88)
printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
" network cable problem?\n", dev->name);
- if (inw(ioaddr + EL3_STATUS) & IntLatch) {
+ if (ioread16(ioaddr + EL3_STATUS) & IntLatch) {
printk(KERN_ERR "%s: Interrupt posted but not delivered --"
" IRQ blocked by another device?\n", dev->name);
/* Bad idea here.. but we might as well handle a few events. */
@@ -2005,21 +2009,21 @@ static void vortex_tx_timeout(struct net
vp->stats.tx_errors++;
if (vp->full_bus_master_tx) {
printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n", dev->name);
- if (vp->cur_tx - vp->dirty_tx > 0 && inl(ioaddr + DownListPtr) == 0)
- outl(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
+ if (vp->cur_tx - vp->dirty_tx > 0 && ioread32(ioaddr + DownListPtr) == 0)
+ iowrite32(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
ioaddr + DownListPtr);
if (vp->cur_tx - vp->dirty_tx < TX_RING_SIZE)
netif_wake_queue (dev);
if (vp->drv_flags & IS_BOOMERANG)
- outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
- outw(DownUnstall, ioaddr + EL3_CMD);
+ iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
+ iowrite16(DownUnstall, ioaddr + EL3_CMD);
} else {
vp->stats.tx_dropped++;
netif_wake_queue(dev);
}
/* Issue Tx Enable */
- outw(TxEnable, ioaddr + EL3_CMD);
+ iowrite16(TxEnable, ioaddr + EL3_CMD);
dev->trans_start = jiffies;
/* Switch to register set 7 for normal use. */
@@ -2034,7 +2038,7 @@ static void
vortex_error(struct net_device *dev, int status)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int do_tx_reset = 0, reset_mask = 0;
unsigned char tx_status = 0;
@@ -2043,7 +2047,7 @@ vortex_error(struct net_device *dev, int
}
if (status & TxComplete) { /* Really "TxError" for us. */
- tx_status = inb(ioaddr + TxStatus);
+ tx_status = ioread8(ioaddr + TxStatus);
/* Presumably a tx-timeout. We must merely re-enable. */
if (vortex_debug > 2
|| (tx_status != 0x88 && vortex_debug > 0)) {
@@ -2057,20 +2061,20 @@ vortex_error(struct net_device *dev, int
}
if (tx_status & 0x14) vp->stats.tx_fifo_errors++;
if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
- outb(0, ioaddr + TxStatus);
+ iowrite8(0, ioaddr + TxStatus);
if (tx_status & 0x30) { /* txJabber or txUnderrun */
do_tx_reset = 1;
} else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */
do_tx_reset = 1;
reset_mask = 0x0108; /* Reset interface logic, but not download logic */
} else { /* Merely re-enable the transmitter. */
- outw(TxEnable, ioaddr + EL3_CMD);
+ iowrite16(TxEnable, ioaddr + EL3_CMD);
}
}
if (status & RxEarly) { /* Rx early is unused. */
vortex_rx(dev);
- outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD);
}
if (status & StatsFull) { /* Empty statistics. */
static int DoneDidThat;
@@ -2080,29 +2084,29 @@ vortex_error(struct net_device *dev, int
/* HACK: Disable statistics as an interrupt source. */
/* This occurs when we have the wrong media type! */
if (DoneDidThat == 0 &&
- inw(ioaddr + EL3_STATUS) & StatsFull) {
+ ioread16(ioaddr + EL3_STATUS) & StatsFull) {
printk(KERN_WARNING "%s: Updating statistics failed, disabling "
"stats as an interrupt source.\n", dev->name);
EL3WINDOW(5);
- outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);
+ iowrite16(SetIntrEnb | (ioread16(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);
vp->intr_enable &= ~StatsFull;
EL3WINDOW(7);
DoneDidThat++;
}
}
if (status & IntReq) { /* Restore all interrupt sources. */
- outw(vp->status_enable, ioaddr + EL3_CMD);
- outw(vp->intr_enable, ioaddr + EL3_CMD);
+ iowrite16(vp->status_enable, ioaddr + EL3_CMD);
+ iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
}
if (status & HostError) {
u16 fifo_diag;
EL3WINDOW(4);
- fifo_diag = inw(ioaddr + Wn4_FIFODiag);
+ fifo_diag = ioread16(ioaddr + Wn4_FIFODiag);
printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n",
dev->name, fifo_diag);
/* Adapter failure requires Tx/Rx reset and reinit. */
if (vp->full_bus_master_tx) {
- int bus_status = inl(ioaddr + PktStatus);
+ int bus_status = ioread32(ioaddr + PktStatus);
/* 0x80000000 PCI master abort. */
/* 0x40000000 PCI target abort. */
if (vortex_debug)
@@ -2122,14 +2126,14 @@ vortex_error(struct net_device *dev, int
set_rx_mode(dev);
/* enable 802.1q VLAN tagged frames */
set_8021q_mode(dev, 1);
- outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
- outw(AckIntr | HostError, ioaddr + EL3_CMD);
+ iowrite16(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+ iowrite16(AckIntr | HostError, ioaddr + EL3_CMD);
}
}
if (do_tx_reset) {
issue_and_wait(dev, TxReset|reset_mask);
- outw(TxEnable, ioaddr + EL3_CMD);
+ iowrite16(TxEnable, ioaddr + EL3_CMD);
if (!vp->full_bus_master_tx)
netif_wake_queue(dev);
}
@@ -2139,29 +2143,29 @@ static int
vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
/* Put out the doubleword header... */
- outl(skb->len, ioaddr + TX_FIFO);
+ iowrite32(skb->len, ioaddr + TX_FIFO);
if (vp->bus_master) {
/* Set the bus-master controller to transfer the packet. */
int len = (skb->len + 3) & ~3;
- outl( vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE),
+ iowrite32( vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE),
ioaddr + Wn7_MasterAddr);
- outw(len, ioaddr + Wn7_MasterLen);
+ iowrite16(len, ioaddr + Wn7_MasterLen);
vp->tx_skb = skb;
- outw(StartDMADown, ioaddr + EL3_CMD);
+ iowrite16(StartDMADown, ioaddr + EL3_CMD);
/* netif_wake_queue() will be called at the DMADone interrupt. */
} else {
/* ... and the packet rounded to a doubleword. */
- outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+ iowrite32_rep(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
dev_kfree_skb (skb);
- if (inw(ioaddr + TxFree) > 1536) {
+ if (ioread16(ioaddr + TxFree) > 1536) {
netif_start_queue (dev); /* AKPM: redundant? */
} else {
/* Interrupt us when the FIFO has room for max-sized packet. */
netif_stop_queue(dev);
- outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
}
}
@@ -2172,7 +2176,7 @@ vortex_start_xmit(struct sk_buff *skb, s
int tx_status;
int i = 32;
- while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
+ while (--i > 0 && (tx_status = ioread8(ioaddr + TxStatus)) > 0) {
if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n",
@@ -2182,9 +2186,9 @@ vortex_start_xmit(struct sk_buff *skb, s
if (tx_status & 0x30) {
issue_and_wait(dev, TxReset);
}
- outw(TxEnable, ioaddr + EL3_CMD);
+ iowrite16(TxEnable, ioaddr + EL3_CMD);
}
- outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
+ iowrite8(0x00, ioaddr + TxStatus); /* Pop the status stack. */
}
}
return 0;
@@ -2194,7 +2198,7 @@ static int
boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
/* Calculate the next Tx descriptor entry. */
int entry = vp->cur_tx % TX_RING_SIZE;
struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
@@ -2258,8 +2262,8 @@ boomerang_start_xmit(struct sk_buff *skb
/* Wait for the stall to complete. */
issue_and_wait(dev, DownStall);
prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc));
- if (inl(ioaddr + DownListPtr) == 0) {
- outl(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
+ if (ioread32(ioaddr + DownListPtr) == 0) {
+ iowrite32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
vp->queued_packet++;
}
@@ -2274,7 +2278,7 @@ boomerang_start_xmit(struct sk_buff *skb
prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
#endif
}
- outw(DownUnstall, ioaddr + EL3_CMD);
+ iowrite16(DownUnstall, ioaddr + EL3_CMD);
spin_unlock_irqrestore(&vp->lock, flags);
dev->trans_start = jiffies;
return 0;
@@ -2293,15 +2297,15 @@ vortex_interrupt(int irq, void *dev_id,
{
struct net_device *dev = dev_id;
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr;
+ void __iomem *ioaddr;
int status;
int work_done = max_interrupt_work;
int handled = 0;
- ioaddr = dev->base_addr;
+ ioaddr = vp->ioaddr;
spin_lock(&vp->lock);
- status = inw(ioaddr + EL3_STATUS);
+ status = ioread16(ioaddr + EL3_STATUS);
if (vortex_debug > 6)
printk("vortex_interrupt(). status=0x%4x\n", status);
@@ -2320,7 +2324,7 @@ vortex_interrupt(int irq, void *dev_id,
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
- dev->name, status, inb(ioaddr + Timer));
+ dev->name, status, ioread8(ioaddr + Timer));
do {
if (vortex_debug > 5)
@@ -2333,16 +2337,16 @@ vortex_interrupt(int irq, void *dev_id,
if (vortex_debug > 5)
printk(KERN_DEBUG " TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
- outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | TxAvailable, ioaddr + EL3_CMD);
netif_wake_queue (dev);
}
if (status & DMADone) {
- if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
- outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+ if (ioread16(ioaddr + Wn7_MasterStatus) & 0x1000) {
+ iowrite16(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
- if (inw(ioaddr + TxFree) > 1536) {
+ if (ioread16(ioaddr + TxFree) > 1536) {
/*
* AKPM: FIXME: I don't think we need this. If the queue was stopped due to
* insufficient FIFO room, the TxAvailable test will succeed and call
@@ -2350,7 +2354,7 @@ vortex_interrupt(int irq, void *dev_id,
*/
netif_wake_queue(dev);
} else { /* Interrupt when FIFO has room for max-sized packet. */
- outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
netif_stop_queue(dev);
}
}
@@ -2368,17 +2372,17 @@ vortex_interrupt(int irq, void *dev_id,
/* Disable all pending interrupts. */
do {
vp->deferred |= status;
- outw(SetStatusEnb | (~vp->deferred & vp->status_enable),
+ iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable),
ioaddr + EL3_CMD);
- outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
- } while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
+ iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
+ } while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch);
/* The timer will reenable interrupts. */
mod_timer(&vp->timer, jiffies + 1*HZ);
break;
}
/* Acknowledge the IRQ. */
- outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
- } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+ iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+ } while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
@@ -2398,11 +2402,11 @@ boomerang_interrupt(int irq, void *dev_i
{
struct net_device *dev = dev_id;
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr;
+ void __iomem *ioaddr;
int status;
int work_done = max_interrupt_work;
- ioaddr = dev->base_addr;
+ ioaddr = vp->ioaddr;
/*
* It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout
@@ -2410,7 +2414,7 @@ boomerang_interrupt(int irq, void *dev_i
*/
spin_lock(&vp->lock);
- status = inw(ioaddr + EL3_STATUS);
+ status = ioread16(ioaddr + EL3_STATUS);
if (vortex_debug > 6)
printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status);
@@ -2431,13 +2435,13 @@ boomerang_interrupt(int irq, void *dev_i
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
- dev->name, status, inb(ioaddr + Timer));
+ dev->name, status, ioread8(ioaddr + Timer));
do {
if (vortex_debug > 5)
printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
dev->name, status);
if (status & UpComplete) {
- outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | UpComplete, ioaddr + EL3_CMD);
if (vortex_debug > 5)
printk(KERN_DEBUG "boomerang_interrupt->boomerang_rx\n");
boomerang_rx(dev);
@@ -2446,11 +2450,11 @@ boomerang_interrupt(int irq, void *dev_i
if (status & DownComplete) {
unsigned int dirty_tx = vp->dirty_tx;
- outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | DownComplete, ioaddr + EL3_CMD);
while (vp->cur_tx - dirty_tx > 0) {
int entry = dirty_tx % TX_RING_SIZE;
#if 1 /* AKPM: the latter is faster, but cyclone-only */
- if (inl(ioaddr + DownListPtr) ==
+ if (ioread32(ioaddr + DownListPtr) ==
vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc))
break; /* It still hasn't been processed. */
#else
@@ -2497,20 +2501,20 @@ boomerang_interrupt(int irq, void *dev_i
/* Disable all pending interrupts. */
do {
vp->deferred |= status;
- outw(SetStatusEnb | (~vp->deferred & vp->status_enable),
+ iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable),
ioaddr + EL3_CMD);
- outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
- } while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
+ iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
+ } while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch);
/* The timer will reenable interrupts. */
mod_timer(&vp->timer, jiffies + 1*HZ);
break;
}
/* Acknowledge the IRQ. */
- outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
- writel(0x8000, vp->cb_fn_base + 4);
+ iowrite32(0x8000, vp->cb_fn_base + 4);
- } while ((status = inw(ioaddr + EL3_STATUS)) & IntLatch);
+ } while ((status = ioread16(ioaddr + EL3_STATUS)) & IntLatch);
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
@@ -2523,16 +2527,16 @@ handler_exit:
static int vortex_rx(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int i;
short rx_status;
if (vortex_debug > 5)
printk(KERN_DEBUG "vortex_rx(): status %4.4x, rx_status %4.4x.\n",
- inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
- while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
+ ioread16(ioaddr+EL3_STATUS), ioread16(ioaddr+RxStatus));
+ while ((rx_status = ioread16(ioaddr + RxStatus)) > 0) {
if (rx_status & 0x4000) { /* Error, update stats. */
- unsigned char rx_error = inb(ioaddr + RxErrors);
+ unsigned char rx_error = ioread8(ioaddr + RxErrors);
if (vortex_debug > 2)
printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error);
vp->stats.rx_errors++;
@@ -2555,27 +2559,28 @@ static int vortex_rx(struct net_device *
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
if (vp->bus_master &&
- ! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
+ ! (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)) {
dma_addr_t dma = pci_map_single(VORTEX_PCI(vp), skb_put(skb, pkt_len),
pkt_len, PCI_DMA_FROMDEVICE);
- outl(dma, ioaddr + Wn7_MasterAddr);
- outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
- outw(StartDMAUp, ioaddr + EL3_CMD);
- while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
+ iowrite32(dma, ioaddr + Wn7_MasterAddr);
+ iowrite16((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+ iowrite16(StartDMAUp, ioaddr + EL3_CMD);
+ while (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)
;
pci_unmap_single(VORTEX_PCI(vp), dma, pkt_len, PCI_DMA_FROMDEVICE);
} else {
- insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
- (pkt_len + 3) >> 2);
+ ioread32_rep(ioaddr + RX_FIFO,
+ skb_put(skb, pkt_len),
+ (pkt_len + 3) >> 2);
}
- outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+ iowrite16(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
vp->stats.rx_packets++;
/* Wait a limited time to go to next packet. */
for (i = 200; i >= 0; i--)
- if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ if ( ! (ioread16(ioaddr + EL3_STATUS) & CmdInProgress))
break;
continue;
} else if (vortex_debug > 0)
@@ -2594,12 +2599,12 @@ boomerang_rx(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
int entry = vp->cur_rx % RX_RING_SIZE;
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int rx_status;
int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
if (vortex_debug > 5)
- printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", inw(ioaddr+EL3_STATUS));
+ printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS));
while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
if (--rx_work_limit < 0)
@@ -2682,7 +2687,7 @@ boomerang_rx(struct net_device *dev)
vp->rx_skbuff[entry] = skb;
}
vp->rx_ring[entry].status = 0; /* Clear complete bit. */
- outw(UpUnstall, ioaddr + EL3_CMD);
+ iowrite16(UpUnstall, ioaddr + EL3_CMD);
}
return 0;
}
@@ -2711,7 +2716,7 @@ static void
vortex_down(struct net_device *dev, int final_down)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
netif_stop_queue (dev);
@@ -2719,26 +2724,26 @@ vortex_down(struct net_device *dev, int
del_timer_sync(&vp->timer);
/* Turn off statistics ASAP. We update vp->stats below. */
- outw(StatsDisable, ioaddr + EL3_CMD);
+ iowrite16(StatsDisable, ioaddr + EL3_CMD);
/* Disable the receiver and transmitter. */
- outw(RxDisable, ioaddr + EL3_CMD);
- outw(TxDisable, ioaddr + EL3_CMD);
+ iowrite16(RxDisable, ioaddr + EL3_CMD);
+ iowrite16(TxDisable, ioaddr + EL3_CMD);
/* Disable receiving 802.1q tagged frames */
set_8021q_mode(dev, 0);
if (dev->if_port == XCVR_10base2)
/* Turn off thinnet power. Green! */
- outw(StopCoax, ioaddr + EL3_CMD);
+ iowrite16(StopCoax, ioaddr + EL3_CMD);
- outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
+ iowrite16(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
update_stats(ioaddr, dev);
if (vp->full_bus_master_rx)
- outl(0, ioaddr + UpListPtr);
+ iowrite32(0, ioaddr + UpListPtr);
if (vp->full_bus_master_tx)
- outl(0, ioaddr + DownListPtr);
+ iowrite32(0, ioaddr + DownListPtr);
if (final_down && VORTEX_PCI(vp)) {
vp->pm_state_valid = 1;
@@ -2751,7 +2756,7 @@ static int
vortex_close(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int i;
if (netif_device_present(dev))
@@ -2759,7 +2764,7 @@ vortex_close(struct net_device *dev)
if (vortex_debug > 1) {
printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
- dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus));
+ dev->name, ioread16(ioaddr + EL3_STATUS), ioread8(ioaddr + TxStatus));
printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d"
" tx_queued %d Rx pre-checksummed %d.\n",
dev->name, vp->rx_nocopy, vp->rx_copy, vp->queued_packet, vp->rx_csumhits);
@@ -2813,18 +2818,18 @@ dump_tx_ring(struct net_device *dev)
{
if (vortex_debug > 0) {
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
if (vp->full_bus_master_tx) {
int i;
- int stalled = inl(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */
+ int stalled = ioread32(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */
printk(KERN_ERR " Flags; bus-master %d, dirty %d(%d) current %d(%d)\n",
vp->full_bus_master_tx,
vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE,
vp->cur_tx, vp->cur_tx % TX_RING_SIZE);
printk(KERN_ERR " Transmit list %8.8x vs. %p.\n",
- inl(ioaddr + DownListPtr),
+ ioread32(ioaddr + DownListPtr),
&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
issue_and_wait(dev, DownStall);
for (i = 0; i < TX_RING_SIZE; i++) {
@@ -2838,7 +2843,7 @@ dump_tx_ring(struct net_device *dev)
le32_to_cpu(vp->tx_ring[i].status));
}
if (!stalled)
- outw(DownUnstall, ioaddr + EL3_CMD);
+ iowrite16(DownUnstall, ioaddr + EL3_CMD);
}
}
}
@@ -2846,11 +2851,12 @@ dump_tx_ring(struct net_device *dev)
static struct net_device_stats *vortex_get_stats(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
if (netif_device_present(dev)) { /* AKPM: Used to be netif_running */
spin_lock_irqsave (&vp->lock, flags);
- update_stats(dev->base_addr, dev);
+ update_stats(ioaddr, dev);
spin_unlock_irqrestore (&vp->lock, flags);
}
return &vp->stats;
@@ -2863,37 +2869,37 @@ static struct net_device_stats *vortex_g
table. This is done by checking that the ASM (!) code generated uses
atomic updates with '+='.
*/
-static void update_stats(long ioaddr, struct net_device *dev)
+static void update_stats(void __iomem *ioaddr, struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- int old_window = inw(ioaddr + EL3_CMD);
+ int old_window = ioread16(ioaddr + EL3_CMD);
if (old_window == 0xffff) /* Chip suspended or ejected. */
return;
/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
/* Switch to the stats window, and read everything. */
EL3WINDOW(6);
- vp->stats.tx_carrier_errors += inb(ioaddr + 0);
- vp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
- vp->stats.collisions += inb(ioaddr + 3);
- vp->stats.tx_window_errors += inb(ioaddr + 4);
- vp->stats.rx_fifo_errors += inb(ioaddr + 5);
- vp->stats.tx_packets += inb(ioaddr + 6);
- vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4;
- /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */
+ vp->stats.tx_carrier_errors += ioread8(ioaddr + 0);
+ vp->stats.tx_heartbeat_errors += ioread8(ioaddr + 1);
+ vp->stats.collisions += ioread8(ioaddr + 3);
+ vp->stats.tx_window_errors += ioread8(ioaddr + 4);
+ vp->stats.rx_fifo_errors += ioread8(ioaddr + 5);
+ vp->stats.tx_packets += ioread8(ioaddr + 6);
+ vp->stats.tx_packets += (ioread8(ioaddr + 9)&0x30) << 4;
+ /* Rx packets */ ioread8(ioaddr + 7); /* Must read to clear */
/* Don't bother with register 9, an extension of registers 6&7.
If we do use the 6&7 values the atomic update assumption above
is invalid. */
- vp->stats.rx_bytes += inw(ioaddr + 10);
- vp->stats.tx_bytes += inw(ioaddr + 12);
+ vp->stats.rx_bytes += ioread16(ioaddr + 10);
+ vp->stats.tx_bytes += ioread16(ioaddr + 12);
/* Extra stats for get_ethtool_stats() */
- vp->xstats.tx_multiple_collisions += inb(ioaddr + 2);
- vp->xstats.tx_deferred += inb(ioaddr + 8);
+ vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2);
+ vp->xstats.tx_deferred += ioread8(ioaddr + 8);
EL3WINDOW(4);
- vp->xstats.rx_bad_ssd += inb(ioaddr + 12);
+ vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12);
{
- u8 up = inb(ioaddr + 13);
+ u8 up = ioread8(ioaddr + 13);
vp->stats.rx_bytes += (up & 0x0f) << 16;
vp->stats.tx_bytes += (up & 0xf0) << 12;
}
@@ -2905,7 +2911,7 @@ static void update_stats(long ioaddr, st
static int vortex_nway_reset(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int rc;
@@ -2919,7 +2925,7 @@ static int vortex_nway_reset(struct net_
static u32 vortex_get_link(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int rc;
@@ -2933,7 +2939,7 @@ static u32 vortex_get_link(struct net_de
static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int rc;
@@ -2947,7 +2953,7 @@ static int vortex_get_settings(struct ne
static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int rc;
@@ -2977,10 +2983,11 @@ static void vortex_get_ethtool_stats(str
struct ethtool_stats *stats, u64 *data)
{
struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
spin_lock_irqsave(&vp->lock, flags);
- update_stats(dev->base_addr, dev);
+ update_stats(ioaddr, dev);
spin_unlock_irqrestore(&vp->lock, flags);
data[0] = vp->xstats.tx_deferred;
@@ -3040,7 +3047,7 @@ static int vortex_ioctl(struct net_devic
{
int err;
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int state = 0;
@@ -3068,7 +3075,8 @@ static int vortex_ioctl(struct net_devic
the chip has a very clean way to set the mode, unlike many others. */
static void set_rx_mode(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
int new_mode;
if (dev->flags & IFF_PROMISC) {
@@ -3080,7 +3088,7 @@ static void set_rx_mode(struct net_devic
} else
new_mode = SetRxFilter | RxStation | RxBroadcast;
- outw(new_mode, ioaddr + EL3_CMD);
+ iowrite16(new_mode, ioaddr + EL3_CMD);
}
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
@@ -3094,8 +3102,8 @@ static void set_rx_mode(struct net_devic
static void set_8021q_mode(struct net_device *dev, int enable)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
- int old_window = inw(ioaddr + EL3_CMD);
+ void __iomem *ioaddr = vp->ioaddr;
+ int old_window = ioread16(ioaddr + EL3_CMD);
int mac_ctrl;
if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) {
@@ -3107,24 +3115,24 @@ static void set_8021q_mode(struct net_de
max_pkt_size += 4; /* 802.1Q VLAN tag */
EL3WINDOW(3);
- outw(max_pkt_size, ioaddr+Wn3_MaxPktSize);
+ iowrite16(max_pkt_size, ioaddr+Wn3_MaxPktSize);
/* set VlanEtherType to let the hardware checksumming
treat tagged frames correctly */
EL3WINDOW(7);
- outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
+ iowrite16(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
} else {
/* on older cards we have to enable large frames */
vp->large_frames = dev->mtu > 1500 || enable;
EL3WINDOW(3);
- mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl);
+ mac_ctrl = ioread16(ioaddr+Wn3_MAC_Ctrl);
if (vp->large_frames)
mac_ctrl |= 0x40;
else
mac_ctrl &= ~0x40;
- outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
+ iowrite16(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
}
EL3WINDOW(old_window);
@@ -3146,7 +3154,7 @@ static void set_8021q_mode(struct net_de
/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
met by back-to-back PCI I/O cycles, but we insert a delay to avoid
"overclocking" issues. */
-#define mdio_delay() inl(mdio_addr)
+#define mdio_delay() ioread32(mdio_addr)
#define MDIO_SHIFT_CLK 0x01
#define MDIO_DIR_WRITE 0x04
@@ -3157,15 +3165,15 @@ static void set_8021q_mode(struct net_de
/* Generate the preamble required for initial synchronization and
a few older transceivers. */
-static void mdio_sync(long ioaddr, int bits)
+static void mdio_sync(void __iomem *ioaddr, int bits)
{
- long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
/* Establish sync by sending at least 32 logic ones. */
while (-- bits >= 0) {
- outw(MDIO_DATA_WRITE1, mdio_addr);
+ iowrite16(MDIO_DATA_WRITE1, mdio_addr);
mdio_delay();
- outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ iowrite16(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
}
@@ -3173,10 +3181,11 @@ static void mdio_sync(long ioaddr, int b
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
int i;
- long ioaddr = dev->base_addr;
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
unsigned int retval = 0;
- long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
if (mii_preamble_required)
mdio_sync(ioaddr, 32);
@@ -3184,17 +3193,17 @@ static int mdio_read(struct net_device *
/* Shift the read command bits out. */
for (i = 14; i >= 0; i--) {
int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
- outw(dataval, mdio_addr);
+ iowrite16(dataval, mdio_addr);
mdio_delay();
- outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+ iowrite16(dataval | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
/* Read the two transition, 16 data, and wire-idle bits. */
for (i = 19; i > 0; i--) {
- outw(MDIO_ENB_IN, mdio_addr);
+ iowrite16(MDIO_ENB_IN, mdio_addr);
mdio_delay();
- retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
- outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ retval = (retval << 1) | ((ioread16(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+ iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
@@ -3202,9 +3211,10 @@ static int mdio_read(struct net_device *
static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
{
- long ioaddr = dev->base_addr;
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
- long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
int i;
if (mii_preamble_required)
@@ -3213,16 +3223,16 @@ static void mdio_write(struct net_device
/* Shift the command bits out. */
for (i = 31; i >= 0; i--) {
int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
- outw(dataval, mdio_addr);
+ iowrite16(dataval, mdio_addr);
mdio_delay();
- outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+ iowrite16(dataval | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
/* Leave the interface idle. */
for (i = 1; i >= 0; i--) {
- outw(MDIO_ENB_IN, mdio_addr);
+ iowrite16(MDIO_ENB_IN, mdio_addr);
mdio_delay();
- outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
return;
@@ -3233,15 +3243,15 @@ static void mdio_write(struct net_device
static void acpi_set_WOL(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
if (vp->enable_wol) {
/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
EL3WINDOW(7);
- outw(2, ioaddr + 0x0c);
+ iowrite16(2, ioaddr + 0x0c);
/* The RxFilter must accept the WOL frames. */
- outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
- outw(RxEnable, ioaddr + EL3_CMD);
+ iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
+ iowrite16(RxEnable, ioaddr + EL3_CMD);
pci_enable_wake(VORTEX_PCI(vp), 0, 1);
@@ -3263,10 +3273,9 @@ static void __devexit vortex_remove_one
vp = netdev_priv(dev);
- /* AKPM: FIXME: we should have
- * if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
- * here
- */
+ if (vp->cb_fn_base)
+ pci_iounmap(VORTEX_PCI(vp), vp->cb_fn_base);
+
unregister_netdev(dev);
if (VORTEX_PCI(vp)) {
@@ -3276,8 +3285,10 @@ static void __devexit vortex_remove_one
pci_disable_device(VORTEX_PCI(vp));
}
/* Should really use issue_and_wait() here */
- outw(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
- dev->base_addr + EL3_CMD);
+ iowrite16(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
+ vp->ioaddr + EL3_CMD);
+
+ pci_iounmap(VORTEX_PCI(vp), vp->ioaddr);
pci_free_consistent(pdev,
sizeof(struct boom_rx_desc) * RX_RING_SIZE
@@ -3325,7 +3336,7 @@ static int __init vortex_init (void)
static void __exit vortex_eisa_cleanup (void)
{
struct vortex_private *vp;
- long ioaddr;
+ void __iomem *ioaddr;
#ifdef CONFIG_EISA
/* Take care of the EISA devices */
@@ -3334,11 +3345,13 @@ static void __exit vortex_eisa_cleanup (
if (compaq_net_device) {
vp = compaq_net_device->priv;
- ioaddr = compaq_net_device->base_addr;
+ ioaddr = ioport_map(compaq_net_device->base_addr,
+ VORTEX_TOTAL_SIZE);
unregister_netdev (compaq_net_device);
- outw (TotalReset, ioaddr + EL3_CMD);
- release_region (ioaddr, VORTEX_TOTAL_SIZE);
+ iowrite16 (TotalReset, ioaddr + EL3_CMD);
+ release_region(compaq_net_device->base_addr,
+ VORTEX_TOTAL_SIZE);
free_netdev (compaq_net_device);
}
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* RE: [PATCH] wrong firmware location in IPW2100 Kconfig entry (Was: IPW2100 Kconfig)
From: Alejandro Bonilla @ 2005-09-06 18:51 UTC (permalink / raw)
To: 'Jesper Juhl'
Cc: netdev, linux-kernel, ipw2100-admin, 'Roman Zippel',
'Sam Ravnborg'
In-Reply-To: <200509062048.29495.jesper.juhl@gmail.com>
> > Who should I send the "patch" to? Or can someone simply change that?
Jesper,
Thanks. I also had a question. To whom is this patch sent to? Netdev or LK?
How does one determine?
.Alejandro
>
> Firmware should go into /lib/firmware, not /etc/firmware.
>
> Found by Alejandro Bonilla.
>
>
> Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
^ permalink raw reply
* [PATCH] wrong firmware location in IPW2100 Kconfig entry (Was: IPW2100 Kconfig)
From: Jesper Juhl @ 2005-09-06 18:48 UTC (permalink / raw)
To: Alejandro Bonilla
Cc: netdev, linux-kernel, ipw2100-admin, Roman Zippel, Sam Ravnborg
In-Reply-To: <005101c5b311$4ca69a50$a20cc60a@amer.sykes.com>
On Tuesday 06 September 2005 20:32, Alejandro Bonilla wrote:
> Hi,
>
> I checked the IPW2100 in the current git from linux-2.6 and the menuconfig
> help (Kconfig) says you need to put the firmware in /etc/firmware, it should
> be /lib/firmware.
>
> Who should I send the "patch" to? Or can someone simply change that?
>
Firmware should go into /lib/firmware, not /etc/firmware.
Found by Alejandro Bonilla.
Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
---
drivers/net/wireless/Kconfig | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
--- linux-2.6.13-mm1-orig/drivers/net/wireless/Kconfig 2005-09-02 23:59:51.000000000 +0200
+++ linux-2.6.13-mm1/drivers/net/wireless/Kconfig 2005-09-06 20:39:45.000000000 +0200
@@ -152,7 +152,7 @@
In order to use this driver, you will need a firmware image for it.
You can obtain the firmware from
<http://ipw2100.sf.net/>. Once you have the firmware image, you
- will need to place it in /etc/firmware.
+ will need to place it in /lib/firmware.
You will also very likely need the Wireless Tools in order to
configure your card:
^ permalink raw reply
* IPW2100 Kconfig
From: Alejandro Bonilla @ 2005-09-06 18:32 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel
Hi,
I checked the IPW2100 in the current git from linux-2.6 and the menuconfig
help (Kconfig) says you need to put the firmware in /etc/firmware, it should
be /lib/firmware.
Who should I send the "patch" to? Or can someone simply change that?
Thanks,
.Alejandro
^ permalink raw reply
* Re: Modifying Cryptography Code
From: Aidas Kasparas @ 2005-09-06 15:24 UTC (permalink / raw)
To: Alaa Dalghan; +Cc: linux-security-module, linux-crypto, linux-net, netdev
In-Reply-To: <BAY106-F336464E0C97EA44289AA87ABA70@phx.gbl>
Alaa Dalghan wrote:
> imposes too much processing overhead on the linux VPN gateway. The
> required behavior is that the VPN gateway just RELAYS encrypted data
> (ESP envelopes) without decrypting them. This is impossible in the
> current ipsec implementation since"the end of a tunnel HAS ALWAYS to be
> decrypted".
>
That can work only in case when you set esp's encryption keys manually
and the same on all 30 your clients. Also, SPIs should be the same. I
would not call such setup secure.
Better way is to put all these clients into single subnet and configure
them to require transport mode esp transformation in that subnet +
employ automatic keying and auth by certs. And required subset of these
scarry 900 tunnels will set up automatically. [Don't ask me how to
configure this setup in windows -- I don't know].
> I hope that someone can help me with finding this portion of the code
> and modify it. By the way I searched in the kernel file "esp4.c" but
> can't seem to find what I want.
Check xfrm*.c files, also net/xfrm directory.
--
Aidas Kasparas
IT administrator
GM Consult Group, UAB
^ permalink raw reply
* Re: Modifying Cryptography Code
From: Martijn van Oosterhout @ 2005-09-06 15:24 UTC (permalink / raw)
To: Alaa Dalghan; +Cc: linux-security-module, linux-crypto, linux-net, netdev
In-Reply-To: <BAY106-F336464E0C97EA44289AA87ABA70@phx.gbl>
[-- Attachment #1: Type: text/plain, Size: 1381 bytes --]
On Tue, Sep 06, 2005 at 01:56:56PM +0000, Alaa Dalghan wrote:
> Hello everyone,
> I need to modify some CRYPTOGRAPHY code in Linux Kernel to get a specific
> VPN behavior, but I don't know where to start.
<snip>
> Each packet sent from a given client to the other get processed 4 times
> (encryption at the sender, decryption at the gateway, encryption at the
> gateway, decryption at the receiver). This is the normal behavior but it
> imposes too much processing overhead on the linux VPN gateway. The required
> behavior is that the VPN gateway just RELAYS encrypted data (ESP envelopes)
> without decrypting them. This is impossible in the current ipsec
> implementation since"the end of a tunnel HAS ALWAYS to be decrypted".
Umm, if I understand correctly, unless each tunnel is using the same
keys, the decrypt and reencrypt ends up with *different* data. So
just skipping the decrypt won't work, you'll just end up sending
packets which the other end can't read.
If your using the same keys, perhaps the kernal can see that, I don't
know...
Hope this helps,
--
Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply
* Modifying Cryptography Code
From: Alaa Dalghan @ 2005-09-06 13:56 UTC (permalink / raw)
To: linux-security-module, linux-crypto, linux-net, netdev
Hello everyone,
I need to modify some CRYPTOGRAPHY code in Linux Kernel to get a specific
VPN behavior, but I don't know where to start.
The situation is the following:
I have a VPN gateway (Linux kernel 2.6.10 with Openswan 2.3.1 installed). I
have only installed the user land tools from openswan package in order to
use the native ipsec stack in the kernel.
I have 30 laptops equipped with Windows XP configured to launch secure
tunnels towards the VPN gateway (so I have 30 tunnels). The laptops can
communicate securely VIA the gateway and everything works fine but..
the problem is the following:
Each packet sent from a given client to the other get processed 4 times
(encryption at the sender, decryption at the gateway, encryption at the
gateway, decryption at the receiver). This is the normal behavior but it
imposes too much processing overhead on the linux VPN gateway. The required
behavior is that the VPN gateway just RELAYS encrypted data (ESP envelopes)
without decrypting them. This is impossible in the current ipsec
implementation since"the end of a tunnel HAS ALWAYS to be decrypted".
Note that this required behavior can be achieved by launching a tunnel from
each client to every other client making the VPN gateway
transparent..BUT..this would mean 900 tunnels!! instead of 30, so it is not
the answer.
What I am looking for is the portion of the C code in the kernel where the
Decryption function is called to decrypt a received packet. When I find this
statement, maybe i can make it conditionnal such as: If the destination is
me then Decrypt else DO NOT!
I hope that someone can help me with finding this portion of the code and
modify it. By the way I searched in the kernel file "esp4.c" but can't seem
to find what I want.
----------------------------------------------------------WinXP(1)
|
Openswan
box------------------------------------------------------------WinXP(2)
|
----------------------------------------------------------WinXP(3)
|
|
|
|
---------------------------------------------------------WinXP(30)
_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today - it's FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
^ permalink raw reply
* Re: Fw: [Bugme-new] [Bug 5194] New: IPSec related OOps in 2.6.13
From: Krzysztof Oledzki @ 2005-09-06 13:17 UTC (permalink / raw)
To: Herbert Xu
Cc: Andrew Morton, netdev, bugme-daemon@kernel-bugs.osdl.org,
Matt LaPlante, Linux Kernel Mailing List, David S. Miller
In-Reply-To: <20050906122029.GB4594@gondor.apana.org.au>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 830 bytes --]
On Tue, 6 Sep 2005, Herbert Xu wrote:
> On Tue, Sep 06, 2005 at 04:08:56AM -0700, Andrew Morton wrote:
>>
>> Problem Description:
>>
>> Oops: 0000 [#1]
>> PREEMPT
>> Modules linked in:
>> CPU: 0
>> EIP: 0060:[<c01f562c>] Not tainted VLI
>> EFLAGS: 00010216 (2.6.13)
>> EIP is at sha1_update+0x7c/0x160
>
> Thanks for the report. Matt LaPlante had exactly the same problem
> a couple of days ago. I've tracked down now to my broken crypto
> cipher wrapper functions which will step over a page boundary if
> it's not aligned correctly.
>
>
> [CRYPTO] Fix boundary check in standard multi-block cipher processors
Thanks. Patched my kernel, recompiled and waiting. So far it is OK,
Should this patch be merged into 2.6.13.1?
Best regards,
Krzysztof Olędzki
^ permalink raw reply
* Re: Fw: [Bugme-new] [Bug 5194] New: IPSec related OOps in 2.6.13
From: Herbert Xu @ 2005-09-06 12:20 UTC (permalink / raw)
To: Andrew Morton
Cc: netdev, olel, bugme-daemon@kernel-bugs.osdl.org, Matt LaPlante,
Linux Kernel Mailing List, David S. Miller
In-Reply-To: <20050906040856.4e38419f.akpm@osdl.org>
[-- Attachment #1: Type: text/plain, Size: 1087 bytes --]
On Tue, Sep 06, 2005 at 04:08:56AM -0700, Andrew Morton wrote:
>
> Problem Description:
>
> Oops: 0000 [#1]
> PREEMPT
> Modules linked in:
> CPU: 0
> EIP: 0060:[<c01f562c>] Not tainted VLI
> EFLAGS: 00010216 (2.6.13)
> EIP is at sha1_update+0x7c/0x160
Thanks for the report. Matt LaPlante had exactly the same problem
a couple of days ago. I've tracked down now to my broken crypto
cipher wrapper functions which will step over a page boundary if
it's not aligned correctly.
[CRYPTO] Fix boundary check in standard multi-block cipher processors
The boundary check in the standard multi-block cipher processors are
broken when nbytes is not a multiple of bsize. In those cases it will
always process an extra block.
This patch corrects the check so that it processes at most nbytes of data.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p --]
[-- Type: text/plain, Size: 1180 bytes --]
diff --git a/crypto/cipher.c b/crypto/cipher.c
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -191,6 +191,8 @@ static unsigned int cbc_process_encrypt(
u8 *iv = desc->info;
unsigned int done = 0;
+ nbytes -= bsize;
+
do {
xor(iv, src);
fn(crypto_tfm_ctx(tfm), dst, iv);
@@ -198,7 +200,7 @@ static unsigned int cbc_process_encrypt(
src += bsize;
dst += bsize;
- } while ((done += bsize) < nbytes);
+ } while ((done += bsize) <= nbytes);
return done;
}
@@ -219,6 +221,8 @@ static unsigned int cbc_process_decrypt(
u8 *iv = desc->info;
unsigned int done = 0;
+ nbytes -= bsize;
+
do {
u8 *tmp_dst = *dst_p;
@@ -230,7 +234,7 @@ static unsigned int cbc_process_decrypt(
src += bsize;
dst += bsize;
- } while ((done += bsize) < nbytes);
+ } while ((done += bsize) <= nbytes);
return done;
}
@@ -243,12 +247,14 @@ static unsigned int ecb_process(const st
void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
unsigned int done = 0;
+ nbytes -= bsize;
+
do {
fn(crypto_tfm_ctx(tfm), dst, src);
src += bsize;
dst += bsize;
- } while ((done += bsize) < nbytes);
+ } while ((done += bsize) <= nbytes);
return done;
}
^ permalink raw reply
* Re: [PATCH 8/8] orinoco: New driver - spectrum_cs.
From: Christoph Hellwig @ 2005-09-06 11:24 UTC (permalink / raw)
To: Pavel Roskin; +Cc: Orinoco Development List, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1125619806.29016.11.camel@dv>
> +#ifdef __IN_PCMCIA_PACKAGE__
> +#include <pcmcia/k_compat.h>
> +#endif /* __IN_PCMCIA_PACKAGE__ */
this doesn't make sense for a 2.6 driver.
> +/*
> + * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
> + * the driver. Use get_symbol_fw script to generate spectrum_fw.h and
> + * copy it to the same directory as spectrum_cs.c.
> + *
> + * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
> + * runtime using hotplug. Use the same get_symbol_fw script to generate
> + * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
> + * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
> + * make sure that you have hotplug installed and enabled in the kernel.
> + */
> +/* #define SPECTRUM_FW_INCLUDED 1 */
> +
> +#ifdef SPECTRUM_FW_INCLUDED
> +/* Header with the firmware */
> +#include "spectrum_fw.h"
> +#else /* !SPECTRUM_FW_INCLUDED */
While I see the point of this for the standalone orinoco driver package
it doesn't make sense for the version in the kernel tree.
> +#define CS_CHECK(fn, ret) \
> + do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
I don't think this macro abuse helps anyone..
-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
^ permalink raw reply
* [git patches] net driver updates
From: Jeff Garzik @ 2005-09-05 22:47 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel, netdev
Please pull from the 'upstream' branch of
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
to obtain the following changes:
drivers/net/Kconfig | 9
drivers/net/chelsio/common.h | 4
drivers/net/chelsio/cxgb2.c | 2
drivers/net/e1000/e1000_hw.h | 2
drivers/net/mv643xx_eth.c | 139 +---
drivers/net/mv643xx_eth.h | 4
drivers/net/ne3210.c | 9
drivers/net/phy/Kconfig | 2
drivers/net/phy/mdio_bus.c | 2
drivers/net/s2io.c | 14
drivers/net/sis190.c | 131 ++-
drivers/net/tulip/uli526x.c | 2
drivers/net/wireless/Kconfig | 38 -
drivers/net/wireless/Makefile | 2
drivers/net/wireless/ipw2100.c | 69 +-
drivers/net/wireless/ipw2200.h | 1
drivers/net/wireless/orinoco.c | 93 +-
drivers/net/wireless/orinoco_cs.c | 1
drivers/net/wireless/orinoco_nortel.c | 324 +++++++++
drivers/net/wireless/spectrum_cs.c | 1120 ++++++++++++++++++++++++++++++++++
net/core/ethtool.c | 2
21 files changed, 1736 insertions(+), 234 deletions(-)
Adrian Bunk:
drivers/net/ne3210.c: cleanups
Al Viro:
(15/22) Kconfig fix (82596)
Dale Farnsworth:
mv643xx: fix skb memory leak
mv643xx: fix outstanding tx skb counter
mv643xx: Disable per port bandwidth limits
mv643xx: Fix promiscuous mode handling
mv643xx: add netpoll api support
Francois Romieu:
sis190: unmask the link change events
sis190: recent chipsets from SiS include a RGMII
sis190: make 10Mbps the default when handling the StationControl register
sis190: RGMII Tx internal delay fiddling
sis190: basic sis191 support
Pavel Roskin:
orinoco: Change orinoco_translate_scan() to return error code on error.
orinoco: Remove entry for Intel PRO/Wireless 2011B.
orinoco: Fix memory leak on error in processing hostscan frames.
orinoco: Optimize orinoco_join_ap()
orinoco: Remove EXPERIMENTAL mark from PLX_HERMES, TMD_HERMES and PCI_HERMES.
orinoco: New driver - orinoco_nortel.
orinoco: New driver - spectrum_cs.
Peter Chubb:
'mdio_bus_exit' in discarded section .text.exit
viro@ftp.linux.org.uk:
(1/7) chelsio sparse annotations
(2/7) iomem annotations (e1000)
(3/7) iomem annotations (s2io)
(4/7) missing include (uli526x)
(5/7) iomem annotations, NULL noise removal (ipw2100)
(6/7) missing include (ipw2200)
(7/7) __user annotations (ethtool)
viro@ZenIV.linux.org.uk:
Kconfig fix (PHYLIB vs. s390)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -397,7 +397,7 @@ config SUN3LANCE
If you're not building a kernel for a Sun 3, say N.
config SUN3_82586
- tristate "Sun3 on-board Intel 82586 support"
+ bool "Sun3 on-board Intel 82586 support"
depends on NET_ETHERNET && SUN3
help
This driver enables support for the on-board Intel 82586 based
@@ -1924,12 +1924,15 @@ config R8169_VLAN
If in doubt, say Y.
config SIS190
- tristate "SiS190 gigabit ethernet support"
+ tristate "SiS190/SiS191 gigabit ethernet support"
depends on PCI
select CRC32
select MII
---help---
- Say Y here if you have a SiS 190 PCI Gigabit Ethernet adapter.
+ Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
+ a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
+ appear in lan on motherboard designs which are based on SiS 965
+ and SiS 966 south bridge.
To compile this driver as a module, choose M here: the module
will be called sis190. This is recommended.
diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h
--- a/drivers/net/chelsio/common.h
+++ b/drivers/net/chelsio/common.h
@@ -88,7 +88,7 @@ struct t1_rx_mode {
static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm)
{
- u8 *addr = 0;
+ u8 *addr = NULL;
if (rm->idx++ < rm->dev->mc_count) {
addr = rm->list->dmi_addr;
@@ -190,7 +190,7 @@ struct sge;
struct peespi;
struct adapter {
- u8 *regs;
+ u8 __iomem *regs;
struct pci_dev *pdev;
unsigned long registered_device_map;
unsigned long open_device_map;
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -824,7 +824,7 @@ static void cxgb_proc_cleanup(struct ada
static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
{
struct adapter *adapter = dev->priv;
- struct mii_ioctl_data *data = (struct mii_ioctl_data *)&req->ifr_data;
+ struct mii_ioctl_data *data = if_mii(req);
switch (cmd) {
case SIOCGMIIPHY:
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -1270,7 +1270,7 @@ struct e1000_hw_stats {
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
- uint8_t *hw_addr;
+ uint8_t __iomem *hw_addr;
uint8_t *flash_address;
e1000_mac_type mac_type;
e1000_phy_type phy_type;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -58,11 +58,10 @@
#define INT_CAUSE_UNMASK_ALL 0x0007ffff
#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff
-#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
#define INT_CAUSE_MASK_ALL 0x00000000
+#define INT_CAUSE_MASK_ALL_EXT 0x00000000
#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL
#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT
-#endif
#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
@@ -259,14 +258,13 @@ static void mv643xx_eth_update_mac_addre
static void mv643xx_eth_set_rx_mode(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
- u32 config_reg;
- config_reg = ethernet_get_config_reg(mp->port_num);
if (dev->flags & IFF_PROMISC)
- config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+ mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
else
- config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
- ethernet_set_config_reg(mp->port_num, config_reg);
+ mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+
+ mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
}
/*
@@ -369,15 +367,6 @@ static int mv643xx_eth_free_tx_queue(str
dev_kfree_skb_irq(pkt_info.return_info);
released = 0;
-
- /*
- * Decrement the number of outstanding skbs counter on
- * the TX queue.
- */
- if (mp->tx_ring_skbs == 0)
- panic("ERROR - TX outstanding SKBs"
- " counter is corrupted");
- mp->tx_ring_skbs--;
} else
dma_unmap_page(NULL, pkt_info.buf_ptr,
pkt_info.byte_cnt, DMA_TO_DEVICE);
@@ -412,15 +401,13 @@ static int mv643xx_eth_receive_queue(str
struct pkt_info pkt_info;
#ifdef MV643XX_NAPI
- while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) {
+ while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) {
#else
while (eth_port_receive(mp, &pkt_info) == ETH_OK) {
#endif
mp->rx_ring_skbs--;
received_packets++;
-#ifdef MV643XX_NAPI
- budget--;
-#endif
+
/* Update statistics. Note byte count includes 4 byte CRC count */
stats->rx_packets++;
stats->rx_bytes += pkt_info.byte_cnt;
@@ -1044,9 +1031,6 @@ static void mv643xx_tx(struct net_device
DMA_TO_DEVICE);
dev_kfree_skb_irq(pkt_info.return_info);
-
- if (mp->tx_ring_skbs)
- mp->tx_ring_skbs--;
} else
dma_unmap_page(NULL, pkt_info.buf_ptr,
pkt_info.byte_cnt, DMA_TO_DEVICE);
@@ -1189,7 +1173,6 @@ linear:
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
DMA_TO_DEVICE);
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
status = eth_port_send(mp, &pkt_info);
if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
printk(KERN_ERR "%s: Error on transmitting packet\n",
@@ -1274,7 +1257,6 @@ linear:
pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
ETH_TX_LAST_DESC;
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
} else {
pkt_info.return_info = 0;
}
@@ -1311,7 +1293,6 @@ linear:
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
DMA_TO_DEVICE);
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
status = eth_port_send(mp, &pkt_info);
if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
printk(KERN_ERR "%s: Error on transmitting packet\n",
@@ -1356,6 +1337,43 @@ static struct net_device_stats *mv643xx_
return &mp->stats;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static inline void mv643xx_enable_irq(struct mv643xx_private *mp)
+{
+ int port_num = mp->port_num;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_CAUSE_UNMASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_CAUSE_UNMASK_ALL_EXT);
+ spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static inline void mv643xx_disable_irq(struct mv643xx_private *mp)
+{
+ int port_num = mp->port_num;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_CAUSE_MASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_CAUSE_MASK_ALL_EXT);
+ spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static void mv643xx_netpoll(struct net_device *netdev)
+{
+ struct mv643xx_private *mp = netdev_priv(netdev);
+
+ mv643xx_disable_irq(mp);
+ mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
+ mv643xx_enable_irq(mp);
+}
+#endif
+
/*/
* mv643xx_eth_probe
*
@@ -1406,6 +1424,10 @@ static int mv643xx_eth_probe(struct devi
dev->weight = 64;
#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = mv643xx_netpoll;
+#endif
+
dev->watchdog_timeo = 2 * HZ;
dev->tx_queue_len = mp->tx_ring_size;
dev->base_addr = 0;
@@ -1883,6 +1905,9 @@ static void eth_port_start(struct mv643x
/* Enable port Rx. */
mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
mp->port_rx_queue_command);
+
+ /* Disable port bandwidth limits by clearing MTU register */
+ mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0);
}
/*
@@ -2292,34 +2317,6 @@ static void eth_port_reset(unsigned int
mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
}
-/*
- * ethernet_set_config_reg - Set specified bits in configuration register.
- *
- * DESCRIPTION:
- * This function sets specified bits in the given ethernet
- * configuration register.
- *
- * INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- * unsigned int value 32 bit value.
- *
- * OUTPUT:
- * The set bits in the value parameter are set in the configuration
- * register.
- *
- * RETURN:
- * None.
- *
- */
-static void ethernet_set_config_reg(unsigned int eth_port_num,
- unsigned int value)
-{
- unsigned int eth_config_reg;
-
- eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num));
- eth_config_reg |= value;
- mv_write(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num), eth_config_reg);
-}
static int eth_port_autoneg_supported(unsigned int eth_port_num)
{
@@ -2346,31 +2343,6 @@ static int eth_port_link_is_up(unsigned
}
/*
- * ethernet_get_config_reg - Get the port configuration register
- *
- * DESCRIPTION:
- * This function returns the configuration register value of the given
- * ethernet port.
- *
- * INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- *
- * OUTPUT:
- * None.
- *
- * RETURN:
- * Port configuration register value.
- */
-static unsigned int ethernet_get_config_reg(unsigned int eth_port_num)
-{
- unsigned int eth_config_reg;
-
- eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG
- (eth_port_num));
- return eth_config_reg;
-}
-
-/*
* eth_port_read_smi_reg - Read PHY registers
*
* DESCRIPTION:
@@ -2528,6 +2500,9 @@ static ETH_FUNC_RET_STATUS eth_port_send
return ETH_ERROR;
}
+ mp->tx_ring_skbs++;
+ BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
+
/* Get the Tx Desc ring indexes */
tx_desc_curr = mp->tx_curr_desc_q;
tx_desc_used = mp->tx_used_desc_q;
@@ -2594,6 +2569,9 @@ static ETH_FUNC_RET_STATUS eth_port_send
if (mp->tx_resource_err)
return ETH_QUEUE_FULL;
+ mp->tx_ring_skbs++;
+ BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
+
/* Get the Tx Desc ring indexes */
tx_desc_curr = mp->tx_curr_desc_q;
tx_desc_used = mp->tx_used_desc_q;
@@ -2694,6 +2672,9 @@ static ETH_FUNC_RET_STATUS eth_tx_return
/* Any Tx return cancels the Tx resource error status */
mp->tx_resource_err = 0;
+ BUG_ON(mp->tx_ring_skbs == 0);
+ mp->tx_ring_skbs--;
+
return ETH_OK;
}
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
--- a/drivers/net/mv643xx_eth.h
+++ b/drivers/net/mv643xx_eth.h
@@ -408,10 +408,6 @@ static void eth_port_init(struct mv643xx
static void eth_port_reset(unsigned int eth_port_num);
static void eth_port_start(struct mv643xx_private *mp);
-static void ethernet_set_config_reg(unsigned int eth_port_num,
- unsigned int value);
-static unsigned int ethernet_get_config_reg(unsigned int eth_port_num);
-
/* Port MAC address routines */
static void eth_port_uc_addr_set(unsigned int eth_port_num,
unsigned char *p_addr);
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -26,9 +26,6 @@
Updated to EISA probing API 5/2003 by Marc Zyngier.
*/
-static const char *version =
- "ne3210.c: Driver revision v0.03, 30/09/98\n";
-
#include <linux/module.h>
#include <linux/eisa.h>
#include <linux/kernel.h>
@@ -197,7 +194,7 @@ static int __init ne3210_eisa_probe (str
ei_status.priv = phys_mem;
if (ei_debug > 0)
- printk(version);
+ printk("ne3210 loaded.\n");
ei_status.reset_8390 = &ne3210_reset_8390;
ei_status.block_input = &ne3210_block_input;
@@ -360,12 +357,12 @@ MODULE_DESCRIPTION("NE3210 EISA Ethernet
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(eisa, ne3210_ids);
-int ne3210_init(void)
+static int ne3210_init(void)
{
return eisa_driver_register (&ne3210_eisa_driver);
}
-void ne3210_cleanup(void)
+static void ne3210_cleanup(void)
{
eisa_driver_unregister (&ne3210_eisa_driver);
}
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -6,7 +6,7 @@ menu "PHY device support"
config PHYLIB
tristate "PHY Device support and infrastructure"
- depends on NET_ETHERNET
+ depends on NET_ETHERNET && (BROKEN || !ARCH_S390)
help
Ethernet controllers are usually attached to PHY
devices. This option provides infrastructure for
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -170,7 +170,7 @@ int __init mdio_bus_init(void)
return bus_register(&mdio_bus_type);
}
-void __exit mdio_bus_exit(void)
+void mdio_bus_exit(void)
{
bus_unregister(&mdio_bus_type);
}
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -686,7 +686,7 @@ static void free_shared_mem(struct s2io_
static int s2io_verify_pci_mode(nic_t *nic)
{
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
register u64 val64 = 0;
int mode;
@@ -704,7 +704,7 @@ static int s2io_verify_pci_mode(nic_t *n
*/
static int s2io_print_pci_mode(nic_t *nic)
{
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
register u64 val64 = 0;
int mode;
struct config_param *config = &nic->config;
@@ -1403,7 +1403,7 @@ static int init_nic(struct s2io_nic *nic
writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7);
/* Disable RMAC PAD STRIPPING */
- add = (void *) &bar0->mac_cfg;
+ add = &bar0->mac_cfg;
val64 = readq(&bar0->mac_cfg);
val64 &= ~(MAC_CFG_RMAC_STRIP_PAD);
writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
@@ -1934,7 +1934,7 @@ static int start_nic(struct s2io_nic *ni
val64 |= 0x0000800000000000ULL;
writeq(val64, &bar0->gpio_control);
val64 = 0x0411040400000000ULL;
- writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));
+ writeq(val64, (void __iomem *)bar0 + 0x2700);
}
/*
@@ -2395,7 +2395,7 @@ static int s2io_poll(struct net_device *
int pkt_cnt = 0, org_pkts_to_process;
mac_info_t *mac_control;
struct config_param *config;
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
u64 val64;
int i;
@@ -2831,7 +2831,7 @@ void s2io_reset(nic_t * sp)
val64 |= 0x0000800000000000ULL;
writeq(val64, &bar0->gpio_control);
val64 = 0x0411040400000000ULL;
- writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));
+ writeq(val64, (void __iomem *)bar0 + 0x2700);
}
/*
@@ -3234,7 +3234,7 @@ s2io_alarm_handle(unsigned long data)
static void s2io_txpic_intr_handle(nic_t *sp)
{
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0;
+ XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
val64 = readq(&bar0->pic_int_status);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -179,14 +179,6 @@ enum sis190_register_content {
TxInterFrameGapShift = 24,
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
- /* StationControl */
- _1000bpsF = 0x1c00,
- _1000bpsH = 0x0c00,
- _100bpsF = 0x1800,
- _100bpsH = 0x0800,
- _10bpsF = 0x1400,
- _10bpsH = 0x0400,
-
LinkStatus = 0x02, // unused
FullDup = 0x01, // unused
@@ -279,6 +271,12 @@ enum sis190_eeprom_address {
EEPROMMACAddr = 0x03
};
+enum sis190_feature {
+ F_HAS_RGMII = 1,
+ F_PHY_88E1111 = 2,
+ F_PHY_BCM5461 = 4
+};
+
struct sis190_private {
void __iomem *mmio_addr;
struct pci_dev *pci_dev;
@@ -300,6 +298,7 @@ struct sis190_private {
u32 msg_enable;
struct mii_if_info mii_if;
struct list_head first_phy;
+ u32 features;
};
struct sis190_phy {
@@ -321,24 +320,25 @@ static struct mii_chip_info {
const char *name;
u16 id[2];
unsigned int type;
+ u32 feature;
} mii_chip_table[] = {
- { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN },
- { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN },
- { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN },
- { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN },
+ { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
+ { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
+ { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
+ { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 },
{ NULL, }
};
const static struct {
const char *name;
- u8 version; /* depend on docs */
- u32 RxConfigMask; /* clear the bits supported by this chip */
} sis_chip_info[] = {
- { DRV_NAME, 0x00, 0xff7e1880, },
+ { "SiS 190 PCI Fast Ethernet adapter" },
+ { "SiS 191 PCI Gigabit Ethernet adapter" },
};
static struct pci_device_id sis190_pci_tbl[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
{ 0, },
};
@@ -360,7 +360,7 @@ MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
static const u32 sis190_intr_mask =
- RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt;
+ RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange;
/*
* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
@@ -879,11 +879,6 @@ static void sis190_hw_start(struct net_d
SIS_W32(IntrStatus, 0xffffffff);
SIS_W32(IntrMask, 0x0);
- /*
- * Default is 100Mbps.
- * A bit strange: 100Mbps is 0x1801 elsewhere -- FR 2005/06/09
- */
- SIS_W16(StationControl, 0x1901);
SIS_W32(GMIIControl, 0x0);
SIS_W32(TxMacControl, 0x60);
SIS_W16(RxMacControl, 0x02);
@@ -923,35 +918,30 @@ static void sis190_phy_task(void * data)
BMSR_ANEGCOMPLETE)) {
net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n",
dev->name);
+ netif_carrier_off(dev);
mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET);
mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
} else {
/* Rejoice ! */
struct {
int val;
+ u32 ctl;
const char *msg;
- u16 ctl;
} reg31[] = {
- { LPA_1000XFULL | LPA_SLCT,
- "1000 Mbps Full Duplex",
- 0x01 | _1000bpsF },
- { LPA_1000XHALF | LPA_SLCT,
- "1000 Mbps Half Duplex",
- 0x01 | _1000bpsH },
- { LPA_100FULL,
- "100 Mbps Full Duplex",
- 0x01 | _100bpsF },
- { LPA_100HALF,
- "100 Mbps Half Duplex",
- 0x01 | _100bpsH },
- { LPA_10FULL,
- "10 Mbps Full Duplex",
- 0x01 | _10bpsF },
- { LPA_10HALF,
- "10 Mbps Half Duplex",
- 0x01 | _10bpsH },
- { 0, "unknown", 0x0000 }
- }, *p;
+ { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000,
+ "1000 Mbps Full Duplex" },
+ { LPA_1000XHALF | LPA_SLCT, 0x07000c00,
+ "1000 Mbps Half Duplex" },
+ { LPA_100FULL, 0x04000800 | 0x00001000,
+ "100 Mbps Full Duplex" },
+ { LPA_100HALF, 0x04000800,
+ "100 Mbps Half Duplex" },
+ { LPA_10FULL, 0x04000400 | 0x00001000,
+ "10 Mbps Full Duplex" },
+ { LPA_10HALF, 0x04000400,
+ "10 Mbps Half Duplex" },
+ { 0, 0x04000400, "unknown" }
+ }, *p;
u16 adv;
val = mdio_read(ioaddr, phy_id, 0x1f);
@@ -964,12 +954,29 @@ static void sis190_phy_task(void * data)
val &= adv;
- for (p = reg31; p->ctl; p++) {
+ for (p = reg31; p->val; p++) {
if ((val & p->val) == p->val)
break;
}
- if (p->ctl)
- SIS_W16(StationControl, p->ctl);
+
+ p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
+
+ if ((tp->features & F_HAS_RGMII) &&
+ (tp->features & F_PHY_BCM5461)) {
+ // Set Tx Delay in RGMII mode.
+ mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
+ udelay(200);
+ mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
+ p->ctl |= 0x03000000;
+ }
+
+ SIS_W32(StationControl, p->ctl);
+
+ if (tp->features & F_HAS_RGMII) {
+ SIS_W32(RGDelay, 0x0441);
+ SIS_W32(RGDelay, 0x0440);
+ }
+
net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name,
p->msg);
netif_carrier_on(dev);
@@ -1308,6 +1315,7 @@ static void sis190_init_phy(struct net_d
phy->type = (p->type == MIX) ?
((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
LAN : HOME) : p->type;
+ tp->features |= p->feature;
} else
phy->type = UNKNOWN;
@@ -1316,6 +1324,25 @@ static void sis190_init_phy(struct net_d
(phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id);
}
+static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
+{
+ if (tp->features & F_PHY_88E1111) {
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ u16 reg[2][2] = {
+ { 0x808b, 0x0ce1 },
+ { 0x808f, 0x0c60 }
+ }, *p;
+
+ p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
+
+ mdio_write(ioaddr, phy_id, 0x1b, p[0]);
+ udelay(200);
+ mdio_write(ioaddr, phy_id, 0x14, p[1]);
+ udelay(200);
+ }
+}
+
/**
* sis190_mii_probe - Probe MII PHY for sis190
* @dev: the net device to probe for
@@ -1366,6 +1393,8 @@ static int __devinit sis190_mii_probe(st
/* Select default PHY for mac */
sis190_default_phy(dev);
+ sis190_mii_probe_88e1111_fixup(tp);
+
mii_if->dev = dev;
mii_if->mdio_read = __mdio_read;
mii_if->mdio_write = __mdio_write;
@@ -1505,6 +1534,11 @@ static void sis190_tx_timeout(struct net
netif_wake_queue(dev);
}
+static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
+{
+ tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
+}
+
static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
struct net_device *dev)
{
@@ -1532,6 +1566,8 @@ static int __devinit sis190_get_mac_addr
((u16 *)dev->dev_addr)[0] = le16_to_cpu(w);
}
+ sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
+
return 0;
}
@@ -1577,6 +1613,8 @@ static int __devinit sis190_get_mac_addr
outb(0x12, 0x78);
reg = inb(0x79);
+ sis190_set_rgmii(tp, reg);
+
/* Restore the value to ISA Bridge */
pci_write_config_byte(isa_bridge, 0x48, tmp8);
pci_dev_put(isa_bridge);
@@ -1799,6 +1837,9 @@ static int __devinit sis190_init_one(str
dev->dev_addr[2], dev->dev_addr[3],
dev->dev_addr[4], dev->dev_addr[5]);
+ net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
+ (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
+
netif_carrier_off(dev);
sis190_set_speed_auto(dev);
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -21,7 +21,6 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
-#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
@@ -34,6 +33,7 @@
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
#include <asm/processor.h>
#include <asm/bitops.h>
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -289,8 +289,8 @@ config APPLE_AIRPORT
a non-standard interface
config PLX_HERMES
- tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
+ depends on PCI && HERMES
help
Enable support for PCMCIA cards supported by the "Hermes" (aka
orinoco) driver when used in PLX9052 based PCI adaptors. These
@@ -299,12 +299,9 @@ config PLX_HERMES
802.11b PCMCIA cards can be used in desktop machines. The Netgear
MA301 is such an adaptor.
- Support for these adaptors is so far still incomplete and buggy.
- You have been warned.
-
config TMD_HERMES
- tristate "Hermes in TMD7160 based PCI adaptor support (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Hermes in TMD7160 based PCI adaptor support"
+ depends on PCI && HERMES
help
Enable support for PCMCIA cards supported by the "Hermes" (aka
orinoco) driver when used in TMD7160 based PCI adaptors. These
@@ -312,12 +309,18 @@ config TMD_HERMES
PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
802.11b PCMCIA cards can be used in desktop machines.
- Support for these adaptors is so far still incomplete and buggy.
- You have been warned.
+config NORTEL_HERMES
+ tristate "Nortel emobility PCI adaptor support"
+ depends on PCI && HERMES
+ help
+ Enable support for PCMCIA cards supported by the "Hermes" (aka
+ orinoco) driver when used in Nortel emobility PCI adaptors. These
+ adaptors are not full PCMCIA controllers, but act as a more limited
+ PCI <-> PCMCIA bridge.
config PCI_HERMES
- tristate "Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Prism 2.5 PCI 802.11b adaptor support"
+ depends on PCI && HERMES
help
Enable support for PCI and mini-PCI 802.11b wireless NICs based on
the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
@@ -372,6 +375,19 @@ config PCMCIA_HERMES
configure your card and that /etc/pcmcia/wireless.opts works:
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+config PCMCIA_SPECTRUM
+ tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
+ depends on NET_RADIO && PCMCIA && HERMES
+ ---help---
+
+ This is a driver for 802.11b cards using RAM-loadable Symbol
+ firmware, such as Symbol Wireless Networker LA4100, CompactFlash
+ cards by Socket Communications and Intel PRO/Wireless 2011B.
+
+ This driver requires firmware download on startup. Utilities
+ for downloading Symbol firmware are available at
+ <http://sourceforge.net/projects/orinoco/>
+
config AIRO_CS
tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -22,6 +22,8 @@ obj-$(CONFIG_APPLE_AIRPORT) += airport.o
obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
+obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
+obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
obj-$(CONFIG_AIRO) += airo.o
obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -327,38 +327,38 @@ static struct iw_handler_def ipw2100_wx_
static inline void read_register(struct net_device *dev, u32 reg, u32 *val)
{
- *val = readl((void *)(dev->base_addr + reg));
+ *val = readl((void __iomem *)(dev->base_addr + reg));
IPW_DEBUG_IO("r: 0x%08X => 0x%08X\n", reg, *val);
}
static inline void write_register(struct net_device *dev, u32 reg, u32 val)
{
- writel(val, (void *)(dev->base_addr + reg));
+ writel(val, (void __iomem *)(dev->base_addr + reg));
IPW_DEBUG_IO("w: 0x%08X <= 0x%08X\n", reg, val);
}
static inline void read_register_word(struct net_device *dev, u32 reg, u16 *val)
{
- *val = readw((void *)(dev->base_addr + reg));
+ *val = readw((void __iomem *)(dev->base_addr + reg));
IPW_DEBUG_IO("r: 0x%08X => %04X\n", reg, *val);
}
static inline void read_register_byte(struct net_device *dev, u32 reg, u8 *val)
{
- *val = readb((void *)(dev->base_addr + reg));
+ *val = readb((void __iomem *)(dev->base_addr + reg));
IPW_DEBUG_IO("r: 0x%08X => %02X\n", reg, *val);
}
static inline void write_register_word(struct net_device *dev, u32 reg, u16 val)
{
- writew(val, (void *)(dev->base_addr + reg));
+ writew(val, (void __iomem *)(dev->base_addr + reg));
IPW_DEBUG_IO("w: 0x%08X <= %04X\n", reg, val);
}
static inline void write_register_byte(struct net_device *dev, u32 reg, u8 val)
{
- writeb(val, (void *)(dev->base_addr + reg));
+ writeb(val, (void __iomem *)(dev->base_addr + reg));
IPW_DEBUG_IO("w: 0x%08X =< %02X\n", reg, val);
}
@@ -498,7 +498,7 @@ static inline void read_nic_memory(struc
static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev)
{
return (dev->base_addr &&
- (readl((void *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START))
+ (readl((void __iomem *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START))
== IPW_DATA_DOA_DEBUG_VALUE));
}
@@ -2125,19 +2125,19 @@ static void isr_indicate_scanning(struct
}
static const struct ipw2100_status_indicator status_handlers[] = {
- IPW2100_HANDLER(IPW_STATE_INITIALIZED, 0),
- IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, 0),
+ IPW2100_HANDLER(IPW_STATE_INITIALIZED, NULL),
+ IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, NULL),
IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated),
IPW2100_HANDLER(IPW_STATE_ASSN_LOST, isr_indicate_association_lost),
- IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, 0),
+ IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, NULL),
IPW2100_HANDLER(IPW_STATE_SCAN_COMPLETE, isr_scan_complete),
- IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, 0),
- IPW2100_HANDLER(IPW_STATE_LEFT_PSP, 0),
+ IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, NULL),
+ IPW2100_HANDLER(IPW_STATE_LEFT_PSP, NULL),
IPW2100_HANDLER(IPW_STATE_RF_KILL, isr_indicate_rf_kill),
- IPW2100_HANDLER(IPW_STATE_DISABLED, 0),
- IPW2100_HANDLER(IPW_STATE_POWER_DOWN, 0),
+ IPW2100_HANDLER(IPW_STATE_DISABLED, NULL),
+ IPW2100_HANDLER(IPW_STATE_POWER_DOWN, NULL),
IPW2100_HANDLER(IPW_STATE_SCANNING, isr_indicate_scanning),
- IPW2100_HANDLER(-1, 0)
+ IPW2100_HANDLER(-1, NULL)
};
@@ -6327,7 +6327,7 @@ static void ipw2100_irq_tasklet(struct i
static struct net_device *ipw2100_alloc_device(
struct pci_dev *pci_dev,
- char *base_addr,
+ void __iomem *base_addr,
unsigned long mem_start,
unsigned long mem_len)
{
@@ -6474,7 +6474,7 @@ static int ipw2100_pci_init_one(struct p
const struct pci_device_id *ent)
{
unsigned long mem_start, mem_len, mem_flags;
- char *base_addr = NULL;
+ void __iomem *base_addr = NULL;
struct net_device *dev = NULL;
struct ipw2100_priv *priv = NULL;
int err = 0;
@@ -6664,7 +6664,7 @@ static int ipw2100_pci_init_one(struct p
}
if (base_addr)
- iounmap((char*)base_addr);
+ iounmap(base_addr);
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
@@ -6714,7 +6714,7 @@ static void __devexit ipw2100_pci_remove
free_irq(dev->irq, priv);
if (dev->base_addr)
- iounmap((unsigned char *)dev->base_addr);
+ iounmap((void __iomem *)dev->base_addr);
free_ieee80211(dev);
}
@@ -8574,6 +8574,7 @@ static int ipw2100_ucode_download(struct
struct net_device *dev = priv->net_dev;
const unsigned char *microcode_data = fw->uc.data;
unsigned int microcode_data_left = fw->uc.size;
+ void __iomem *reg = (void __iomem *)dev->base_addr;
struct symbol_alive_response response;
int i, j;
@@ -8581,23 +8582,23 @@ static int ipw2100_ucode_download(struct
/* Symbol control */
write_nic_word(dev, IPW2100_CONTROL_REG, 0x703);
- readl((void *)(dev->base_addr));
+ readl(reg);
write_nic_word(dev, IPW2100_CONTROL_REG, 0x707);
- readl((void *)(dev->base_addr));
+ readl(reg);
/* HW config */
write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */
- readl((void *)(dev->base_addr));
+ readl(reg);
write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */
- readl((void *)(dev->base_addr));
+ readl(reg);
/* EN_CS_ACCESS bit to reset control store pointer */
write_nic_byte(dev, 0x210000, 0x40);
- readl((void *)(dev->base_addr));
+ readl(reg);
write_nic_byte(dev, 0x210000, 0x0);
- readl((void *)(dev->base_addr));
+ readl(reg);
write_nic_byte(dev, 0x210000, 0x40);
- readl((void *)(dev->base_addr));
+ readl(reg);
/* copy microcode from buffer into Symbol */
@@ -8609,31 +8610,31 @@ static int ipw2100_ucode_download(struct
/* EN_CS_ACCESS bit to reset the control store pointer */
write_nic_byte(dev, 0x210000, 0x0);
- readl((void *)(dev->base_addr));
+ readl(reg);
/* Enable System (Reg 0)
* first enable causes garbage in RX FIFO */
write_nic_byte(dev, 0x210000, 0x0);
- readl((void *)(dev->base_addr));
+ readl(reg);
write_nic_byte(dev, 0x210000, 0x80);
- readl((void *)(dev->base_addr));
+ readl(reg);
/* Reset External Baseband Reg */
write_nic_word(dev, IPW2100_CONTROL_REG, 0x703);
- readl((void *)(dev->base_addr));
+ readl(reg);
write_nic_word(dev, IPW2100_CONTROL_REG, 0x707);
- readl((void *)(dev->base_addr));
+ readl(reg);
/* HW Config (Reg 5) */
write_nic_byte(dev, 0x210014, 0x72); // fifo width =16
- readl((void *)(dev->base_addr));
+ readl(reg);
write_nic_byte(dev, 0x210014, 0x72); // fifo width =16
- readl((void *)(dev->base_addr));
+ readl(reg);
/* Enable System (Reg 0)
* second enable should be OK */
write_nic_byte(dev, 0x210000, 0x00); // clear enable system
- readl((void *)(dev->base_addr));
+ readl(reg);
write_nic_byte(dev, 0x210000, 0x80); // set enable system
/* check Symbol is enabled - upped this from 5 as it wasn't always
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -42,6 +42,7 @@
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/random.h>
+#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/wireless.h>
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -1053,8 +1053,9 @@ static void orinoco_join_ap(struct net_d
u16 channel;
} __attribute__ ((packed)) req;
const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
- struct prism2_scan_apinfo *atom;
+ struct prism2_scan_apinfo *atom = NULL;
int offset = 4;
+ int found = 0;
u8 *buf;
u16 len;
@@ -1089,15 +1090,18 @@ static void orinoco_join_ap(struct net_d
* we were requested to join */
for (; offset + atom_len <= len; offset += atom_len) {
atom = (struct prism2_scan_apinfo *) (buf + offset);
- if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0)
- goto found;
+ if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
+ found = 1;
+ break;
+ }
}
- DEBUG(1, "%s: Requested AP not found in scan results\n",
- dev->name);
- goto out;
+ if (! found) {
+ DEBUG(1, "%s: Requested AP not found in scan results\n",
+ dev->name);
+ goto out;
+ }
- found:
memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
req.channel = atom->channel; /* both are little-endian */
err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
@@ -1284,8 +1288,10 @@ static void __orinoco_ev_info(struct net
/* Read scan data */
err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
infofid, sizeof(info));
- if (err)
+ if (err) {
+ kfree(buf);
break;
+ }
#ifdef ORINOCO_DEBUG
{
@@ -4021,7 +4027,8 @@ static int orinoco_ioctl_setscan(struct
}
/* Translate scan data returned from the card to a card independant
- * format that the Wireless Tools will understand - Jean II */
+ * format that the Wireless Tools will understand - Jean II
+ * Return message length or -errno for fatal errors */
static inline int orinoco_translate_scan(struct net_device *dev,
char *buffer,
char *scan,
@@ -4061,13 +4068,19 @@ static inline int orinoco_translate_scan
break;
case FIRMWARE_TYPE_INTERSIL:
offset = 4;
- if (priv->has_hostscan)
- atom_len = scan[0] + (scan[1] << 8);
- else
+ if (priv->has_hostscan) {
+ atom_len = le16_to_cpup((u16 *)scan);
+ /* Sanity check for atom_len */
+ if (atom_len < sizeof(struct prism2_scan_apinfo)) {
+ printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
+ dev->name, atom_len);
+ return -EIO;
+ }
+ } else
atom_len = offsetof(struct prism2_scan_apinfo, atim);
break;
default:
- return 0;
+ return -EOPNOTSUPP;
}
/* Check that we got an whole number of atoms */
@@ -4075,7 +4088,7 @@ static inline int orinoco_translate_scan
printk(KERN_ERR "%s: Unexpected scan data length %d, "
"atom_len %d, offset %d\n", dev->name, scan_len,
atom_len, offset);
- return 0;
+ return -EIO;
}
/* Read the entries one by one */
@@ -4210,33 +4223,41 @@ static int orinoco_ioctl_getscan(struct
/* We have some results to push back to user space */
/* Translate to WE format */
- srq->length = orinoco_translate_scan(dev, extra,
- priv->scan_result,
- priv->scan_len);
-
- /* Return flags */
- srq->flags = (__u16) priv->scan_mode;
+ int ret = orinoco_translate_scan(dev, extra,
+ priv->scan_result,
+ priv->scan_len);
+
+ if (ret < 0) {
+ err = ret;
+ kfree(priv->scan_result);
+ priv->scan_result = NULL;
+ } else {
+ srq->length = ret;
- /* Results are here, so scan no longer in progress */
- priv->scan_inprogress = 0;
+ /* Return flags */
+ srq->flags = (__u16) priv->scan_mode;
- /* In any case, Scan results will be cleaned up in the
- * reset function and when exiting the driver.
- * The person triggering the scanning may never come to
- * pick the results, so we need to do it in those places.
- * Jean II */
+ /* In any case, Scan results will be cleaned up in the
+ * reset function and when exiting the driver.
+ * The person triggering the scanning may never come to
+ * pick the results, so we need to do it in those places.
+ * Jean II */
#ifdef SCAN_SINGLE_READ
- /* If you enable this option, only one client (the first
- * one) will be able to read the result (and only one
- * time). If there is multiple concurent clients that
- * want to read scan results, this behavior is not
- * advisable - Jean II */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
+ /* If you enable this option, only one client (the first
+ * one) will be able to read the result (and only one
+ * time). If there is multiple concurent clients that
+ * want to read scan results, this behavior is not
+ * advisable - Jean II */
+ kfree(priv->scan_result);
+ priv->scan_result = NULL;
#endif /* SCAN_SINGLE_READ */
- /* Here, if too much time has elapsed since last scan,
- * we may want to clean up scan results... - Jean II */
+ /* Here, if too much time has elapsed since last scan,
+ * we may want to clean up scan results... - Jean II */
+ }
+
+ /* Scan is no longer in progress */
+ priv->scan_inprogress = 0;
}
orinoco_unlock(priv, &flags);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -604,7 +604,6 @@ static char version[] __initdata = DRIVE
static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
- PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
new file mode 100644
--- /dev/null
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -0,0 +1,324 @@
+/* orinoco_nortel.c
+ *
+ * Driver for Prism II devices which would usually be driven by orinoco_cs,
+ * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter.
+ *
+ * Copyright (C) 2002 Tobias Hoffmann
+ * (C) 2003 Christoph Jungegger <disdos@traum404.de>
+ *
+ * Some of this code is borrowed from orinoco_plx.c
+ * Copyright (C) 2001 Daniel Barlow
+ * Some of this code is borrowed from orinoco_pci.c
+ * Copyright (C) 2001 Jean Tourrilhes
+ * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
+ * has been copied from it. linux-wlan-ng-0.1.10 is originally :
+ * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#define DRIVER_NAME "orinoco_nortel"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/fcntl.h>
+
+#include <pcmcia/cisreg.h>
+
+#include "hermes.h"
+#include "orinoco.h"
+
+#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+
+
+/* Nortel specific data */
+struct nortel_pci_card {
+ unsigned long iobase1;
+ unsigned long iobase2;
+};
+
+/*
+ * Do a soft reset of the PCI card using the Configuration Option Register
+ * We need this to get going...
+ * This is the part of the code that is strongly inspired from wlan-ng
+ *
+ * Note bis : Don't try to access HERMES_CMD during the reset phase.
+ * It just won't work !
+ */
+static int nortel_pci_cor_reset(struct orinoco_private *priv)
+{
+ struct nortel_pci_card *card = priv->card;
+
+ /* Assert the reset until the card notice */
+ outw_p(8, card->iobase1 + 2);
+ inw(card->iobase2 + COR_OFFSET);
+ outw_p(0x80, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ /* Give time for the card to recover from this hard effort */
+ outw_p(0, card->iobase2 + COR_OFFSET);
+ outw_p(0, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ /* set COR as usual */
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ outw_p(0x228, card->iobase1 + 2);
+
+ return 0;
+}
+
+int nortel_pci_hw_init(struct nortel_pci_card *card)
+{
+ int i;
+ u32 reg;
+
+ /* setup bridge */
+ if (inw(card->iobase1) & 1) {
+ printk(KERN_ERR PFX "brg1 answer1 wrong\n");
+ return -EBUSY;
+ }
+ outw_p(0x118, card->iobase1 + 2);
+ outw_p(0x108, card->iobase1 + 2);
+ mdelay(30);
+ outw_p(0x8, card->iobase1 + 2);
+ for (i = 0; i < 30; i++) {
+ mdelay(30);
+ if (inw(card->iobase1) & 0x10) {
+ break;
+ }
+ }
+ if (i == 30) {
+ printk(KERN_ERR PFX "brg1 timed out\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe0) & 1) {
+ printk(KERN_ERR PFX "brg2 answer1 wrong\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe2) & 1) {
+ printk(KERN_ERR PFX "brg2 answer2 wrong\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe4) & 1) {
+ printk(KERN_ERR PFX "brg2 answer3 wrong\n");
+ return -EBUSY;
+ }
+
+ /* set the PCMCIA COR-Register */
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+ reg = inw(card->iobase2 + COR_OFFSET);
+ if (reg != COR_VALUE) {
+ printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
+ reg);
+ return -EBUSY;
+ }
+
+ /* set leds */
+ outw_p(1, card->iobase1 + 10);
+ return 0;
+}
+
+static int nortel_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int err;
+ struct orinoco_private *priv;
+ struct nortel_pci_card *card;
+ struct net_device *dev;
+ void __iomem *iomem;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot enable PCI device\n");
+ return err;
+ }
+
+ err = pci_request_regions(pdev, DRIVER_NAME);
+ if (err != 0) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+ goto fail_resources;
+ }
+
+ iomem = pci_iomap(pdev, 3, 0);
+ if (!iomem) {
+ err = -ENOMEM;
+ goto fail_map_io;
+ }
+
+ /* Allocate network device */
+ dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset);
+ if (!dev) {
+ printk(KERN_ERR PFX "Cannot allocate network device\n");
+ err = -ENOMEM;
+ goto fail_alloc;
+ }
+
+ priv = netdev_priv(dev);
+ card = priv->card;
+ card->iobase1 = pci_resource_start(pdev, 0);
+ card->iobase2 = pci_resource_start(pdev, 1);
+ dev->base_addr = pci_resource_start(pdev, 2);
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING);
+
+ printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, "
+ "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr);
+
+ err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+ dev->name, dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
+ err = -EBUSY;
+ goto fail_irq;
+ }
+ dev->irq = pdev->irq;
+
+ err = nortel_pci_hw_init(card);
+ if (err) {
+ printk(KERN_ERR PFX "Hardware initialization failed\n");
+ goto fail;
+ }
+
+ err = nortel_pci_cor_reset(priv);
+ if (err) {
+ printk(KERN_ERR PFX "Initial reset failed\n");
+ goto fail;
+ }
+
+
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register network device\n");
+ goto fail;
+ }
+
+ pci_set_drvdata(pdev, dev);
+
+ return 0;
+
+ fail:
+ free_irq(pdev->irq, dev);
+
+ fail_irq:
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
+
+ fail_alloc:
+ pci_iounmap(pdev, iomem);
+
+ fail_map_io:
+ pci_release_regions(pdev);
+
+ fail_resources:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void __devexit nortel_pci_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct nortel_pci_card *card = priv->card;
+
+ /* clear leds */
+ outw_p(0, card->iobase1 + 10);
+
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
+ pci_iounmap(pdev, priv->hw.iobase);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+
+static struct pci_device_id nortel_pci_id_table[] = {
+ /* Nortel emobility PCI */
+ {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
+ {0,},
+};
+
+MODULE_DEVICE_TABLE(pci, nortel_pci_id_table);
+
+static struct pci_driver nortel_pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = nortel_pci_id_table,
+ .probe = nortel_pci_init_one,
+ .remove = __devexit_p(nortel_pci_remove_one),
+};
+
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+ " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
+MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
+MODULE_DESCRIPTION
+ ("Driver for wireless LAN cards using the Nortel PCI bridge");
+MODULE_LICENSE("Dual MPL/GPL");
+
+static int __init nortel_pci_init(void)
+{
+ printk(KERN_DEBUG "%s\n", version);
+ return pci_module_init(&nortel_pci_driver);
+}
+
+static void __exit nortel_pci_exit(void)
+{
+ pci_unregister_driver(&nortel_pci_driver);
+ ssleep(1);
+}
+
+module_init(nortel_pci_init);
+module_exit(nortel_pci_exit);
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
new file mode 100644
--- /dev/null
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -0,0 +1,1120 @@
+/*
+ * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
+ * Symbol Wireless Networker LA4100, CompactFlash cards by Socket
+ * Communications and Intel PRO/Wireless 2011B.
+ *
+ * The driver implements Symbol firmware download. The rest is handled
+ * in hermes.c and orinoco.c.
+ *
+ * Utilities for downloading the Symbol firmware are available at
+ * http://sourceforge.net/projects/orinoco/
+ *
+ * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
+ * Portions based on orinoco_cs.c:
+ * Copyright (C) David Gibson, Linuxcare Australia
+ * Portions based on Spectrum24tDnld.c from original spectrum24 driver:
+ * Copyright (C) Symbol Technologies.
+ *
+ * See copyright notice in file orinoco.c.
+ */
+
+#define DRIVER_NAME "spectrum_cs"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/config.h>
+#ifdef __IN_PCMCIA_PACKAGE__
+#include <pcmcia/k_compat.h>
+#endif /* __IN_PCMCIA_PACKAGE__ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "orinoco.h"
+
+/*
+ * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
+ * the driver. Use get_symbol_fw script to generate spectrum_fw.h and
+ * copy it to the same directory as spectrum_cs.c.
+ *
+ * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
+ * runtime using hotplug. Use the same get_symbol_fw script to generate
+ * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
+ * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
+ * make sure that you have hotplug installed and enabled in the kernel.
+ */
+/* #define SPECTRUM_FW_INCLUDED 1 */
+
+#ifdef SPECTRUM_FW_INCLUDED
+/* Header with the firmware */
+#include "spectrum_fw.h"
+#else /* !SPECTRUM_FW_INCLUDED */
+#include <linux/firmware.h>
+static unsigned char *primsym;
+static unsigned char *secsym;
+static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
+static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
+#endif /* !SPECTRUM_FW_INCLUDED */
+
+/********************************************************************/
+/* Module stuff */
+/********************************************************************/
+
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
+MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader");
+MODULE_LICENSE("Dual MPL/GPL");
+
+/* Module parameters */
+
+/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
+ * don't have any CIS entry for it. This workaround it... */
+static int ignore_cis_vcc; /* = 0 */
+module_param(ignore_cis_vcc, int, 0);
+MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
+
+/********************************************************************/
+/* Magic constants */
+/********************************************************************/
+
+/*
+ * The dev_info variable is the "key" that is used to match up this
+ * device driver with appropriate cards, through the card
+ * configuration database.
+ */
+static dev_info_t dev_info = DRIVER_NAME;
+
+/********************************************************************/
+/* Data structures */
+/********************************************************************/
+
+/* PCMCIA specific device information (goes in the card field of
+ * struct orinoco_private */
+struct orinoco_pccard {
+ dev_link_t link;
+ dev_node_t node;
+};
+
+/*
+ * A linked list of "instances" of the device. Each actual PCMCIA
+ * card corresponds to one device instance, and is described by one
+ * dev_link_t structure (defined in ds.h).
+ */
+static dev_link_t *dev_list; /* = NULL */
+
+/********************************************************************/
+/* Function prototypes */
+/********************************************************************/
+
+/* device methods */
+static int spectrum_cs_hard_reset(struct orinoco_private *priv);
+
+/* PCMCIA gumpf */
+static void spectrum_cs_config(dev_link_t * link);
+static void spectrum_cs_release(dev_link_t * link);
+static int spectrum_cs_event(event_t event, int priority,
+ event_callback_args_t * args);
+
+static dev_link_t *spectrum_cs_attach(void);
+static void spectrum_cs_detach(dev_link_t *);
+
+/********************************************************************/
+/* Firmware downloader */
+/********************************************************************/
+
+/* Position of PDA in the adapter memory */
+#define EEPROM_ADDR 0x3000
+#define EEPROM_LEN 0x200
+#define PDA_OFFSET 0x100
+
+#define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET)
+#define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2)
+
+/* Constants for the CISREG_CCSR register */
+#define HCR_RUN 0x07 /* run firmware after reset */
+#define HCR_IDLE 0x0E /* don't run firmware after reset */
+#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
+
+/*
+ * AUX port access. To unlock the AUX port write the access keys to the
+ * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
+ * register. Then read it and make sure it's HERMES_AUX_ENABLED.
+ */
+#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
+#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
+#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
+
+#define HERMES_AUX_PW0 0xFE01
+#define HERMES_AUX_PW1 0xDC23
+#define HERMES_AUX_PW2 0xBA45
+
+/* End markers */
+#define PDI_END 0x00000000 /* End of PDA */
+#define BLOCK_END 0xFFFFFFFF /* Last image block */
+#define TEXT_END 0x1A /* End of text header */
+
+/*
+ * The following structures have little-endian fields denoted by
+ * the leading underscore. Don't access them directly - use inline
+ * functions defined below.
+ */
+
+/*
+ * The binary image to be downloaded consists of series of data blocks.
+ * Each block has the following structure.
+ */
+struct dblock {
+ u32 _addr; /* adapter address where to write the block */
+ u16 _len; /* length of the data only, in bytes */
+ char data[0]; /* data to be written */
+} __attribute__ ((packed));
+
+/*
+ * Plug Data References are located in in the image after the last data
+ * block. They refer to areas in the adapter memory where the plug data
+ * items with matching ID should be written.
+ */
+struct pdr {
+ u32 _id; /* record ID */
+ u32 _addr; /* adapter address where to write the data */
+ u32 _len; /* expected length of the data, in bytes */
+ char next[0]; /* next PDR starts here */
+} __attribute__ ((packed));
+
+
+/*
+ * Plug Data Items are located in the EEPROM read from the adapter by
+ * primary firmware. They refer to the device-specific data that should
+ * be plugged into the secondary firmware.
+ */
+struct pdi {
+ u16 _len; /* length of ID and data, in words */
+ u16 _id; /* record ID */
+ char data[0]; /* plug data */
+} __attribute__ ((packed));;
+
+
+/* Functions for access to little-endian data */
+static inline u32
+dblock_addr(const struct dblock *blk)
+{
+ return le32_to_cpu(blk->_addr);
+}
+
+static inline u32
+dblock_len(const struct dblock *blk)
+{
+ return le16_to_cpu(blk->_len);
+}
+
+static inline u32
+pdr_id(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->_id);
+}
+
+static inline u32
+pdr_addr(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->_addr);
+}
+
+static inline u32
+pdr_len(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->_len);
+}
+
+static inline u32
+pdi_id(const struct pdi *pdi)
+{
+ return le16_to_cpu(pdi->_id);
+}
+
+/* Return length of the data only, in bytes */
+static inline u32
+pdi_len(const struct pdi *pdi)
+{
+ return 2 * (le16_to_cpu(pdi->_len) - 1);
+}
+
+
+/* Set address of the auxiliary port */
+static inline void
+spectrum_aux_setaddr(hermes_t *hw, u32 addr)
+{
+ hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
+ hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
+}
+
+
+/* Open access to the auxiliary port */
+static int
+spectrum_aux_open(hermes_t *hw)
+{
+ int i;
+
+ /* Already open? */
+ if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED)
+ return 0;
+
+ hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
+ hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
+ hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
+ hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE);
+
+ for (i = 0; i < 20; i++) {
+ udelay(10);
+ if (hermes_read_reg(hw, HERMES_CONTROL) ==
+ HERMES_AUX_ENABLED)
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+
+#define CS_CHECK(fn, ret) \
+ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+/*
+ * Reset the card using configuration registers COR and CCSR.
+ * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
+ */
+static int
+spectrum_reset(dev_link_t *link, int idle)
+{
+ int last_ret, last_fn;
+ conf_reg_t reg;
+ u_int save_cor;
+
+ /* Doing it if hardware is gone is guaranteed crash */
+ if (!(link->state & DEV_CONFIG))
+ return -ENODEV;
+
+ /* Save original COR value */
+ reg.Function = 0;
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_COR;
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, ®));
+ save_cor = reg.Value;
+
+ /* Soft-Reset card */
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = (save_cor | COR_SOFT_RESET);
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, ®));
+ udelay(1000);
+
+ /* Read CCSR */
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_CCSR;
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, ®));
+
+ /*
+ * Start or stop the firmware. Memory width bit should be
+ * preserved from the value we've just read.
+ */
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_CCSR;
+ reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, ®));
+ udelay(1000);
+
+ /* Restore original COR configuration index */
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = (save_cor & ~COR_SOFT_RESET);
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, ®));
+ udelay(1000);
+ return 0;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+ return -ENODEV;
+}
+
+
+/*
+ * Scan PDR for the record with the specified RECORD_ID.
+ * If it's not found, return NULL.
+ */
+static struct pdr *
+spectrum_find_pdr(struct pdr *first_pdr, u32 record_id)
+{
+ struct pdr *pdr = first_pdr;
+
+ while (pdr_id(pdr) != PDI_END) {
+ /*
+ * PDR area is currently not terminated by PDI_END.
+ * It's followed by CRC records, which have the type
+ * field where PDR has length. The type can be 0 or 1.
+ */
+ if (pdr_len(pdr) < 2)
+ return NULL;
+
+ /* If the record ID matches, we are done */
+ if (pdr_id(pdr) == record_id)
+ return pdr;
+
+ pdr = (struct pdr *) pdr->next;
+ }
+ return NULL;
+}
+
+
+/* Process one Plug Data Item - find corresponding PDR and plug it */
+static int
+spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi)
+{
+ struct pdr *pdr;
+
+ /* Find the PDI corresponding to this PDR */
+ pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi));
+
+ /* No match is found, safe to ignore */
+ if (!pdr)
+ return 0;
+
+ /* Lengths of the data in PDI and PDR must match */
+ if (pdi_len(pdi) != pdr_len(pdr))
+ return -EINVAL;
+
+ /* do the actual plugging */
+ spectrum_aux_setaddr(hw, pdr_addr(pdr));
+ hermes_write_words(hw, HERMES_AUXDATA, pdi->data,
+ pdi_len(pdi) / 2);
+
+ return 0;
+}
+
+
+/* Read PDA from the adapter */
+static int
+spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
+{
+ int ret;
+ int pda_size;
+
+ /* Issue command to read EEPROM */
+ ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
+ if (ret)
+ return ret;
+
+ /* Open auxiliary port */
+ ret = spectrum_aux_open(hw);
+ if (ret)
+ return ret;
+
+ /* read PDA from EEPROM */
+ spectrum_aux_setaddr(hw, PDA_ADDR);
+ hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2);
+
+ /* Check PDA length */
+ pda_size = le16_to_cpu(pda[0]);
+ if (pda_size > pda_len)
+ return -EINVAL;
+
+ return 0;
+}
+
+
+/* Parse PDA and write the records into the adapter */
+static int
+spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
+ u16 *pda)
+{
+ int ret;
+ struct pdi *pdi;
+ struct pdr *first_pdr;
+ const struct dblock *blk = first_block;
+
+ /* Skip all blocks to locate Plug Data References */
+ while (dblock_addr(blk) != BLOCK_END)
+ blk = (struct dblock *) &blk->data[dblock_len(blk)];
+
+ first_pdr = (struct pdr *) blk;
+
+ /* Go through every PDI and plug them into the adapter */
+ pdi = (struct pdi *) (pda + 2);
+ while (pdi_id(pdi) != PDI_END) {
+ ret = spectrum_plug_pdi(hw, first_pdr, pdi);
+ if (ret)
+ return ret;
+
+ /* Increment to the next PDI */
+ pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
+ }
+ return 0;
+}
+
+
+/* Load firmware blocks into the adapter */
+static int
+spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
+{
+ const struct dblock *blk;
+ u32 blkaddr;
+ u32 blklen;
+
+ blk = first_block;
+ blkaddr = dblock_addr(blk);
+ blklen = dblock_len(blk);
+
+ while (dblock_addr(blk) != BLOCK_END) {
+ spectrum_aux_setaddr(hw, blkaddr);
+ hermes_write_words(hw, HERMES_AUXDATA, blk->data,
+ blklen / 2);
+
+ blk = (struct dblock *) &blk->data[blklen];
+ blkaddr = dblock_addr(blk);
+ blklen = dblock_len(blk);
+ }
+ return 0;
+}
+
+
+/*
+ * Process a firmware image - stop the card, load the firmware, reset
+ * the card and make sure it responds. For the secondary firmware take
+ * care of the PDA - read it and then write it on top of the firmware.
+ */
+static int
+spectrum_dl_image(hermes_t *hw, dev_link_t *link,
+ const unsigned char *image)
+{
+ int ret;
+ const unsigned char *ptr;
+ const struct dblock *first_block;
+
+ /* Plug Data Area (PDA) */
+ u16 pda[PDA_WORDS];
+
+ /* Binary block begins after the 0x1A marker */
+ ptr = image;
+ while (*ptr++ != TEXT_END);
+ first_block = (const struct dblock *) ptr;
+
+ /* Read the PDA */
+ if (image != primsym) {
+ ret = spectrum_read_pda(hw, pda, sizeof(pda));
+ if (ret)
+ return ret;
+ }
+
+ /* Stop the firmware, so that it can be safely rewritten */
+ ret = spectrum_reset(link, 1);
+ if (ret)
+ return ret;
+
+ /* Program the adapter with new firmware */
+ ret = spectrum_load_blocks(hw, first_block);
+ if (ret)
+ return ret;
+
+ /* Write the PDA to the adapter */
+ if (image != primsym) {
+ ret = spectrum_apply_pda(hw, first_block, pda);
+ if (ret)
+ return ret;
+ }
+
+ /* Run the firmware */
+ ret = spectrum_reset(link, 0);
+ if (ret)
+ return ret;
+
+ /* Reset hermes chip and make sure it responds */
+ ret = hermes_init(hw);
+
+ /* hermes_reset() should return 0 with the secondary firmware */
+ if (image != primsym && ret != 0)
+ return -ENODEV;
+
+ /* And this should work with any firmware */
+ if (!hermes_present(hw))
+ return -ENODEV;
+
+ return 0;
+}
+
+
+/*
+ * Download the firmware into the card, this also does a PCMCIA soft
+ * reset on the card, to make sure it's in a sane state.
+ */
+static int
+spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
+{
+ int ret;
+ client_handle_t handle = link->handle;
+
+#ifndef SPECTRUM_FW_INCLUDED
+ const struct firmware *fw_entry;
+
+ if (request_firmware(&fw_entry, primary_fw_name,
+ &handle_to_dev(handle)) == 0) {
+ primsym = fw_entry->data;
+ } else {
+ printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+ primary_fw_name);
+ return -ENOENT;
+ }
+
+ if (request_firmware(&fw_entry, secondary_fw_name,
+ &handle_to_dev(handle)) == 0) {
+ secsym = fw_entry->data;
+ } else {
+ printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+ secondary_fw_name);
+ return -ENOENT;
+ }
+#endif
+
+ /* Load primary firmware */
+ ret = spectrum_dl_image(hw, link, primsym);
+ if (ret) {
+ printk(KERN_ERR PFX "Primary firmware download failed\n");
+ return ret;
+ }
+
+ /* Load secondary firmware */
+ ret = spectrum_dl_image(hw, link, secsym);
+
+ if (ret) {
+ printk(KERN_ERR PFX "Secondary firmware download failed\n");
+ }
+
+ return ret;
+}
+
+/********************************************************************/
+/* Device methods */
+/********************************************************************/
+
+static int
+spectrum_cs_hard_reset(struct orinoco_private *priv)
+{
+ struct orinoco_pccard *card = priv->card;
+ dev_link_t *link = &card->link;
+ int err;
+
+ if (!hermes_present(&priv->hw)) {
+ /* The firmware needs to be reloaded */
+ if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) {
+ printk(KERN_ERR PFX "Firmware download failed\n");
+ err = -ENODEV;
+ }
+ } else {
+ /* Soft reset using COR and HCR */
+ spectrum_reset(link, 0);
+ }
+
+ return 0;
+}
+
+/********************************************************************/
+/* PCMCIA stuff */
+/********************************************************************/
+
+/*
+ * This creates an "instance" of the driver, allocating local data
+ * structures for one device. The device is registered with Card
+ * Services.
+ *
+ * The dev_link structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a card
+ * insertion event. */
+static dev_link_t *
+spectrum_cs_attach(void)
+{
+ struct net_device *dev;
+ struct orinoco_private *priv;
+ struct orinoco_pccard *card;
+ dev_link_t *link;
+ client_reg_t client_reg;
+ int ret;
+
+ dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
+ if (! dev)
+ return NULL;
+ priv = netdev_priv(dev);
+ card = priv->card;
+
+ /* Link both structures together */
+ link = &card->link;
+ link->priv = dev;
+
+ /* Interrupt setup */
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->irq.Handler = orinoco_interrupt;
+ link->irq.Instance = dev;
+
+ /* General socket configuration defaults can go here. In this
+ * client, we assume very little, and rely on the CIS for
+ * almost everything. In most clients, many details (i.e.,
+ * number, sizes, and attributes of IO windows) are fixed by
+ * the nature of the device, and can be hard-wired here. */
+ link->conf.Attributes = 0;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ /* Register with Card Services */
+ /* FIXME: need a lock? */
+ link->next = dev_list;
+ dev_list = link;
+
+ client_reg.dev_info = &dev_info;
+ client_reg.Version = 0x0210; /* FIXME: what does this mean? */
+ client_reg.event_callback_args.client_data = link;
+
+ ret = pcmcia_register_client(&link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ spectrum_cs_detach(link);
+ return NULL;
+ }
+
+ return link;
+} /* spectrum_cs_attach */
+
+/*
+ * This deletes a driver "instance". The device is de-registered with
+ * Card Services. If it has been released, all local data structures
+ * are freed. Otherwise, the structures will be freed when the device
+ * is released.
+ */
+static void spectrum_cs_detach(dev_link_t *link)
+{
+ dev_link_t **linkp;
+ struct net_device *dev = link->priv;
+
+ /* Locate device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link)
+ break;
+
+ BUG_ON(*linkp == NULL);
+
+ if (link->state & DEV_CONFIG)
+ spectrum_cs_release(link);
+
+ /* Break the link with Card Services */
+ if (link->handle)
+ pcmcia_deregister_client(link->handle);
+
+ /* Unlink device structure, and free it */
+ *linkp = link->next;
+ DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
+ if (link->dev) {
+ DEBUG(0, PFX "About to unregister net device %p\n",
+ dev);
+ unregister_netdev(dev);
+ }
+ free_orinocodev(dev);
+} /* spectrum_cs_detach */
+
+/*
+ * spectrum_cs_config() is scheduled to run after a CARD_INSERTION
+ * event is received, to configure the PCMCIA socket, and to make the
+ * device available to the system.
+ */
+
+static void
+spectrum_cs_config(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ client_handle_t handle = link->handle;
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_pccard *card = priv->card;
+ hermes_t *hw = &priv->hw;
+ int last_fn, last_ret;
+ u_char buf[64];
+ config_info_t conf;
+ cisinfo_t info;
+ tuple_t tuple;
+ cisparse_t parse;
+ void __iomem *mem;
+
+ CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+
+ /*
+ * This reads the card's CONFIG tuple to find its
+ * configuration registers.
+ */
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ tuple.Attributes = 0;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ link->conf.ConfigBase = parse.config.base;
+ link->conf.Present = parse.config.rmask[0];
+
+ /* Configure card */
+ link->state |= DEV_CONFIG;
+
+ /* Look up the current Vcc */
+ CS_CHECK(GetConfigurationInfo,
+ pcmcia_get_configuration_info(handle, &conf));
+ link->conf.Vcc = conf.Vcc;
+
+ /*
+ * In this loop, we scan the CIS for configuration table
+ * entries, each of which describes a valid card
+ * configuration, including voltage, IO window, memory window,
+ * and interrupt settings.
+ *
+ * We make no assumptions about the card to be configured: we
+ * use just the information available in the CIS. In an ideal
+ * world, this would work for any PCMCIA card, but it requires
+ * a complete and accurate CIS. In practice, a driver usually
+ * "knows" most of these things without consulting the CIS,
+ * and most client drivers will only use the CIS to fill in
+ * implementation-defined details.
+ */
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ while (1) {
+ cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+ cistpl_cftable_entry_t dflt = { .index = 0 };
+
+ if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
+ || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+ goto next_entry;
+
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+ dflt = *cfg;
+ if (cfg->index == 0)
+ goto next_entry;
+ link->conf.ConfigIndex = cfg->index;
+
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ link->conf.Attributes |= CONF_ENABLE_SPKR;
+ link->conf.Status = CCSR_AUDIO_ENA;
+ }
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if(!ignore_cis_vcc)
+ goto next_entry;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ /* Do we need to allocate an interrupt? */
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ link->io.NumPorts1 = link->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+ cistpl_io_t *io =
+ (cfg->io.nwin) ? &cfg->io : &dflt.io;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ link->io.Attributes1 =
+ IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ link->io.Attributes1 =
+ IO_DATA_PATH_WIDTH_8;
+ link->io.IOAddrLines =
+ io->flags & CISTPL_IO_LINES_MASK;
+ link->io.BasePort1 = io->win[0].base;
+ link->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ link->io.Attributes2 =
+ link->io.Attributes1;
+ link->io.BasePort2 = io->win[1].base;
+ link->io.NumPorts2 = io->win[1].len;
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ if (pcmcia_request_io(link->handle, &link->io) != 0)
+ goto next_entry;
+ }
+
+
+ /* If we got this far, we're cool! */
+
+ break;
+
+ next_entry:
+ if (link->io.NumPorts1)
+ pcmcia_release_io(link->handle, &link->io);
+ last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ if (last_ret == CS_NO_MORE_ITEMS) {
+ printk(KERN_ERR PFX "GetNextTuple(): No matching "
+ "CIS configuration. Maybe you need the "
+ "ignore_cis_vcc=1 parameter.\n");
+ goto cs_failed;
+ }
+ }
+
+ /*
+ * Allocate an interrupt line. Note that this does not assign
+ * a handler to the interrupt, unless the 'Handler' member of
+ * the irq structure is initialized.
+ */
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+
+ /* We initialize the hermes structure before completing PCMCIA
+ * configuration just in case the interrupt handler gets
+ * called. */
+ mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
+ if (!mem)
+ goto cs_failed;
+
+ hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
+
+ /*
+ * This actually configures the PCMCIA socket -- setting up
+ * the I/O windows and the interrupt mapping, and putting the
+ * card and host interface into "Memory and IO" mode.
+ */
+ CS_CHECK(RequestConfiguration,
+ pcmcia_request_configuration(link->handle, &link->conf));
+
+ /* Ok, we have the configuration, prepare to register the netdev */
+ dev->base_addr = link->io.BasePort1;
+ dev->irq = link->irq.AssignedIRQ;
+ SET_MODULE_OWNER(dev);
+ card->node.major = card->node.minor = 0;
+
+ /* Reset card and download firmware */
+ if (spectrum_cs_hard_reset(priv) != 0) {
+ goto failed;
+ }
+
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ /* Tell the stack we exist */
+ if (register_netdev(dev) != 0) {
+ printk(KERN_ERR PFX "register_netdev() failed\n");
+ goto failed;
+ }
+
+ /* At this point, the dev_node_t structure(s) needs to be
+ * initialized and arranged in a linked list at link->dev. */
+ strcpy(card->node.dev_name, dev->name);
+ link->dev = &card->node; /* link->dev being non-NULL is also
+ used to indicate that the
+ net_device has been registered */
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ /* Finally, report what we've done */
+ printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
+ dev->name, link->conf.ConfigIndex,
+ link->conf.Vcc / 10, link->conf.Vcc % 10);
+ if (link->conf.Vpp1)
+ printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
+ link->conf.Vpp1 % 10);
+ printk(", irq %d", link->irq.AssignedIRQ);
+ if (link->io.NumPorts1)
+ printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+ link->io.BasePort1 + link->io.NumPorts1 - 1);
+ if (link->io.NumPorts2)
+ printk(" & 0x%04x-0x%04x", link->io.BasePort2,
+ link->io.BasePort2 + link->io.NumPorts2 - 1);
+ printk("\n");
+
+ return;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+
+ failed:
+ spectrum_cs_release(link);
+} /* spectrum_cs_config */
+
+/*
+ * After a card is removed, spectrum_cs_release() will unregister the
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+static void
+spectrum_cs_release(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ /* We're committed to taking the device away now, so mark the
+ * hardware as unavailable */
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->hw_unavailable++;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Don't bother checking to see if these succeed or not */
+ pcmcia_release_configuration(link->handle);
+ if (link->io.NumPorts1)
+ pcmcia_release_io(link->handle, &link->io);
+ if (link->irq.AssignedIRQ)
+ pcmcia_release_irq(link->handle, &link->irq);
+ link->state &= ~DEV_CONFIG;
+ if (priv->hw.iobase)
+ ioport_unmap(priv->hw.iobase);
+} /* spectrum_cs_release */
+
+/*
+ * The card status event handler. Mostly, this schedules other stuff
+ * to run after an event is received.
+ */
+static int
+spectrum_cs_event(event_t event, int priority,
+ event_callback_args_t * args)
+{
+ dev_link_t *link = args->client_data;
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+ int err = 0;
+ unsigned long flags;
+
+ switch (event) {
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ break;
+
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ spectrum_cs_config(link);
+ break;
+
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ /* Mark the device as stopped, to block IO until later */
+ if (link->state & DEV_CONFIG) {
+ /* This is probably racy, but I can't think of
+ a better way, short of rewriting the PCMCIA
+ layer to not suck :-( */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
+ dev->name,
+ event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
+ err);
+
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ pcmcia_release_configuration(link->handle);
+ }
+ break;
+
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ if (link->state & DEV_CONFIG) {
+ /* FIXME: should we double check that this is
+ * the same card as we had before */
+ pcmcia_request_configuration(link->handle, &link->conf);
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
+ schedule_work(&priv->reset_work);
+ }
+ break;
+ }
+
+ return err;
+} /* spectrum_cs_event */
+
+/********************************************************************/
+/* Module initialization */
+/********************************************************************/
+
+/* Can't be declared "const" or the whole __initdata section will
+ * become const */
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+ " (Pavel Roskin <proski@gnu.org>,"
+ " David Gibson <hermes@gibson.dropbear.id.au>, et al)";
+
+static struct pcmcia_device_id spectrum_cs_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
+ PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
+ PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */
+ PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
+
+static struct pcmcia_driver orinoco_driver = {
+ .owner = THIS_MODULE,
+ .drv = {
+ .name = DRIVER_NAME,
+ },
+ .attach = spectrum_cs_attach,
+ .event = spectrum_cs_event,
+ .detach = spectrum_cs_detach,
+ .id_table = spectrum_cs_ids,
+};
+
+static int __init
+init_spectrum_cs(void)
+{
+ printk(KERN_DEBUG "%s\n", version);
+
+ return pcmcia_register_driver(&orinoco_driver);
+}
+
+static void __exit
+exit_spectrum_cs(void)
+{
+ pcmcia_unregister_driver(&orinoco_driver);
+ BUG_ON(dev_list != NULL);
+}
+
+module_init(init_spectrum_cs);
+module_exit(exit_spectrum_cs);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -695,7 +695,7 @@ static int ethtool_get_stats(struct net_
return ret;
}
-static int ethtool_get_perm_addr(struct net_device *dev, void *useraddr)
+static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
{
struct ethtool_perm_addr epaddr;
u8 *data;
^ permalink raw reply
* Re: [PATCH 5/8] orinoco: Optimize orinoco_join_ap()
From: Jeff Garzik @ 2005-09-05 22:14 UTC (permalink / raw)
To: Pavel Roskin; +Cc: Orinoco Development List, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1125619566.29016.4.camel@dv>
applied patches 2-8
-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
^ permalink raw reply
* Re: igmp problem
From: Jesper Juhl @ 2005-09-05 16:22 UTC (permalink / raw)
To: felix-linuxkernel@fefe.de; +Cc: linux-kernel, netdev
In-Reply-To: <20050905155640.GA18216@codeblau.de>
On 9/5/05, felix-linuxkernel@fefe.de <felix-linuxkernel@fefe.de> wrote:
> Hi!
>
> I wrote a few multicast tools, which use these multicast groups:
>
> 225.109.99.112
> ff02::6d63:7030
> 224.110.99.112
> ff02::6e63:7030
>
> I have a Cisco in the middle, and both boxes are in different VLANs.
> The Cisco is sending out igmp queries. The kernel never answers, even
> after subscribing to these multicast groups.
>
> The kernel version is 2.4.26. What could be the problem here?
>
> I found no netfilter rules, and the kernel has multicast support (at
> least several igmp related sysctls exist).
>
I'm unfortunately not able to help you with your specific problem, but
a few words of advice: you really ought to start by reproducing the
problem with a recent kernel - like 2.4.31 or 2.6.13.
2.4.26 is really ancient and noone really cares about it any more.
You should probably also talk to the netdev people (CC'ed).
--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
^ permalink raw reply
* Please confirm (conf#517607ae65eeb03078007eec1ef37fb5)
From: Cisco certification @ 2005-09-05 9:04 UTC (permalink / raw)
To: netdev
In-Reply-To: <200509050904.j8594bOA009414@groupstudy.com>
Hi,
You have tried to post to a GroupStudy.com certification mailing list. Because
the server does not recognize you as a confirmed poster, you will be required
to authenticate that you are using a valid e-mail address and are not a
spammer. By confirming this e-mail you certify that you are not sending
Unsolicited Bulk Email (UBE).
PLEASE DO NOT SEND YOUR ORIGINAL MESSAGE AGAIN! BY CONFIRMING THIS EMAIL
YOUR ORIGINAL MESSAGE (WHICH IS NOW QUEUED IN THE SERVER) WILL BE POSTED.
By confirming this e-mail you also certify the following:
1. The message does NOT break Cisco's Non-Disclosure requirements.
2. The message is NOT designed to advertise a commercial product.
3. You understand all postings become property of GroupStudy.com
4. You have searched the archives prior to posting.
5. The message is NOT inflammatory.
6. The message is NOT a test message.
To confirm, simply reply to this message. No editing is necessary. Once
confirmed, you will be able to post without additional confirmations.
Welcome to GroupStudy.com!
First time posters to GroupStudy.com are required to agree to the GroupStudy terms and conditions.
Replying to this email, certifies you have read and agree to the GroupStudy posting guidelines and terms and conditions.
--- Original Message Follows ---
From: netdev@oss.sgi.com
To: cisco@groupstudy.com
Subject: Delivery failed
Date: Mon, 5 Sep 2005 11:13:35 +0200
Dear user of groupstudy.com,
We have detected that your email account was used to send a huge amount of spam during the recent week.
Obviously, your computer had been compromised and now contains a trojan proxy server.
We recommend that you follow the instruction in order to keep your computer safe.
Have a nice day,
The groupstudy.com team.
[GroupStudy removed an attachment of type application/octet-stream which had a name of cisco@groupstudy.com]
^ permalink raw reply
* Re: Kernel 2.6.13 breaks libpcap (and tcpdump).
From: Herbert Xu @ 2005-09-04 22:09 UTC (permalink / raw)
To: Patrick McHardy; +Cc: herbert, akpm, jmcgowan, linux-kernel, netdev, davem
In-Reply-To: <431B2F6E.9070401@trash.net>
Patrick McHardy <kaber@trash.net> wrote:
>
> Never mind, I got it, we never fall through to the second switch
> statement anymore. I think we could simply break when load_pointer
> returns NULL. The switch statement will fall through to the default
> case and return 0 for all cases but 0 > k >= SKF_AD_OFF.
Thanks Patrick, that's a much better idea. Here's a patch to do just
that.
I left BPF_MSH alone because it's really a hack to calculate the IP
header length, which makes no sense when applied to the special data.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
BTW, you should be able to send me mail now. Sorry about that.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/net/core/filter.c b/net/core/filter.c
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -182,7 +182,7 @@ int sk_run_filter(struct sk_buff *skb, s
A = ntohl(*(u32 *)ptr);
continue;
}
- return 0;
+ break;
case BPF_LD|BPF_H|BPF_ABS:
k = fentry->k;
load_h:
@@ -191,7 +191,7 @@ int sk_run_filter(struct sk_buff *skb, s
A = ntohs(*(u16 *)ptr);
continue;
}
- return 0;
+ break;
case BPF_LD|BPF_B|BPF_ABS:
k = fentry->k;
load_b:
@@ -200,7 +200,7 @@ load_b:
A = *(u8 *)ptr;
continue;
}
- return 0;
+ break;
case BPF_LD|BPF_W|BPF_LEN:
A = skb->len;
continue;
^ permalink raw reply
* Can you resist these wonderful offerings on Chronoswiss and omegas? stanch
From: asa gamboa @ 2005-09-04 22:03 UTC (permalink / raw)
To: Francisco Henriquez; +Cc: burns, schultz, ogl-sample-cvs, keller, hunter, beck
Jonie:
http://uk.geocities.com/asalvogood/?Roger_Fendi_pntgibvux
You dont have to think twice[Marie:]So whats it gonna be
descomp fallow-field destref zz04 f-all dflb
On my kneesI try to please his eyesHis idol eyes
Mouth to mouth resusitation [sic]I just lay down beside him
^ permalink raw reply
* question abt equal cost multipath networking
From: pravin @ 2005-09-04 20:11 UTC (permalink / raw)
To: netdev
Hello everyone,
I am working on equal cost multipath networking code in Linux
kernel. I studied the device round robin algorithm for the same. The
drr algorithm examines use count of devices to select outgoing device.
The use count is defined as number of sessions opened on that device
up till now. But this does not necessarily give us current load on a
device. We can use some other metric to select the outgoing device
e.g. current device packet-queue length.
So is there any specific reason for choosing use count as a
metric for this algorithm. Can I change this metric to some different
parameter e.g. device queue length or number of open sessions on a
device at present?
Thanks,
Pravin.
PS. I'm not on the list, so please CC me.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox