2002-06-03 11:11:15

by Alessandro Suardi

[permalink] [raw]
Subject: 2.5.20 - Xircom PCI Cardbus doesn't work

In 2.5.19 I got an oops on boot (kindly fixed by Peter's patch),
in 2.5.20 no oopsen but eth0 isn't seen anymore by the kernel:

[...]
Jun 3 12:50:38 dolphin kernel: PCI: Probing PCI hardware
Jun 3 12:50:38 dolphin kernel: PCI: Probing PCI hardware (bus 00)
Jun 3 12:50:38 dolphin kernel: PCI: Address space collision on region 7 of device Intel Corp. 82371AB PIIX4 ACPI [800:83f]
Jun 3 12:50:38 dolphin kernel: PCI: Address space collision on region 8 of device Intel Corp. 82371AB PIIX4 ACPI [840:85f]
Jun 3 12:50:38 dolphin kernel: Unknown bridge resource 2: assuming transparent
Jun 3 12:50:38 dolphin kernel: PCI: Using IRQ router PIIX [8086/7110] at 00:07.0
[...]
Jun 3 12:50:39 dolphin kernel: Linux Kernel Card Services 3.1.22
Jun 3 12:50:39 dolphin kernel: options: [pci] [cardbus] [pm]
Jun 3 12:50:39 dolphin kernel: PCI: Found IRQ 11 for device 00:03.0
Jun 3 12:50:39 dolphin kernel: PCI: Sharing IRQ 11 with 00:03.1
Jun 3 12:50:39 dolphin kernel: PCI: Sharing IRQ 11 with 00:07.2
Jun 3 12:50:39 dolphin keytable: Loading keymap: succeeded
Jun 3 12:50:39 dolphin kernel: PCI: Found IRQ 11 for device 00:03.1
Jun 3 12:50:39 dolphin kernel: PCI: Sharing IRQ 11 with 00:03.0
Jun 3 12:50:39 dolphin kernel: PCI: Sharing IRQ 11 with 00:07.2
Jun 3 12:50:39 dolphin kernel: Yenta IRQ list 06d8, PCI irq11
Jun 3 12:50:39 dolphin kernel: Socket status: 30000020
Jun 3 12:50:39 dolphin kernel: Yenta IRQ list 06d8, PCI irq11
Jun 3 12:50:39 dolphin kernel: Socket status: 30000006
[...]
Jun 3 12:50:39 dolphin kernel: cs: cb_alloc(bus 2): vendor 0x115d, device 0x0003
Jun 3 12:50:39 dolphin kernel: PCI: Enabling device 02:00.0 (0000 -> 0003)
Jun 3 12:50:39 dolphin kernel: PCI: Enabling device 02:00.1 (0000 -> 0003)
[...]
Jun 3 12:50:40 dolphin kernel: cs: IO port probe 0x0100-0x04ff: excluding 0x290-0x297 0x378-0x37f 0x4d0-0x4d7
Jun 3 12:50:40 dolphin cardmgr[597]: socket 0: Xircom CBEM56G-100 CardBus 10/100 Ethernet + 56K Modem
Jun 3 12:50:40 dolphin sshd: Starting sshd:
Jun 3 12:50:37 dolphin network: Bringing up interface eth0: succeeded
Jun 3 12:50:40 dolphin kernel: cs: IO port probe 0x0a00-0x0aff: clean.
Jun 3 12:50:41 dolphin cardmgr[597]: executing: 'modprobe cb_enabler'
Jun 3 12:50:41 dolphin apmd[572]: Battery: * * * (100% 4:15)
Jun 3 12:50:41 dolphin cardmgr[597]: executing: 'modprobe xircom_cb'
Jun 3 12:50:41 dolphin sshd: succeeded
Jun 3 12:50:41 dolphin sshd:
Jun 3 12:50:42 dolphin rc: Starting sshd: succeeded
Jun 3 12:50:42 dolphin cardmgr[597]: get dev info on socket 0 failed: Resource temporarily unavailable

Note that cb_enabler and xircom_cb are aliased to 'off' in
/etc/modules.conf since both are actually built in-kernel.

...back to 2.5.18 for the moment.


Thanks & ciao,

--alessandro

"the hands that build / can also pull down
even the hands of love"
(U2, "Exit")


2002-06-16 18:16:36

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On 16 Jun 2002, Peter Osterlund wrote:
>
> Sure, with an unpatched 2.5.21 kernel, bringing up eth0 fails during
> boot. Tobias Diedrich posted a one-line patch that fixes this problem
> for me:

Ok, that looks correct to me. Good.

> All tests I have done so far with 2.5.21 based kernels produce an oops
> at shutdown, which makes the machine hang instead of rebooting or
> powering off.

This is an IDE one - the IDE driver puts a device that it never got.

I'll do a 2.5.22 (with Tobias' fix too).

Linus

2002-06-06 17:08:50

by Peter Osterlund

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Alessandro Suardi <[email protected]> writes:

> In 2.5.19 I got an oops on boot (kindly fixed by Peter's patch),
> in 2.5.20 no oopsen but eth0 isn't seen anymore by the kernel:

Same problem here. My network card isn't seen either by the kernel in
2.5.20. If it's still broken in 2.5.21, maybe I'll try to fix it.

--
Peter Osterlund - [email protected]
http://w1.894.telia.com/~u89404340

2002-06-09 09:17:22

by Tobias Diedrich

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Peter Osterlund wrote:
> Alessandro Suardi <[email protected]> writes:
>
> > In 2.5.19 I got an oops on boot (kindly fixed by Peter's patch),
> > in 2.5.20 no oopsen but eth0 isn't seen anymore by the kernel:
>
> Same problem here. My network card isn't seen either by the kernel in
> 2.5.20. If it's still broken in 2.5.21, maybe I'll try to fix it.

This oneliner fixes it for me, but I don't know if that's the right fix:

--- linux-2.5.20/drivers/pcmcia/cardbus.c Sat May 25 03:55:22 2002
+++ linux-2.5.20/drivers/pcmcia/cardbus.c Sun Jun 9 02:27:35 2002
@@ -284,6 +284,7 @@
dev->dev.parent = bus->dev;
strcpy(dev->dev.name, dev->name);
strcpy(dev->dev.bus_id, dev->slot_name);
+ dev->dev.bus = &pci_bus_type;
device_register(&dev->dev);

/* FIXME: Do we need to enable the expansion ROM? */

--
Tobias PGP: 0x9AC7E0BC

2002-06-09 10:55:47

by Peter Osterlund

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Tobias Diedrich <[email protected]> writes:

> Peter Osterlund wrote:
> > Alessandro Suardi <[email protected]> writes:
> >
> > > In 2.5.19 I got an oops on boot (kindly fixed by Peter's patch),
> > > in 2.5.20 no oopsen but eth0 isn't seen anymore by the kernel:
> >
> > Same problem here. My network card isn't seen either by the kernel in
> > 2.5.20. If it's still broken in 2.5.21, maybe I'll try to fix it.
>
> This oneliner fixes it for me, but I don't know if that's the right fix:

Thanks, it fixes my problem too. (This patch is still needed in
2.5.21.) However, in 2.5.21 I get an oops at shutdown in
device_detach. This happens both with and without your patch:

flushing ide devices: hda <1>Unable to handle kernel NULL pointer dereference a4
c017ae03
*pde = 00000000
Oops: 0002
CPU: 0
EIP: 0010:[<c017ae03>] Not tainted
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010202
eax: c02f6d24 ebx: c3784000 ecx: 00000000 edx: 00000000
esi: c02f6d0c edi: c0290180 ebp: 00000000 esp: c3785e50
ds: 0018 es: 0018 ss: 0018
Stack: c02f6d0c c02f6bb4 00000001 c017b17d c02f6d0c c02f6bb0 c01b030c c02f6d0c
c02f6bb0 c01a9a26 c02f6bb0 c028fcbc 00000000 00000001 bffffcc8 c011e27c
c028fcbc 00000001 00000000 00000001 c3784000 fee1dead c011e64e c02d8b88
Call Trace: [<c017b17d>] [<c01b030c>] [<c01a9a26>] [<c011e27c>] [<c011e64e>]
[<c01241ec>] [<c020e776>] [<c0208f57>] [<c0138f7b>] [<c014ac2e>] [<c02067a4>
[<c01490ec>] [<c01380ea>] [<c0136bc0>] [<c0136c31>] [<c0106ee7>]
Code: 89 4a 04 89 11 89 46 18 89 40 04 8b 43 10 48 89 43 10 8b 43

>>EIP; c017ae03 <device_detach+53/a0> <=====
Trace; c017b17d <put_device+6d/a0>
Trace; c01b030c <idedisk_cleanup+1c/60>
Trace; c01a9a26 <ata_sys_notify+a6/e0>
Trace; c011e27c <notifier_call_chain+1c/40>
Trace; c011e64e <sys_reboot+fe/2a0>
Trace; c01241ec <handle_mm_fault+6c/120>
Trace; c020e776 <dev_change_flags+106/110>
Trace; c0208f57 <sk_free+37/40>
Trace; c0138f7b <invalidate_inode_buffers+b/70>
Trace; c014ac2e <clear_inode+e/b0>
Trace; c02067a4 <sock_destroy_inode+14/20>
Trace; c01490ec <dput+1c/1a0>
Trace; c01380ea <fput+ea/110>
Trace; c0136bc0 <filp_close+a0/b0>
Trace; c0136c31 <sys_close+61/90>
Trace; c0106ee7 <syscall_call+7/b>
Code; c017ae03 <device_detach+53/a0>
00000000 <_EIP>:
Code; c017ae03 <device_detach+53/a0> <=====
0: 89 4a 04 mov %ecx,0x4(%edx) <=====
Code; c017ae06 <device_detach+56/a0>
3: 89 11 mov %edx,(%ecx)
Code; c017ae08 <device_detach+58/a0>
5: 89 46 18 mov %eax,0x18(%esi)
Code; c017ae0b <device_detach+5b/a0>
8: 89 40 04 mov %eax,0x4(%eax)
Code; c017ae0e <device_detach+5e/a0>
b: 8b 43 10 mov 0x10(%ebx),%eax
Code; c017ae11 <device_detach+61/a0>
e: 48 dec %eax
Code; c017ae12 <device_detach+62/a0>
f: 89 43 10 mov %eax,0x10(%ebx)
Code; c017ae15 <device_detach+65/a0>
12: 8b 43 00 mov 0x0(%ebx),%eax

--
Peter Osterlund - [email protected]
http://w1.894.telia.com/~u89404340

2002-06-10 15:49:23

by Patrick Mochel

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work


On 9 Jun 2002, Peter Osterlund wrote:

> Tobias Diedrich <[email protected]> writes:
>
> > Peter Osterlund wrote:
> > > Alessandro Suardi <[email protected]> writes:
> > >
> > > > In 2.5.19 I got an oops on boot (kindly fixed by Peter's patch),
> > > > in 2.5.20 no oopsen but eth0 isn't seen anymore by the kernel:
> > >
> > > Same problem here. My network card isn't seen either by the kernel in
> > > 2.5.20. If it's still broken in 2.5.21, maybe I'll try to fix it.
> >
> > This oneliner fixes it for me, but I don't know if that's the right fix:
>
> Thanks, it fixes my problem too. (This patch is still needed in
> 2.5.21.) However, in 2.5.21 I get an oops at shutdown in
> device_detach. This happens both with and without your patch:

Sorry about the delay. Could you please try this patch and let me know if
it helps? It attempts to treat cardbus more like PCI, and let the PCI
helpers do the probing.

Note that it's based on the assumption that there is a cardbus bridge for
each cardbus slot. This appears to be true on all systems I've seen, but
it may not hold for all systems. If other people are feeling adventurous,
please give this a try and let me know if it works.

You can pull from bk://ldm.bkbits.net/linux-2.5-cardbus

Thanks,

-pat

[email protected], 2002-06-10 08:35:32-07:00, [email protected]
Treat cardbus more like PCI: let the PCI helpers do more WRT probing

drivers/pci/hotplug.c | 2
drivers/pcmcia/cardbus.c | 114 ++++++++++++++++-------------------------------
2 files changed, 40 insertions, 76 deletions


diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
--- a/drivers/pci/hotplug.c Mon Jun 10 08:42:14 2002
+++ b/drivers/pci/hotplug.c Mon Jun 10 08:42:14 2002
@@ -56,8 +56,6 @@
void
pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
{
- list_add_tail(&dev->bus_list, &bus->devices);
- list_add_tail(&dev->global_list, &pci_devices);
#ifdef CONFIG_PROC_FS
pci_proc_attach_device(dev);
#endif
diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
--- a/drivers/pcmcia/cardbus.c Mon Jun 10 08:42:14 2002
+++ b/drivers/pcmcia/cardbus.c Mon Jun 10 08:42:14 2002
@@ -178,16 +178,21 @@
void read_cb_mem(socket_info_t * s, u_char fn, int space,
u_int addr, u_int len, void *ptr)
{
- struct pci_dev *dev;
+ struct pci_dev *dev = NULL;
struct resource *res;
+ list_t * node;

DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len);

- if (!s->cb_config)
+ list_for_each(node,&s->cap.cb_dev->subordinate->devices) {
+ dev = list_entry(node,struct pci_dev,bus_list);
+ if (PCI_FUNC(dev->devfn) == fn)
+ break;
+ dev = NULL;
+ }
+ if (!dev)
goto fail;

- dev = &s->cb_config[fn].dev;
-
/* Config space? */
if (space == 0) {
if (addr + len > 0x100)
@@ -233,10 +238,10 @@
{
struct pci_bus *bus;
struct pci_dev tmp;
- u_short vend, v, dev;
- u_char i, hdr, fn;
- cb_config_t *c;
+ u16 vend, dev;
int irq;
+ list_t * node;
+ struct pci_dev * pdev;

bus = s->cap.cb_dev->subordinate;
memset(&tmp, 0, sizeof(tmp));
@@ -249,80 +254,43 @@
printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, "
"device 0x%04x\n", bus->number, vend, dev);

- pci_readb(&tmp, PCI_HEADER_TYPE, &hdr);
- fn = 1;
- if (hdr & 0x80) {
- do {
- tmp.devfn = fn;
- if (pci_readw(&tmp, PCI_VENDOR_ID, &v) || !v || v == 0xffff)
- break;
- fn++;
- } while (fn < 8);
- }
- s->functions = fn;
-
- c = kmalloc(fn * sizeof(struct cb_config_t), GFP_ATOMIC);
- if (!c)
- return CS_OUT_OF_RESOURCE;
- memset(c, 0, fn * sizeof(struct cb_config_t));
+ /* let generic PCI code scan bus */
+ pci_do_scan_bus(bus);

+ /* walk the bus again and set the irq for the devices,
+ * enable each one, and let userspace know (pci_insert_device)
+ */
irq = s->cap.pci_irq;
- for (i = 0; i < fn; i++) {
- struct pci_dev *dev = &c[i].dev;
+ list_for_each(node,&bus->devices) {
u8 irq_pin;
- int r;
-
- dev->bus = bus;
- dev->sysdata = bus->sysdata;
- dev->devfn = i;
- dev->vendor = vend;
- pci_readw(dev, PCI_DEVICE_ID, &dev->device);
- dev->hdr_type = hdr & 0x7f;
-
- pci_setup_device(dev);
-
- dev->dev.parent = bus->dev;
- strcpy(dev->dev.name, dev->name);
- strcpy(dev->dev.bus_id, dev->slot_name);
- device_register(&dev->dev);
-
- /* FIXME: Do we need to enable the expansion ROM? */
- for (r = 0; r < 7; r++) {
- struct resource *res = dev->resource + r;
- if (res->flags)
- pci_assign_resource(dev, r);
- }
+ pdev = list_entry(node,struct pci_dev, bus_list);

/* Does this function have an interrupt at all? */
- pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin);
+ pci_readb(pdev, PCI_INTERRUPT_PIN, &irq_pin);
if (irq_pin) {
- dev->irq = irq;
- pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
+ pdev->irq = irq;
+ pci_writeb(pdev, PCI_INTERRUPT_LINE, irq);
}
-
- pci_enable_device(dev); /* XXX check return */
- pci_insert_device(dev, bus);
+ pci_enable_device(pdev);
+ pci_insert_device(pdev,bus);
}
-
- s->cb_config = c;
s->irq.AssignedIRQ = irq;
return CS_SUCCESS;
}

void cb_free(socket_info_t * s)
{
- cb_config_t *c = s->cb_config;
-
- if (c) {
- int i;
+ struct pci_bus * bus = s->cap.cb_dev->subordinate;
+ list_t * node = bus->devices.next;

- s->cb_config = NULL;
- for (i = 0 ; i < s->functions ; i++)
- pci_remove_device(&c[i].dev);

- kfree(c);
- printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
+ while(node != &bus->devices) {
+ struct pci_dev * pdev = list_entry(node,struct pci_dev,bus_list);
+ pci_remove_device(pdev);
+ node = bus->devices.next;
}
+
+ printk(KERN_INFO "cs: cb_free(bus %d)\n", bus->number);
}

/*=====================================================================
@@ -374,27 +342,25 @@

void cb_enable(socket_info_t * s)
{
- struct pci_dev *dev;
- u_char i;
+ list_t * node;
+ struct pci_bus * bus = s->cap.cb_dev->subordinate;

- DEBUG(0, "cs: cb_enable(bus %d)\n", s->cap.cb_dev->subordinate->number);
+ DEBUG(0, "cs: cb_enable(bus %d)\n", bus->number);

/* Configure bridge */
cb_release_cis_mem(s);

/* Set up PCI interrupt and command registers */
- for (i = 0; i < s->functions; i++) {
- dev = &s->cb_config[i].dev;
+ list_for_each(node,&bus->devices) {
+ struct pci_dev * dev = list_entry(node,struct pci_dev,bus_list);
pci_writeb(dev, PCI_COMMAND, PCI_COMMAND_MASTER |
PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
pci_writeb(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
- }

- if (s->irq.AssignedIRQ) {
- for (i = 0; i < s->functions; i++) {
- dev = &s->cb_config[i].dev;
+ if (s->irq.AssignedIRQ)
pci_writeb(dev, PCI_INTERRUPT_LINE, s->irq.AssignedIRQ);
- }
+ }
+ if (s->irq.AssignedIRQ) {
s->socket.io_irq = s->irq.AssignedIRQ;
s->ss_entry->set_socket(s->sock, &s->socket);
}

2002-06-10 19:29:06

by Peter Osterlund

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Patrick Mochel <[email protected]> writes:

> On 9 Jun 2002, Peter Osterlund wrote:
>
> > Tobias Diedrich <[email protected]> writes:
> >
> > > Peter Osterlund wrote:
> > > > Alessandro Suardi <[email protected]> writes:
> > > >
> > > > > in 2.5.20 no oopsen but eth0 isn't seen anymore by the kernel:
> > > >
> > > > Same problem here. My network card isn't seen either by the kernel in
> > > > 2.5.20.
> > >
> > > This oneliner fixes it for me, but I don't know if that's the right fix:
> >
> > Thanks, it fixes my problem too. (This patch is still needed in
> > 2.5.21.) However, in 2.5.21 I get an oops at shutdown in
> > device_detach. This happens both with and without your patch:
>
> Sorry about the delay. Could you please try this patch and let me know if
> it helps? It attempts to treat cardbus more like PCI, and let the PCI
> helpers do the probing.

It doesn't help unfortunately. The network card is not detected at
boot and I get the same oops at shutdown as with a vanilla 2.5.21
kernel.

> Note that it's based on the assumption that there is a cardbus bridge for
> each cardbus slot. This appears to be true on all systems I've seen, but
> it may not hold for all systems.

This is true on my system as well.

Here is the output from dmesg after booting (drivers/pci/probe.c
compiled with debugging turned on):

...
Initializing RT netlink socket
PCI: PCI BIOS revision 2.10 entry at 0xeafd0, last bus=2
PCI: Using configuration type 1
PCI: Probing PCI hardware
PCI: Probing PCI hardware (bus 00)
Scanning bus 00
Found 00:00 [8086/7100] 000600 00
Found 00:38 [8086/7110] 000680 00
Found 00:39 [8086/7111] 000101 00
Found 00:3a [8086/7112] 000c03 00
Found 00:3b [8086/7113] 000680 00
Found 00:40 [5333/8c01] 000300 00
Found 00:50 [104c/ac17] 000607 02
Found 00:51 [104c/ac17] 000607 02
Fixups for bus 00
Scanning behind PCI bridge 00:0a.0, config 000000, pass 0
Scanning behind PCI bridge 00:0a.1, config 000000, pass 0
Scanning behind PCI bridge 00:0a.0, config 000000, pass 1
Scanning behind PCI bridge 00:0a.1, config 000000, pass 1
Bus scan for 00 returning with max=08
PCI: Using IRQ router PIIX [8086/7110] at 00:07.0
PCI: IRQ 0 for device 00:0a.0 doesn't match PIRQ mask - try pci=usepirqmask
PCI: IRQ 0 for device 00:0a.1 doesn't match PIRQ mask - try pci=usepirqmask
apm: BIOS version 1.2 Flags 0x03 (Driver version 1.16)
Starting kswapd
BIO: pool of 256 setup, 14Kb (56 bytes/bio)
biovec: init pool 0, 1 entries, 12 bytes
biovec: init pool 1, 4 entries, 48 bytes
biovec: init pool 2, 16 entries, 192 bytes
biovec: init pool 3, 64 entries, 768 bytes
biovec: init pool 4, 128 entries, 1536 bytes
biovec: init pool 5, 256 entries, 3072 bytes
Limiting direct PCI/PCI transfers.
pty: 256 Unix98 ptys configured
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI en
abled
ttyS00 at 0x03f8 (irq = 4) is a 16550A
ttyS01 at 0x02f8 (irq = 3) is a 16550A
block: 224 slots per queue, batch=32
Floppy drive(s): fd0 is 1.44M
FDC 0 is a post-1991 82077
PPP generic driver version 2.4.2
ATA/ATAPI device driver v7.0.0
ATA: PCI bus speed 33.3MHz
ATA: unknown interface: Intel Corp. 82371AB PIIX4 IDE, PCI slot 00:07.1
hda: TOSHIBA MK4006MAV, DISK drive
hdc: CD-224E, ATAPI CD/DVD-ROM drive
ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
ide1 at 0x170-0x177,0x376 on irq 15
hda: 8007552 sectors, CHS=7944/16/63
hda: [PTBL] [993/128/63] hda1 hda2 hda3 hda4
SCSI subsystem driver Revision: 1.00
scsi0 : SCSI host adapter emulation for ATAPI devices
scsi: device set offline - command error recover failed: host 0 channel 0 id 0 l
un 0
Linux Kernel Card Services 3.1.22
options: [pci] [cardbus] [pm]
PCI: IRQ 0 for device 00:0a.0 doesn't match PIRQ mask - try pci=usepirqmask
PCI: Assigned IRQ 10 for device 00:0a.0
PCI: IRQ 0 for device 00:0a.1 doesn't match PIRQ mask - try pci=usepirqmask
PCI: Assigned IRQ 10 for device 00:0a.1
Intel PCIC probe: not found.
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 4096 bind 4096)
ip_conntrack version 2.0 (512 buckets, 4096 max) - 292 bytes per conntrack
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
Yenta IRQ list 0a98, PCI irq10
Socket status: 30000068
Yenta IRQ list 0a98, PCI irq10
Socket status: 30000006
cs: cb_alloc(bus 1): vendor 0x13d1, device 0xab02
Scanning bus 01
Found 01:00 [13d1/ab02] 000200 00
Fixups for bus 01
Unknown bridge resource 0: assuming transparent
Unknown bridge resource 1: assuming transparent
Unknown bridge resource 2: assuming transparent
Bus scan for 01 returning with max=01
PCI: Device 01:00.0 not available because of resource collisions
VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 196k freed
Adding Swap: 104828k swap-space (priority -1)
usb.c: registered new driver usbfs
usb.c: registered new driver hub
usb-uhci-hcd.c: High bandwidth mode enabled.
PCI: Assigned IRQ 10 for device 00:07.2
hcd-pci.c: usb-uhci-hcd @ 00:07.2, Intel Corp. 82371AB PIIX4 USB
hcd-pci.c: irq 10, io base 0000f300
hcd.c: new USB bus registered, assigned bus number 1
...

--
Peter Osterlund - [email protected]
http://w1.894.telia.com/~u89404340

2002-06-10 21:05:32

by Alessandro Suardi

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Patrick Mochel wrote:
> On 9 Jun 2002, Peter Osterlund wrote:
>
>
>>Tobias Diedrich <[email protected]> writes:
>>
>>
>>>Peter Osterlund wrote:
>>>
>>>>Alessandro Suardi <[email protected]> writes:
>>>>
>>>>
>>>>>In 2.5.19 I got an oops on boot (kindly fixed by Peter's patch),
>>>>> in 2.5.20 no oopsen but eth0 isn't seen anymore by the kernel:
>>>>
>>>>Same problem here. My network card isn't seen either by the kernel in
>>>>2.5.20. If it's still broken in 2.5.21, maybe I'll try to fix it.
>>>
>>>This oneliner fixes it for me, but I don't know if that's the right fix:
>>
>>Thanks, it fixes my problem too. (This patch is still needed in
>>2.5.21.) However, in 2.5.21 I get an oops at shutdown in
>>device_detach. This happens both with and without your patch:
>
>
> Sorry about the delay. Could you please try this patch and let me know if
> it helps? It attempts to treat cardbus more like PCI, and let the PCI
> helpers do the probing.
>
> Note that it's based on the assumption that there is a cardbus bridge for
> each cardbus slot. This appears to be true on all systems I've seen, but
> it may not hold for all systems. If other people are feeling adventurous,
> please give this a try and let me know if it works.
>
> You can pull from bk://ldm.bkbits.net/linux-2.5-cardbus
>
> Thanks,
>
> -pat
>
> [email protected], 2002-06-10 08:35:32-07:00, [email protected]
> Treat cardbus more like PCI: let the PCI helpers do more WRT probing
>
> drivers/pci/hotplug.c | 2
> drivers/pcmcia/cardbus.c | 114 ++++++++++++++++-------------------------------
> 2 files changed, 40 insertions, 76 deletions

[snipped patch]

Still no go, and the card functions are misdetected - cardmgr
attempts to load memory_cs. Full dmesg and /var/log/messages
for this boot in the attached .tar.gz file.


Thanks,


--alessandro

"the hands that build / can also pull down
even the hands of love"
(U2, "Exit")


Attachments:
bootmsgs.tar.gz (4.61 kB)

2002-06-14 16:33:58

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On 10 Jun 2002, Peter Osterlund wrote:
>
> It doesn't help unfortunately. The network card is not detected at
> boot and I get the same oops at shutdown as with a vanilla 2.5.21
> kernel.

Actually, the card seems to be detected, but:

PCI: Device 01:00.0 not available because of resource collisions

Can you enable PCI debugging and send a full log of that? The DEBUG stuff
is sadly a manual diff and a recompile: please manually enable DEBUG in
arch/i386/pci/pci.h and in drivers/pci/*.c (yes, there's not even one
global place, you have to do it individually for each *.c file, ugh).

Linus

2002-06-14 17:20:17

by Peter Osterlund

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Linus Torvalds <[email protected]> writes:

> On 10 Jun 2002, Peter Osterlund wrote:
> >
> > It doesn't help unfortunately. The network card is not detected at
> > boot and I get the same oops at shutdown as with a vanilla 2.5.21
> > kernel.
>
> Actually, the card seems to be detected, but:
>
> PCI: Device 01:00.0 not available because of resource collisions
>
> Can you enable PCI debugging and send a full log of that?

OK, the log is below.

I wonder if this has anything to do with my problem:

PCI: IRQ 0 for device 00:0a.1 doesn't match PIRQ mask - try pci=usepirqmask

I've been seeing this for a long time in 2.5, but never bothered to
investigate because before 2.5.21 it didn't seem to cause any harm.
Passing pci=usepirqmask as boot argument to the kernel doesn't make
any difference.



Linux version 2.5.21-packet ([email protected]) (gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)) #17 Fri Jun 14 18:50:59 CEST 2002
Video mode to be used for restore is ffff
BIOS-provided physical RAM map:
BIOS-e801: 0000000000000000 - 000000000009f000 (usable)
BIOS-e801: 0000000000100000 - 0000000004000000 (usable)
64MB LOWMEM available.
On node 0 totalpages: 16384
zone(0): 4096 pages.
zone(1): 12288 pages.
zone(2): 0 pages.
Kernel command line: auto BOOT_IMAGE=test ro root=304 BOOT_FILE=/vmlinuz console=ttyS0,115200n8
Initializing CPU#0
Detected 233.866 MHz processor.
Console: colour VGA+ 80x25
Calibrating delay loop... 466.94 BogoMIPS
Memory: 62696k/65536k available (1152k kernel code, 2452k reserved, 287k data, 200k init, 0k highmem)
Dentry-cache hash table entries: 8192 (order: 4, 65536 bytes)
Inode-cache hash table entries: 4096 (order: 3, 32768 bytes)
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
Intel Pentium with F0 0F bug - workaround enabled.
CPU: Intel Pentium MMX stepping 03
Checking 'hlt' instruction... OK.
POSIX conformance testing by UNIFIX
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
PCI: BIOS32 Service Directory structure at 0xc00e8050
PCI: BIOS32 Service Directory entry at 0xeaf90
PCI: BIOS probe returned s=00 hw=01 ver=02.10 l=02
PCI: PCI BIOS revision 2.10 entry at 0xeafd0, last bus=2
PCI: Using configuration type 1
PCI: Probing PCI hardware
PCI: Probing PCI hardware (bus 00)
Scanning bus 00
Found 00:00 [8086/7100] 000600 00
PCI: Calling quirk c01d5650 for 00:00.0
Found 00:38 [8086/7110] 000680 00
PCI: Calling quirk c01d5650 for 00:07.0
Found 00:39 [8086/7111] 000101 00
PCI: Calling quirk c01d5650 for 00:07.1
PCI: IDE base address fixup for 00:07.1
Found 00:3a [8086/7112] 000c03 00
PCI: Calling quirk c01d5650 for 00:07.2
PCI: Calling quirk c0273da0 for 00:07.2
Found 00:3b [8086/7113] 000680 00
PCI: Calling quirk c01d5650 for 00:07.3
PCI: Calling quirk c01d5720 for 00:07.3
PCI: Calling quirk c0273be0 for 00:07.3
Found 00:40 [5333/8c01] 000300 00
PCI: Calling quirk c01d5650 for 00:08.0
Found 00:50 [104c/ac17] 000607 02
PCI: Calling quirk c01d5650 for 00:0a.0
Found 00:51 [104c/ac17] 000607 02
PCI: Calling quirk c01d5650 for 00:0a.1
Fixups for bus 00
PCI: Scanning for ghost devices on bus 0
Scanning behind PCI bridge 00:0a.0, config 000000, pass 0
Scanning behind PCI bridge 00:0a.1, config 000000, pass 0
Scanning behind PCI bridge 00:0a.0, config 000000, pass 1
Scanning behind PCI bridge 00:0a.1, config 000000, pass 1
Bus scan for 00 returning with max=08
PCI: Peer bridge fixup
PCI: IRQ init
PCI: Interrupt Routing Table found at 0xc00fe840
00:07 slot=00 0:00/1eb8 1:00/1eb8 2:00/1eb8 3:63/0400
00:0a slot=00 0:60/0400 1:61/0400 2:00/0400 3:00/0400
00:0c slot=00 0:60/1eb8 1:00/1eb8 2:00/1eb8 3:00/1eb8
PCI: Attempting to find IRQ router for 8086:122e
PCI: Using IRQ router PIIX [8086/7110] at 00:07.0
PCI: IRQ fixup
00:0a.0: ignoring bogus IRQ 255
00:0a.1: ignoring bogus IRQ 255
IRQ for 00:0a.0:0 -> PIRQ 60, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.0 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=0 ... failed
IRQ for 00:0a.1:1 -> PIRQ 61, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.1 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=0 ... failed
PCI: Allocating resources
PCI: Resource 00001100-0000110f (f=101, d=0, p=0)
PCI: Resource 0000f300-0000f31f (f=101, d=0, p=0)
PCI: Resource c0000000-c3ffffff (f=200, d=0, p=0)
got res[10000000:10000fff] for resource 0 of Texas Instruments PCI1220
got res[10001000:10001fff] for resource 0 of Texas Instruments PCI1220 (#2)
PCI: Sorting device list...
apm: BIOS version 1.2 Flags 0x03 (Driver version 1.16)
Starting kswapd
BIO: pool of 256 setup, 14Kb (56 bytes/bio)
biovec: init pool 0, 1 entries, 12 bytes
biovec: init pool 1, 4 entries, 48 bytes
biovec: init pool 2, 16 entries, 192 bytes
biovec: init pool 3, 64 entries, 768 bytes
biovec: init pool 4, 128 entries, 1536 bytes
biovec: init pool 5, 256 entries, 3072 bytes
PCI: Calling quirk c0273950 for 00:00.0
Limiting direct PCI/PCI transfers.
PCI: Calling quirk c0273e10 for 00:00.0
PCI: Calling quirk c0273e10 for 00:07.0
PCI: Calling quirk c0273e10 for 00:07.1
PCI: Calling quirk c0273e10 for 00:07.2
PCI: Calling quirk c0273e10 for 00:07.3
PCI: Calling quirk c0273e10 for 00:08.0
PCI: Calling quirk c0273e10 for 00:0a.0
PCI: Calling quirk c0273e10 for 00:0a.1
pty: 256 Unix98 ptys configured
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled
ttyS00 at 0x03f8 (irq = 4) is a 16550A
ttyS01 at 0x02f8 (irq = 3) is a 16550A
block: 224 slots per queue, batch=32
Floppy drive(s): fd0 is 1.44M
FDC 0 is a post-1991 82077
PPP generic driver version 2.4.2
ATA/ATAPI device driver v7.0.0
ATA: PCI bus speed 33.3MHz
ATA: unknown interface: Intel Corp. 82371AB PIIX4 IDE, PCI slot 00:07.1
hda: TOSHIBA MK4006MAV, DISK drive
hdc: CD-224E, ATAPI CD/DVD-ROM drive
ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
ide1 at 0x170-0x177,0x376 on irq 15
hda: 8007552 sectors, CHS=7944/16/63
hda: [PTBL] [993/128/63] hda1 hda2 hda3 hda4
SCSI subsystem driver Revision: 1.00
scsi0 : SCSI host adapter emulation for ATAPI devices
scsi: device set offline - command error recover failed: host 0 channel 0 id 0 lun 0
Linux Kernel Card Services 3.1.22
options: [pci] [cardbus] [pm]
IRQ for 00:0a.0:0 -> PIRQ 60, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.0 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=10 -> assigning IRQ 10 -> edge ... OK
PCI: Assigned IRQ 10 for device 00:0a.0
IRQ for 00:0a.1:1 -> PIRQ 61, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.1 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=10 -> assigning IRQ 10 ... OK
PCI: Assigned IRQ 10 for device 00:0a.1
Intel PCIC probe: not found.
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 4096 bind 4096)
ip_conntrack version 2.0 (512 buckets, 4096 max) - 292 bytes per conntrack
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
Yenta IRQ list 0a98, PCI irq10
Socket status: 30000068
Yenta IRQ list 0a98, PCI irq10
Socket status: 30000006
cs: cb_alloc(bus 1): vendor 0x13d1, device 0xab02
Scanning bus 01
Found 01:00 [13d1/ab02] 000200 00
PCI: Calling quirk c01d5650 for 01:00.0
Fixups for bus 01
PCI: Scanning for ghost devices on bus 1
Unknown bridge resource 0: assuming transparent
Unknown bridge resource 1: assuming transparent
Unknown bridge resource 2: assuming transparent
Bus scan for 01 returning with max=01
PCI: Device 01:00.0 not available because of resource collisions
VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 200k freed
INIT: version 2.78 booting
Welcome to Red Hat Linux

--
Peter Osterlund - [email protected]
http://w1.894.telia.com/~u89404340

2002-06-14 17:47:22

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On 14 Jun 2002, Peter Osterlund wrote:
>
> cs: cb_alloc(bus 1): vendor 0x13d1, device 0xab02
> Scanning bus 01
> Found 01:00 [13d1/ab02] 000200 00

Ok, it found a regular PCI network card (000200) with a regular header
(00), and it will have read all the resources but not _allocated_ them
yet.

> PCI: Calling quirk c01d5650 for 01:00.0
> Fixups for bus 01
> PCI: Scanning for ghost devices on bus 1
> Unknown bridge resource 0: assuming transparent
> Unknown bridge resource 1: assuming transparent
> Unknown bridge resource 2: assuming transparent
> Bus scan for 01 returning with max=01
> PCI: Device 01:00.0 not available because of resource collisions

And here it calls it unavailable, because it notices that the device has
resources, but they haven't been allocated, so it assumes that lack of
allocation is due to some resource conflict.

However, it _looks_ like the lack of resource allocation is simply because
we never bothered to even try to allocate them.

Pat, your change to use "pci_do_scan_bus()" seems to have dropped the:

/* FIXME: Do we need to enable the expansion ROM? */
for (r = 0; r < 7; r++) {
struct resource *res = dev->resource + r;
if (res->flags)
pci_assign_resource(dev, r);
}

thing completely, which is the thing that actually _allocates_ and assigns
the resources.

Peter, mind adding that resource allocation loop to the "cb_alloc()"
function, inside the "list_for_each(node,&bus->devices) {" loop? Just
before the "Does this function have an interrupt at all?" line..

Alternatively, maybe that resource allocation might just be done in
"pci_enable_device()". It does kind of make sense at that point, instead
of just giving up due to unallocated resources..

Linus

2002-06-14 17:54:12

by Vojtech Pavlik

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

On Fri, Jun 14, 2002 at 10:47:20AM -0700, Linus Torvalds wrote:
>
>
> On 14 Jun 2002, Peter Osterlund wrote:
> >
> > cs: cb_alloc(bus 1): vendor 0x13d1, device 0xab02
> > Scanning bus 01
> > Found 01:00 [13d1/ab02] 000200 00
>
> Ok, it found a regular PCI network card (000200) with a regular header
> (00), and it will have read all the resources but not _allocated_ them
> yet.
>
> > PCI: Calling quirk c01d5650 for 01:00.0
> > Fixups for bus 01
> > PCI: Scanning for ghost devices on bus 1
> > Unknown bridge resource 0: assuming transparent
> > Unknown bridge resource 1: assuming transparent
> > Unknown bridge resource 2: assuming transparent
> > Bus scan for 01 returning with max=01
> > PCI: Device 01:00.0 not available because of resource collisions
>
> And here it calls it unavailable, because it notices that the device has
> resources, but they haven't been allocated, so it assumes that lack of
> allocation is due to some resource conflict.
>
> However, it _looks_ like the lack of resource allocation is simply because
> we never bothered to even try to allocate them.
>
> Pat, your change to use "pci_do_scan_bus()" seems to have dropped the:
>
> /* FIXME: Do we need to enable the expansion ROM? */
> for (r = 0; r < 7; r++) {
> struct resource *res = dev->resource + r;
> if (res->flags)
> pci_assign_resource(dev, r);
> }
>
> thing completely, which is the thing that actually _allocates_ and assigns
> the resources.

Could this be what has bitten us with new Intel IDE controllers on
latest 2.5? They also were disabled due to 'resource collisions', and
had some i/o not allocated at all - just size was nonzero. It was fixed
in the quirks code by clearing the size fields, because the i/o space
isn't needed ...

> Peter, mind adding that resource allocation loop to the "cb_alloc()"
> function, inside the "list_for_each(node,&bus->devices) {" loop? Just
> before the "Does this function have an interrupt at all?" line..
>
> Alternatively, maybe that resource allocation might just be done in
> "pci_enable_device()". It does kind of make sense at that point, instead
> of just giving up due to unallocated resources..
>
> Linus
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

--
Vojtech Pavlik
SuSE Labs

2002-06-14 18:05:48

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On Fri, 14 Jun 2002, Vojtech Pavlik wrote:
>
> Could this be what has bitten us with new Intel IDE controllers on
> latest 2.5? They also were disabled due to 'resource collisions', and
> had some i/o not allocated at all - just size was nonzero. It was fixed
> in the quirks code by clearing the size fields, because the i/o space
> isn't needed ...

That's not this particular code - this code only handles PCMCIA.

But yes, it's the same issue: a resource that wasn't allocated by
the BIOS, and that the Linux boot sequence didn't bother to allocate
either. The PCI sequence _should_ allocate resources for non-PCMCIA
devices in pcibios_resource_survey(), where it does

pcibios_assign_resources();

but the fact is, that that code is explicitly disabled for IDE
controllers. See pcibios_assign_resources() in arch/i386/pci/i386.c.

I suspect that forcing resource assignment into "pci_enable_device()"
should fix that too.

Although there should probably be some way for the driver to tell which
resources it cares about (some drivers care about the PCI ROM's, for
example, others don't. Some drivers don't care about the IO region, and
others don't care about the MEM region). So the _right_ answer might be to
pass in a bitmap to "pci_enable_device()", which tells the enable code
which parts the driver really cares about..

Linus

2002-06-14 18:12:23

by Kai Germaschewski

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

On Fri, 14 Jun 2002, Linus Torvalds wrote:

> I suspect that forcing resource assignment into "pci_enable_device()"
> should fix that too.
>
> Although there should probably be some way for the driver to tell which
> resources it cares about (some drivers care about the PCI ROM's, for
> example, others don't. Some drivers don't care about the IO region, and
> others don't care about the MEM region). So the _right_ answer might be to
> pass in a bitmap to "pci_enable_device()", which tells the enable code
> which parts the driver really cares about..

That reminds me of some idea I had been thinking about for some time:

What about adding some pci_request_irq() and pci_request_{,mem_}_region,
which would allow for some cleanup of ever-recurring code sequences in
drivers, and which at the same time would allow for the above?
pci_request_mem_region() might even include the ioremap() as well ;)

And yeah, eventually, that might be better done at 'struct device' level,
but that doesn't make a difference to the conceptual idea.

--Kai

2002-06-14 18:18:47

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On Fri, 14 Jun 2002, Kai Germaschewski wrote:
>
> What about adding some pci_request_irq() and pci_request_{,mem_}_region,
> which would allow for some cleanup of ever-recurring code sequences in
> drivers, and which at the same time would allow for the above?
> pci_request_mem_region() might even include the ioremap() as well ;)

That might be the right solution - leave "pci_enable_dev()" as-is, and
just consider that the legacy way of "enable stuff that got allocated
automatically".

And make new drivers start using "pci_request_irq()" and friends.

(The current "pci_enable_dev()" is broken in many respects: sometimes you
do NOT want to enable the IRQ until you have set up the device, but in
order to set up the device you may need to know _which_ irq it will have,
and you need to enable access to memory and IO regions and map the
device).

Linus

2002-06-14 18:30:49

by Peter Osterlund

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Linus Torvalds <[email protected]> writes:

> However, it _looks_ like the lack of resource allocation is simply because
> we never bothered to even try to allocate them.
>
> Pat, your change to use "pci_do_scan_bus()" seems to have dropped the:
>
> /* FIXME: Do we need to enable the expansion ROM? */
> for (r = 0; r < 7; r++) {
> struct resource *res = dev->resource + r;
> if (res->flags)
> pci_assign_resource(dev, r);
> }
>
> thing completely, which is the thing that actually _allocates_ and assigns
> the resources.
>
> Peter, mind adding that resource allocation loop to the "cb_alloc()"
> function, inside the "list_for_each(node,&bus->devices) {" loop? Just
> before the "Does this function have an interrupt at all?" line..

OK, with the patch below I get a little further. The kernel no longer
complains about resource collisions, bringing up eth0 works, but the
network card is still not usable:

eth0: Transmit timed out, status ffffffff, CSR12 ffffffff, resetting...
eth0: Out-of-sync dirty pointer, 0 vs. 17.


--- linux/drivers/pcmcia/cardbus.c.old Fri Jun 14 20:04:45 2002
+++ linux/drivers/pcmcia/cardbus.c Fri Jun 14 20:06:39 2002
@@ -262,9 +262,17 @@
*/
irq = s->cap.pci_irq;
list_for_each(node,&bus->devices) {
+ int r;
u8 irq_pin;
pdev = list_entry(node,struct pci_dev, bus_list);

+ /* FIXME: Do we need to enable the expansion ROM? */
+ for (r = 0; r < 7; r++) {
+ struct resource *res = pdev->resource + r;
+ if (res->flags)
+ pci_assign_resource(pdev, r);
+ }
+
/* Does this function have an interrupt at all? */
pci_readb(pdev, PCI_INTERRUPT_PIN, &irq_pin);
if (irq_pin) {


Linux version 2.5.21-packet ([email protected]) (gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)) #18 Fri Jun 14 20:06:47 CEST 2002
Video mode to be used for restore is ffff
BIOS-provided physical RAM map:
BIOS-e801: 0000000000000000 - 000000000009f000 (usable)
BIOS-e801: 0000000000100000 - 0000000004000000 (usable)
64MB LOWMEM available.
On node 0 totalpages: 16384
zone(0): 4096 pages.
zone(1): 12288 pages.
zone(2): 0 pages.
Kernel command line: auto BOOT_IMAGE=test ro root=304 BOOT_FILE=/vmlinuz console=ttyS0,115200n8
Initializing CPU#0
Detected 233.868 MHz processor.
Console: colour VGA+ 80x25
Calibrating delay loop... 466.94 BogoMIPS
Memory: 62696k/65536k available (1152k kernel code, 2452k reserved, 287k data, 200k init, 0k highmem)
Dentry-cache hash table entries: 8192 (order: 4, 65536 bytes)
Inode-cache hash table entries: 4096 (order: 3, 32768 bytes)
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
Intel Pentium with F0 0F bug - workaround enabled.
CPU: Intel Pentium MMX stepping 03
Checking 'hlt' instruction... OK.
POSIX conformance testing by UNIFIX
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
PCI: BIOS32 Service Directory structure at 0xc00e8050
PCI: BIOS32 Service Directory entry at 0xeaf90
PCI: BIOS probe returned s=00 hw=01 ver=02.10 l=02
PCI: PCI BIOS revision 2.10 entry at 0xeafd0, last bus=2
PCI: Using configuration type 1
PCI: Probing PCI hardware
PCI: Probing PCI hardware (bus 00)
Scanning bus 00
Found 00:00 [8086/7100] 000600 00
PCI: Calling quirk c01d56a0 for 00:00.0
Found 00:38 [8086/7110] 000680 00
PCI: Calling quirk c01d56a0 for 00:07.0
Found 00:39 [8086/7111] 000101 00
PCI: Calling quirk c01d56a0 for 00:07.1
PCI: IDE base address fixup for 00:07.1
Found 00:3a [8086/7112] 000c03 00
PCI: Calling quirk c01d56a0 for 00:07.2
PCI: Calling quirk c0273da0 for 00:07.2
Found 00:3b [8086/7113] 000680 00
PCI: Calling quirk c01d56a0 for 00:07.3
PCI: Calling quirk c01d5770 for 00:07.3
PCI: Calling quirk c0273be0 for 00:07.3
Found 00:40 [5333/8c01] 000300 00
PCI: Calling quirk c01d56a0 for 00:08.0
Found 00:50 [104c/ac17] 000607 02
PCI: Calling quirk c01d56a0 for 00:0a.0
Found 00:51 [104c/ac17] 000607 02
PCI: Calling quirk c01d56a0 for 00:0a.1
Fixups for bus 00
PCI: Scanning for ghost devices on bus 0
Scanning behind PCI bridge 00:0a.0, config 000000, pass 0
Scanning behind PCI bridge 00:0a.1, config 000000, pass 0
Scanning behind PCI bridge 00:0a.0, config 000000, pass 1
Scanning behind PCI bridge 00:0a.1, config 000000, pass 1
Bus scan for 00 returning with max=08
PCI: Peer bridge fixup
PCI: IRQ init
PCI: Interrupt Routing Table found at 0xc00fe840
00:07 slot=00 0:00/1eb8 1:00/1eb8 2:00/1eb8 3:63/0400
00:0a slot=00 0:60/0400 1:61/0400 2:00/0400 3:00/0400
00:0c slot=00 0:60/1eb8 1:00/1eb8 2:00/1eb8 3:00/1eb8
PCI: Attempting to find IRQ router for 8086:122e
PCI: Using IRQ router PIIX [8086/7110] at 00:07.0
PCI: IRQ fixup
00:0a.0: ignoring bogus IRQ 255
00:0a.1: ignoring bogus IRQ 255
IRQ for 00:0a.0:0 -> PIRQ 60, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.0 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=0 ... failed
IRQ for 00:0a.1:1 -> PIRQ 61, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.1 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=0 ... failed
PCI: Allocating resources
PCI: Resource 00001100-0000110f (f=101, d=0, p=0)
PCI: Resource 0000f300-0000f31f (f=101, d=0, p=0)
PCI: Resource c0000000-c3ffffff (f=200, d=0, p=0)
got res[10000000:10000fff] for resource 0 of Texas Instruments PCI1220
got res[10001000:10001fff] for resource 0 of Texas Instruments PCI1220 (#2)
PCI: Sorting device list...
apm: BIOS version 1.2 Flags 0x03 (Driver version 1.16)
Starting kswapd
BIO: pool of 256 setup, 14Kb (56 bytes/bio)
biovec: init pool 0, 1 entries, 12 bytes
biovec: init pool 1, 4 entries, 48 bytes
biovec: init pool 2, 16 entries, 192 bytes
biovec: init pool 3, 64 entries, 768 bytes
biovec: init pool 4, 128 entries, 1536 bytes
biovec: init pool 5, 256 entries, 3072 bytes
PCI: Calling quirk c0273950 for 00:00.0
Limiting direct PCI/PCI transfers.
PCI: Calling quirk c0273e10 for 00:00.0
PCI: Calling quirk c0273e10 for 00:07.0
PCI: Calling quirk c0273e10 for 00:07.1
PCI: Calling quirk c0273e10 for 00:07.2
PCI: Calling quirk c0273e10 for 00:07.3
PCI: Calling quirk c0273e10 for 00:08.0
PCI: Calling quirk c0273e10 for 00:0a.0
PCI: Calling quirk c0273e10 for 00:0a.1
pty: 256 Unix98 ptys configured
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled
ttyS00 at 0x03f8 (irq = 4) is a 16550A
ttyS01 at 0x02f8 (irq = 3) is a 16550A
block: 224 slots per queue, batch=32
Floppy drive(s): fd0 is 1.44M
FDC 0 is a post-1991 82077
PPP generic driver version 2.4.2
ATA/ATAPI device driver v7.0.0
ATA: PCI bus speed 33.3MHz
ATA: unknown interface: Intel Corp. 82371AB PIIX4 IDE, PCI slot 00:07.1
hda: TOSHIBA MK4006MAV, DISK drive
hdc: CD-224E, ATAPI CD/DVD-ROM drive
ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
ide1 at 0x170-0x177,0x376 on irq 15
hda: 8007552 sectors, CHS=7944/16/63
hda: [PTBL] [993/128/63] hda1 hda2 hda3 hda4
SCSI subsystem driver Revision: 1.00
scsi0 : SCSI host adapter emulation for ATAPI devices
scsi: device set offline - command error recover failed: host 0 channel 0 id 0 lun 0
Linux Kernel Card Services 3.1.22
options: [pci] [cardbus] [pm]
IRQ for 00:0a.0:0 -> PIRQ 60, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.0 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=10 -> assigning IRQ 10 -> edge ... OK
PCI: Assigned IRQ 10 for device 00:0a.0
IRQ for 00:0a.1:1 -> PIRQ 61, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.1 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=10 -> assigning IRQ 10 ... OK
PCI: Assigned IRQ 10 for device 00:0a.1
Intel PCIC probe: not found.
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 4096 bind 4096)
ip_conntrack version 2.0 (512 buckets, 4096 max) - 292 bytes per conntrack
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
Yenta IRQ list 0a98, PCI irq10
Socket status: 30000068
Yenta IRQ list 0a98, PCI irq10
Socket status: 30000006
cs: cb_alloc(bus 1): vendor 0x13d1, device 0xab02
Scanning bus 01
Found 01:00 [13d1/ab02] 000200 00
PCI: Calling quirk c01d56a0 for 01:00.0
Fixups for bus 01
PCI: Scanning for ghost devices on bus 1
Unknown bridge resource 0: assuming transparent
Unknown bridge resource 1: assuming transparent
Unknown bridge resource 2: assuming transparent
Bus scan for 01 returning with max=01
got res[1800:18ff] for resource 0 of PCI device 13d1:ab02 (Abocom Systems Inc)
got res[10002000:100023ff] for resource 1 of PCI device 13d1:ab02 (Abocom Systems Inc)
got res[10020000:1003ffff] for resource 6 of PCI device 13d1:ab02 (Abocom Systems Inc)
PCI: Enabling device 01:00.0 (0000 -> 0003)
IRQ for 01:00.0:0 -> not found in routing table
VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 200k freed
INIT: version 2.78 booting
Welcome to Red Hat Linux
Press 'I' to enter interactive startup.
Mounting proc filesystem: [ OK ]
Configuring kernel parameters: [ OK ]
modprobe: modprobe: cannot create /var/log/ksymoops/20020614.log Read-only file system
modprobe: modprobe: cannot create /var/log/ksymoops/20020614.log Read-only file system
Setting clock (utc): Fri Jun 14 20:09:35 CEST 2002 [ OK ]
Activating swap partitions: [ OK ]
Setting hostname pengo.localdomain: [ OK ]
modprobe: cannot create /var/log/ksymoops/20020614.log Read-only file system
/lib/modules/2.5.21-packet/kernel/drivers/usb/core/usbcore.o: cannot create /var/log/ksymoops/20020614200935.ksyms Read-only file system
/lib/modules/2.5.21-packet/kernel/drivers/usb/core/usbcore.o: cannot create /var/log/ksymoops/20020614.log Read-only file system
Mounting USB filesystem: [ OK ]
Initializing USB controller (usb-uhci-hcd): [ OK ]
Checking root filesystem
/dev/hda4: clean, 133078/759808 files, 2827438/3032064 blocks
[/sbin/fsck.ext2 -- /] fsck.ext2 -a /dev/hda4
[ OK ]
Remounting root filesystem in read-write mode: [ OK ]
Finding module dependencies: [ OK ]
Checking filesystems
Checking all file systems.
[ OK ]
Mounting local filesystems: [ OK ]
Turning on user and group quotas for local filesystems: [ OK ]
Enabling swap space: [ OK ]
INIT: Entering runlevel: 3
Entering non-interactive startup
Starting up APM daemon: [ OK ]
apmd[198]: Charge: * * * (-1% unknown)
Setting network parameters: [ OK ]
Bringing up interface lo: [ OK ]
Bringing up interface eth0: [ OK ]
Starting system logger: [ OK ]
Starting kernel logger: [ OK ]
Starting portmapper: [ OK ]
Starting NFS file locking services:
Starting NFS statd: [ OK ]
Starting automount:[ OK ]
Initializing random number generator: [ OK ]
Mounting other filesystems: [ OK ]
Starting identd: [ OK ]
Starting atd: [ OK ]
Starting pcmcia: [ OK ]
Starting xinetd: [ OK ]
Starting named: [ OK ]
Starting lpd: [ OK ]
Starting NFS services: eth0: Transmit timed out, status ffffffff, CSR12 ffffffff, resetting...
eth0: Transmit timed out, status ffffffff, CSR12 ffffffff, resetting...
eth0: Out-of-sync dirty pointer, 0 vs. 17.
eth0: Transmit timed out, status ffffffff, CSR12 ffffffff, resetting...
[ OK ]
Starting NFS quotas: [ OK ]
Starting NFS mountd: eth0: Transmit timed out, status ffffffff, CSR12 ffffffff, resetting...
eth0: Out-of-sync dirty pointer, 16 vs. 33.
INIT: Switching to runlevel: 6
INIT: Sending processes the TERM signal
Stopping named: [ OK ]
Stopping xinetd: [ OK ]
Stopping atd: [ OK ]
Stopping lpd: [ OK ]
Stopping identd: [ OK ]
Shutting down NFS file locking services:
Shutting down NFS statd: [ OK ]
Saving random seed: [ OK ]
Stopping automount:[ OK ]
Stopping portmapper: [ OK ]
Shutting down kernel logger: [ OK ]
Shutting down system logger: [ OK ]
Shutting down interface eth0: [ OK ]
Shutting down APM daemon: [ OK ]
Starting killall: [ OK ]
Sending all processes the TERM signal...
Sending all processes the KILL signal...
Syncing hardware clock to system time
Turning off swap:
Turning off quotas:
Unmounting file systems:
Unmounting proc file system:
Please stand by while rebooting the system...
flushing ide devices: hda <1>Unable to handle kernel NULL pointer dereference at virtual address 00000004
printing eip:
c017aea3
*pde = 00000000
Oops: 0002
CPU: 0
EIP: 0010:[<c017aea3>] Not tainted
EFLAGS: 00010202
eax: c02c6d24 ebx: c37bc000 ecx: 00000000 edx: 00000000
esi: c02c6d0c edi: c02622a0 ebp: 00000000 esp: c37bde50
ds: 0018 es: 0018 ss: 0018
Process reboot (pid: 924, threadinfo=c37bc000 task=c11d3760)
Stack: c02c6d0c c02c6bb4 00000001 c017b21d c02c6d0c c02c6bb0 c01b03ac c02c6d0c
c02c6bb0 c01a9ac6 c02c6bb0 c0261ddc 00000000 00000001 bffffcc8 c011e27c
c0261ddc 00000001 00000000 00000001 c37bc000 fee1dead c011e64e c02a8b88
Call Trace: [<c017b21d>] [<c01b03ac>] [<c01a9ac6>] [<c011e27c>] [<c011e64e>]
[<c01241ec>] [<c01de9a6>] [<c01d9187>] [<c0138f7b>] [<c014ac2e>] [<c01d69d4>]
[<c01490ec>] [<c01380ea>] [<c0136bc0>] [<c0136c31>] [<c0106ee7>]

Code: 89 4a 04 89 11 89 46 18 89 40 04 8b 43 10 48 89 43 10 8b 43
<6>note: reboot[924] exited with preempt_count 2
/etc/rc6.d/S01reboot: line 1: 924 Segmentation fault reboot -i -d -p
INIT: no more processes left in this runlevel

--
Peter Osterlund - [email protected]
http://w1.894.telia.com/~u89404340

2002-06-14 18:51:30

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On 14 Jun 2002, Peter Osterlund wrote:
>
> OK, with the patch below I get a little further. The kernel no longer
> complains about resource collisions, bringing up eth0 works, but the
> network card is still not usable:
>
> eth0: Transmit timed out, status ffffffff, CSR12 ffffffff, resetting...
> eth0: Out-of-sync dirty pointer, 0 vs. 17.

Some part of your resource isn't mapped through the cardbus bridge. Either
because the bridge resources themselves were wrong, or because we didn't
enable the resouce after we allocated it (the latter is unlikely, as any
"pci_enable_dev()" will do that part).

> Yenta IRQ list 0a98, PCI irq10
> Socket status: 30000068
> Yenta IRQ list 0a98, PCI irq10
> Socket status: 30000006
> cs: cb_alloc(bus 1): vendor 0x13d1, device 0xab02
> Scanning bus 01
> Found 01:00 [13d1/ab02] 000200 00
> PCI: Calling quirk c01d56a0 for 01:00.0
> Fixups for bus 01
> PCI: Scanning for ghost devices on bus 1
> Unknown bridge resource 0: assuming transparent
> Unknown bridge resource 1: assuming transparent
> Unknown bridge resource 2: assuming transparent

This is the problem.

The PCI code thinks that the parent of the network device doesn't have
resources allocated, so it will allocate the resources from the parent of
the parent.

Which is wrong, since it means that it will try to allocate the PCI
resources from outside the window that the cardbus controller is
exporting. Resulting in the fffff stuff.

HOWEVER, I don't see why that happens. yenta_allocate_resources() should
have made absolutely certain that we have all the necessary bridge
resources clearly allocated. Can you add debug code to the end of
"yenta_allocate_res()" that prints out the resource that got allocated?

Pat?

Linus


2002-06-14 19:35:15

by Jeff Garzik

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Kai Germaschewski wrote:
> On Fri, 14 Jun 2002, Linus Torvalds wrote:
>
>
>>I suspect that forcing resource assignment into "pci_enable_device()"
>>should fix that too.
>>
>>Although there should probably be some way for the driver to tell which
>>resources it cares about (some drivers care about the PCI ROM's, for
>>example, others don't. Some drivers don't care about the IO region, and
>>others don't care about the MEM region). So the _right_ answer might be to
>>pass in a bitmap to "pci_enable_device()", which tells the enable code
>>which parts the driver really cares about..
>
>
> That reminds me of some idea I had been thinking about for some time:
>
> What about adding some pci_request_irq() and pci_request_{,mem_}_region,
> which would allow for some cleanup of ever-recurring code sequences in
> drivers, and which at the same time would allow for the above?
> pci_request_mem_region() might even include the ioremap() as well ;)


We already have pci_request_regions() and currently PCI drivers should
use that.

Auto-ioremap would be bad, though... you would wind up wasting address
space for any case where MMIO areas are not 100% utilized (like network
cards that require use of PIO due to hardware bugs, but still export an
MMIO region for their NIC registers)

Jeff



2002-06-14 19:38:15

by Jeff Garzik

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Linus Torvalds wrote:
> Although there should probably be some way for the driver to tell which
> resources it cares about (some drivers care about the PCI ROM's, for
> example, others don't. Some drivers don't care about the IO region, and
> others don't care about the MEM region). So the _right_ answer might be to
> pass in a bitmap to "pci_enable_device()", which tells the enable code
> which parts the driver really cares about..



Such a mask has been desired before :)

That would indeed be nice. Still want to keep busmaster enabling
separate, though...

Jeff



2002-06-14 19:40:56

by Jeff Garzik

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Linus Torvalds wrote:
>
> On Fri, 14 Jun 2002, Kai Germaschewski wrote:
>
>>What about adding some pci_request_irq() and pci_request_{,mem_}_region,
>>which would allow for some cleanup of ever-recurring code sequences in
>>drivers, and which at the same time would allow for the above?
>>pci_request_mem_region() might even include the ioremap() as well ;)
>
>
> That might be the right solution - leave "pci_enable_dev()" as-is, and
> just consider that the legacy way of "enable stuff that got allocated
> automatically".
>
> And make new drivers start using "pci_request_irq()" and friends.
>
> (The current "pci_enable_dev()" is broken in many respects: sometimes you
> do NOT want to enable the IRQ until you have set up the device, but in
> order to set up the device you may need to know _which_ irq it will have,
> and you need to enable access to memory and IO regions and map the
> device).


Can someone clarify for me the need of pci_request_irq??

pci_enable_device() assigns the IRQ in routing, but it is not enabled
until you call request_irq. I don't see any simplification that can be
done in the PCI API.

The only thing I've wanted is a cross-platform way to detect if
pdev->irq returned by pci_enable_device is valid.

Jeff



2002-06-14 20:07:36

by Peter Osterlund

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Linus Torvalds <[email protected]> writes:

> > PCI: Scanning for ghost devices on bus 1
> > Unknown bridge resource 0: assuming transparent
> > Unknown bridge resource 1: assuming transparent
> > Unknown bridge resource 2: assuming transparent
>
> This is the problem.
>
> The PCI code thinks that the parent of the network device doesn't have
> resources allocated, so it will allocate the resources from the parent of
> the parent.
>
> Which is wrong, since it means that it will try to allocate the PCI
> resources from outside the window that the cardbus controller is
> exporting. Resulting in the fffff stuff.
>
> HOWEVER, I don't see why that happens. yenta_allocate_resources() should
> have made absolutely certain that we have all the necessary bridge
> resources clearly allocated. Can you add debug code to the end of
> "yenta_allocate_res()" that prints out the resource that got allocated?

I added a bunch of printk statements, see patch at the end for
details. Here is the output:


Linux Kernel Card Services 3.1.22
options: [pci] [cardbus] [pm]
IRQ for 00:0a.0:0 -> PIRQ 60, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.0 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=10 -> assigning IRQ 10 -> edge ... OK
PCI: Assigned IRQ 10 for device 00:0a.0
yenta_allocate_res: nr=0 type=0x1200
yenta_allocate_res: root->name=PCI mem
yenta_allocate_res: size=0x400000 min=0x10000000 max=0xffffffff align=0x400000, ret=0
yenta_allocate_res: res=c11e6de4 name=PCI CardBus #01 start=0x10400000 end=0x107fffff flags=0x1200
yenta_allocate_res: parent=c0251e7c sibling=c11e6920 child=00000000
yenta_allocate_res: parent=PCI mem sibling=S3 Inc. ViRGE/MX child=
yenta_allocate_res: nr=1 type=0x200
yenta_allocate_res: root->name=PCI mem
yenta_allocate_res: size=0x400000 min=0x10000000 max=0xffffffff align=0x400000, ret=0
yenta_allocate_res: res=c11e6e00 name=PCI CardBus #01 start=0x10800000 end=0x10bfffff flags=0x200
yenta_allocate_res: parent=c0251e7c sibling=c11e6920 child=00000000
yenta_allocate_res: parent=PCI mem sibling=S3 Inc. ViRGE/MX child=
yenta_allocate_res: nr=2 type=0x100
yenta_allocate_res: root->name=PCI IO
yenta_allocate_res: size=0x100 min=0x4000 max=0xffff align=0x400, ret=0
yenta_allocate_res: res=c11e6e1c name=PCI CardBus #01 start=0x4000 end=0x40ff flags=0x100
yenta_allocate_res: parent=c0251e60 sibling=c11e6190 child=00000000
yenta_allocate_res: parent=PCI IO sibling=Intel Corp. 82371AB PIIX4 USB child=
yenta_allocate_res: nr=3 type=0x100
yenta_allocate_res: root->name=PCI IO
yenta_allocate_res: size=0x100 min=0x4000 max=0xffff align=0x400, ret=0
yenta_allocate_res: res=c11e6e38 name=PCI CardBus #01 start=0x4400 end=0x44ff flags=0x100
yenta_allocate_res: parent=c0251e60 sibling=c11e6190 child=00000000
yenta_allocate_res: parent=PCI IO sibling=Intel Corp. 82371AB PIIX4 USB child=
IRQ for 00:0a.1:1 -> PIRQ 61, mask 0400, excl 0000<4>PCI: IRQ 0 for device 00:0a.1 doesn't match PIRQ mask - try pci=usepirqmask
-> newirq=10 -> assigning IRQ 10 ... OK
PCI: Assigned IRQ 10 for device 00:0a.1
yenta_allocate_res: nr=0 type=0x1200
yenta_allocate_res: root->name=PCI mem
yenta_allocate_res: size=0x400000 min=0x10000000 max=0xffffffff align=0x400000, ret=0
yenta_allocate_res: res=c11df1e4 name=PCI CardBus #05 start=0x10c00000 end=0x10ffffff flags=0x1200
yenta_allocate_res: parent=c0251e7c sibling=c11e6920 child=00000000
yenta_allocate_res: parent=PCI mem sibling=S3 Inc. ViRGE/MX child=
yenta_allocate_res: nr=1 type=0x200
yenta_allocate_res: root->name=PCI mem
yenta_allocate_res: size=0x400000 min=0x10000000 max=0xffffffff align=0x400000, ret=0
yenta_allocate_res: res=c11df200 name=PCI CardBus #05 start=0x11000000 end=0x113fffff flags=0x200
yenta_allocate_res: parent=c0251e7c sibling=c11e6920 child=00000000
yenta_allocate_res: parent=PCI mem sibling=S3 Inc. ViRGE/MX child=
yenta_allocate_res: nr=2 type=0x100
yenta_allocate_res: root->name=PCI IO
yenta_allocate_res: size=0x100 min=0x4000 max=0xffff align=0x400, ret=0
yenta_allocate_res: res=c11df21c name=PCI CardBus #05 start=0x4800 end=0x48ff flags=0x100
yenta_allocate_res: parent=c0251e60 sibling=c11e6190 child=00000000
yenta_allocate_res: parent=PCI IO sibling=Intel Corp. 82371AB PIIX4 USB child=
yenta_allocate_res: nr=3 type=0x100
yenta_allocate_res: root->name=PCI IO
yenta_allocate_res: size=0x100 min=0x4000 max=0xffff align=0x400, ret=0
yenta_allocate_res: res=c11df238 name=PCI CardBus #05 start=0x4c00 end=0x4cff flags=0x100
yenta_allocate_res: parent=c0251e60 sibling=c11e6190 child=00000000
yenta_allocate_res: parent=PCI IO sibling=Intel Corp. 82371AB PIIX4 USB child=
Intel PCIC probe: not found.
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 4096 bind 4096)
ip_conntrack version 2.0 (512 buckets, 4096 max) - 292 bytes per conntrack
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
Yenta IRQ list 0a98, PCI irq10
Socket status: 30000068
Yenta IRQ list 0a98, PCI irq10
Socket status: 30000006
cs: cb_alloc(bus 1): vendor 0x13d1, device 0xab02
Scanning bus 01
Found 01:00 [13d1/ab02] 000200 00
PCI: Calling quirk c01d57b0 for 01:00.0
Fixups for bus 01
PCI: Scanning for ghost devices on bus 1
pci_read_bridge_bases 0: res=c11e6de4 name=PCI CardBus #01 base=0x0 limit=0x0
Unknown bridge resource 0: assuming transparent
pci_read_bridge_bases 1: res=c11e6e00 name=PCI CardBus #01 base=0xf0000000 limit=0x10700000
Unknown bridge resource 1: assuming transparent
pci_read_bridge_bases 2: res=c11e6e1c name=PCI CardBus #01 base=0x0 limit=0x10800000
Unknown bridge resource 2: assuming transparent
Bus scan for 01 returning with max=01
got res[1800:18ff] for resource 0 of PCI device 13d1:ab02 (Abocom Systems Inc)
got res[10002000:100023ff] for resource 1 of PCI device 13d1:ab02 (Abocom Systems Inc)
got res[10020000:1003ffff] for resource 6 of PCI device 13d1:ab02 (Abocom Systems Inc)
PCI: Enabling device 01:00.0 (0000 -> 0003)
IRQ for 01:00.0:0 -> not found in routing table
VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 200k freed
INIT: version 2.78 booting



--- linux/drivers/pcmcia/yenta.c.old Fri Jun 14 22:02:08 2002
+++ linux/drivers/pcmcia/yenta.c Fri Jun 14 21:39:38 2002
@@ -709,6 +709,9 @@
u32 align, size, min, max;
unsigned offset;
unsigned mask;
+ int ret;
+
+ printk("yenta_allocate_res: nr=%d type=0x%x\n", nr, type);

/* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
mask = ~0xfff;
@@ -727,6 +730,8 @@
if (!root)
return;

+ printk("yenta_allocate_res: root->name=%s\n", root->name);
+
start = config_readl(socket, offset) & mask;
end = config_readl(socket, offset+4) | ~mask;
if (start && end > start) {
@@ -745,9 +750,21 @@
max = 0xffff;
}

- if (allocate_resource(root, res, size, min, max, align, NULL, NULL) < 0)
+ ret = allocate_resource(root, res, size, min, max, align, NULL, NULL);
+ printk("yenta_allocate_res: size=0x%x min=0x%x max=0x%x align=0x%x, ret=%d\n",
+ size, min, max, align, ret);
+ if (ret < 0)
return;

+ printk("yenta_allocate_res: res=%p name=%s start=0x%lx end=0x%lx flags=0x%lx\n",
+ res, res->name, res->start, res->end, res->flags);
+ printk("yenta_allocate_res: parent=%p sibling=%p child=%p\n",
+ res->parent, res->sibling, res->child);
+ printk("yenta_allocate_res: parent=%s sibling=%s child=%s\n",
+ res->parent ? res->parent->name : "",
+ res->sibling ? res->sibling->name : "",
+ res->child ? res->child->name : "");
+
config_writel(socket, offset, res->start);
config_writel(socket, offset+4, res->end);
}
--- linux/drivers/pci/probe.c.old Fri Jun 14 22:01:21 2002
+++ linux/drivers/pci/probe.c Fri Jun 14 21:33:32 2002
@@ -7,7 +7,7 @@
#include <linux/slab.h>
#include <linux/module.h>

-#undef DEBUG
+#define DEBUG

#ifdef DEBUG
#define DBG(x...) printk(x)
@@ -145,6 +145,8 @@
limit |= (io_limit_hi << 16);
}

+ printk("pci_read_bridge_bases 0: res=%p name=%s base=0x%lx limit=0x%lx\n",
+ res, res ? res->name : "", base, limit);
if (base && base <= limit) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
res->start = base;
@@ -163,6 +165,8 @@
pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+ printk("pci_read_bridge_bases 1: res=%p name=%s base=0x%lx limit=0x%lx\n",
+ res, res ? res->name : "", base, limit);
if (base && base <= limit) {
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
res->start = base;
@@ -193,6 +197,8 @@
}
#endif
}
+ printk("pci_read_bridge_bases 2: res=%p name=%s base=0x%lx limit=0x%lx\n",
+ res, res ? res->name : "", base, limit);
if (base && base <= limit) {
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
res->start = base;

--
Peter Osterlund - [email protected]
http://w1.894.telia.com/~u89404340

2002-06-14 23:26:05

by Kai Germaschewski

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

On Fri, 14 Jun 2002, Jeff Garzik wrote:

> We already have pci_request_regions() and currently PCI drivers should
> use that.

I have to admit I wasn't aware of that. It doesn't really help with the
problem which started this thread, though.

> Auto-ioremap would be bad, though... you would wind up wasting address
> space for any case where MMIO areas are not 100% utilized (like network
> cards that require use of PIO due to hardware bugs, but still export an
> MMIO region for their NIC registers)

auto-ioremap would be bad for pci_request_regions(), which just blindly
allocates all regions. Let's show an example of what I was thinking about,
though.

This is eepro100.c::eepro100_init_one() after the conversion
- IMO it looks a lot simpler than the old code.

--------------------------------------------------------------
#ifdef USE_IO
ioaddr = pci_request_io(pdev, 1);
if (!ioaddr)
goto err_out_none;

if (speedo_debug > 2)
printk("Found Intel i82557 PCI Speedo at I/O %#lx.\n", ioaddr);
#else
ioaddr = (unsigned long) pci_request_mmio(pdev, 0);
if (!ioaddr)
goto err_out_none;

if (speedo_debug > 2)
printk("Found Intel i82557 PCI Speedo, MMIO at %#lx.\n",
pci_resource_start(pdev, 0));
#endif
if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)
cards_found++;
else
goto err_out_release;

return 0;

err_out_release:
#ifdef USE_IO
pci_release_io(pdev, 1);
#else
pci_release_mmio(pdev, 0, (void *)ioaddr);
#endif
err_out_none:
return -ENODEV;
--------------------------------------------------------------

We only request the regions we're going to use, so the others may even
stay unassigned and disabled.

So my idea looks something like this:

unsigned long
pci_request_io(struct pci_dev *pdev, int nr);

void *
pci_request_mmio(struct pci_dev *pdev, int nr);

void
pci_release_io(struct pci_dev *pdev, int nr);

void
pci_release_mmio(struct pci_dev *pdev, int nr, void *addr);

int
pci_request_irq(struct pci_dev *pdev,
void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *name, void *dev);

void
pci_release_irq(struct pci_dev *pdev, void *dev);

These functions return directly what we need: an address for
in/out[bwl], a cookie for read/write[bwl] - well, and the irq
which however is only for informational purposes.

It probably makes sense to split the pci_request_irq() into
pci_assign_irq() and pci_request_irq(), since we want to delay the
pci_request_irq() until we really need it.

The advantages are:
o saves the ioremap etc.
o tells the PCI layer explicitly which resources we use, so
it doesn't have to take the all or nothing pci_enable_device()/
pci_request_resources() approach
o adds appropriate printk(KERN_INFO) when request_region etc fails,
saving thousands of places where we need do the printk() by hand,
and fixing the other thousands of places where we don't printk() so the
user has no idea why the driver wouldn't load.

I deliberately deviated a bit from the normal syntax
(region -> io, mem_region -> mmio, free_irq -> release_irq), for one
reason since I find it more logical this way, but also because the API is
somewhat different, so it shouldn't just appear to be the same - the
difference being e.g. that the old API needed the explicit
pci_enable_device(), whereas that should not be used in the new one.

A very early patch is appended, totally untested, though - I chose
eepro100 since I have that in my laptop, but I don't have my laptop here.

Some parts of the implementation are not as clean as they could be since I
didn't want to muck with the internals of the PCI layer too much - some
cleanup there wouldn't hurt, though.

--Kai

===== arch/i386/pci/i386.c 1.10 vs edited =====
--- 1.10/arch/i386/pci/i386.c Wed May 8 18:10:45 2002
+++ edited/arch/i386/pci/i386.c Fri Jun 14 17:23:28 2002
@@ -243,16 +243,15 @@
pcibios_assign_resources();
}

-int pcibios_enable_resources(struct pci_dev *dev)
+int pcibios_enable_resource(struct pci_dev *dev, int nr)
{
+ struct resource *r = &dev->resource(nr);
u16 cmd, old_cmd;
- int idx;
- struct resource *r;

pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
- for(idx=0; idx<6; idx++) {
- r = &dev->resource[idx];
+
+ if (nr != PCI_ROM_RESOURCE) {
if (!r->start && r->end) {
printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
return -EINVAL;
@@ -261,13 +260,21 @@
cmd |= PCI_COMMAND_IO;
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
+ } else {
+ if (r->start)
+ cmd |= PCI_COMMAND_MEMORY;
}
- if (dev->resource[PCI_ROM_RESOURCE].start)
- cmd |= PCI_COMMAND_MEMORY;
if (cmd != old_cmd) {
printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
+}
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+ for(idx = 0; idx <= PCI_ROM_RESOURCE; idx++)
+ pcibios_enable_resource(dev, idx);
+
return 0;
}

===== drivers/net/eepro100.c 1.32 vs edited =====
--- 1.32/drivers/net/eepro100.c Thu May 30 01:18:19 2002
+++ edited/drivers/net/eepro100.c Fri Jun 14 18:05:35 2002
@@ -559,7 +559,6 @@
const struct pci_device_id *ent)
{
unsigned long ioaddr;
- int irq;
int acpi_idle_state = 0, pm;
static int cards_found /* = 0 */;

@@ -575,57 +574,37 @@
acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
}

- if (pci_enable_device(pdev))
- goto err_out_free_mmio_region;
-
pci_set_master(pdev);

- if (!request_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1), "eepro100")) {
- printk (KERN_ERR "eepro100: cannot reserve I/O ports\n");
+#ifdef USE_IO
+ ioaddr = pci_request_io(pdev, 1);
+ if (!ioaddr)
goto err_out_none;
- }
- if (!request_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0), "eepro100")) {
- printk (KERN_ERR "eepro100: cannot reserve MMIO region\n");
- goto err_out_free_pio_region;
- }

- irq = pdev->irq;
-#ifdef USE_IO
- ioaddr = pci_resource_start(pdev, 1);
if (speedo_debug > 2)
- printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
- ioaddr, irq);
+ printk("Found Intel i82557 PCI Speedo at I/O %#lx.\n", ioaddr);
#else
- ioaddr = (unsigned long)ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (!ioaddr) {
- printk (KERN_ERR "eepro100: cannot remap MMIO region %lx @ %lx\n",
- pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));
- goto err_out_free_mmio_region;
- }
+ ioaddr = (unsigned long) pci_request_mmio(pdev, 0);
+ if (!ioaddr)
+ goto err_out_none;
+
if (speedo_debug > 2)
- printk("Found Intel i82557 PCI Speedo, MMIO at %#lx, IRQ %d.\n",
- pci_resource_start(pdev, 0), irq);
+ printk("Found Intel i82557 PCI Speedo, MMIO at %#lx.\n",
+ pci_resource_start(pdev, 0));
#endif
-
-
if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)
cards_found++;
else
- goto err_out_iounmap;
+ goto err_out_release;

return 0;

-err_out_iounmap: ;
-#ifndef USE_IO
- iounmap ((void *)ioaddr);
+err_out_release:
+#ifdef USE_IO
+ pci_release_io(pdev, 1);
+#else
+ pci_release_mmio(pdev, 0, (void *)ioaddr);
#endif
-err_out_free_mmio_region:
- release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-err_out_free_pio_region:
- release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
err_out_none:
return -ENODEV;
}
@@ -803,7 +782,6 @@
pci_set_drvdata (pdev, dev);

dev->base_addr = ioaddr;
- dev->irq = pdev->irq;

sp = dev->priv;
sp->pdev = pdev;
@@ -924,7 +902,7 @@
int retval;

if (speedo_debug > 1)
- printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
+ printk(KERN_DEBUG "%s: speedo_open()\n", dev->name);

MOD_INC_USE_COUNT;

@@ -939,11 +917,12 @@
sp->in_interrupt = 0;

/* .. we can safely take handler calls during init. */
- retval = request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev);
+ retval = pci_request_irq(sp->pdev, &speedo_interrupt, SA_SHIRQ, dev->name, dev);
if (retval) {
MOD_DEC_USE_COUNT;
return retval;
}
+ dev->irq = retval;

dev->if_port = sp->default_port;

@@ -1834,7 +1813,7 @@
/* Shutting down the chip nicely fails to disable flow control. So.. */
outl(PortPartialReset, ioaddr + SCBPort);

- free_irq(dev->irq, dev);
+ pci_release_irq(sp->pdev, dev);

/* Print a few items for debugging. */
if (speedo_debug > 3)
@@ -2253,11 +2232,12 @@

unregister_netdev(dev);

- release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));

-#ifndef USE_IO
- iounmap((char *)dev->base_addr);
+#ifdef USE_IO
+ pci_release_io(pdev, 1);
+#else
+ pci_release_mmio(pdev, 0, (void *) dev->base_addr);
#endif

pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
@@ -2348,7 +2328,6 @@

/*
* Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
===== drivers/pci/pci.c 1.44 vs edited =====
--- 1.44/drivers/pci/pci.c Wed May 8 18:10:45 2002
+++ edited/drivers/pci/pci.c Fri Jun 14 17:54:07 2002
@@ -555,6 +555,112 @@
return 0;
}

+#define IORESOURCE_IO_MEM (IORESOURCE_IO | IORESOURCE_MEM)
+
+unsigned long
+__pci_request_region(struct pci_dev *pdev, int nr, unsigned long flags,
+ struct resource *root)
+{
+ struct pci_driver *drv = pci_dev_driver(pdev);
+ char *drv_name = drv ? drv->name : "unknown";
+ struct resource *res;
+
+ /* Make sure we have the right type (IO/MMIO) */
+ if ((pci_resource_flags(pdev, nr) ^ flags) & IORESOURCE_IO_MEM)
+ goto err;
+
+ /* If no resource has been assigned yet, try to do it now */
+ if (!pci_resource_start(pdev, nr) && pci_resource_end(pdev, nr))
+ if (pci_assign_resource(pdev, nr) < 0)
+ goto err;
+
+ /* Enable the resource (unless already done) */
+ pcibios_enable_resource(pdev, nr);
+
+ res = __request_region(root, pci_resource_start(pdev, nr),
+ pci_resource_len(pdev, nr), drv_name);
+ if (!res)
+ goto err;
+
+ return res->start;
+
+ err:
+ printk(KERN_INFO
+ "%s: failed to get %s(%d) for %s, %#lx-%#lx flags %#lx.\n",
+ pdev->slot_name, (flags == IORESOURCE_IO ? "IO" : "MMIO"),
+ nr, drv_name,
+ pci_resource_start(pdev, nr),
+ pci_resource_flags(pdev, nr),
+ pci_resource_end(pdev, nr));
+
+ return 0;
+}
+
+unsigned long
+pci_request_io(struct pci_dev *pdev, int nr)
+{
+ return __pci_request_region(pdev, nr, IORESOURCE_IO, &ioport_resource);
+}
+
+void *
+pci_request_mmio(struct pci_dev *pdev, int nr)
+{
+ unsigned long base;
+ void *addr;
+
+ base = __pci_request_region(pdev, nr, IORESOURCE_MEM, &iomem_resource);
+ if (!base)
+ return 0;
+
+ addr = ioremap(base, pci_resource_len(pdev, nr));
+ if (!addr)
+ release_region(base, pci_resource_len(pdev, nr));
+
+ return addr;
+}
+
+void
+pci_release_io(struct pci_dev *pdev, int nr)
+{
+ __release_region(&ioport_resource,
+ pci_resource_start(pdev, nr),
+ pci_resource_len(pdev, nr));
+}
+
+void
+pci_release_mmio(struct pci_dev *pdev, int nr, void *addr)
+{
+ iounmap(addr);
+ __release_region(&iomem_resource,
+ pci_resource_start(pdev, nr),
+ pci_resource_len(pdev, nr));
+}
+
+int
+pci_request_irq(struct pci_dev *pdev,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *name, void *dev)
+{
+ int irq, retval;
+
+ pcibios_enable_irq(pdev);
+ irq = pdev->irq;
+
+ retval = request_irq(irq, handler, flags, name, dev);
+ if (retval < 0)
+ return retval;
+
+ return irq;
+}
+
+void
+pci_release_irq(struct pci_dev *pdev, void *dev)
+{
+ free_irq(pdev->irq, dev);
+}
+
+
+
static int __devinit pci_init(void)
{
struct pci_dev *dev;
@@ -601,6 +707,13 @@
EXPORT_SYMBOL(pci_save_state);
EXPORT_SYMBOL(pci_restore_state);
EXPORT_SYMBOL(pci_enable_wake);
+
+EXPORT_SYMBOL(pci_request_io);
+EXPORT_SYMBOL(pci_request_mmio);
+EXPORT_SYMBOL(pci_release_io);
+EXPORT_SYMBOL(pci_release_mmio);
+EXPORT_SYMBOL(pci_request_irq);
+EXPORT_SYMBOL(pci_release_irq);

/* Obsolete functions */

===== include/linux/pci.h 1.32 vs edited =====
--- 1.32/include/linux/pci.h Tue May 28 20:02:33 2002
+++ edited/include/linux/pci.h Fri Jun 14 17:56:28 2002
@@ -580,6 +580,16 @@
int pci_set_power_state(struct pci_dev *dev, int state);
int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);

+/* New resource management */
+unsigned long pci_request_io(struct pci_dev *pdev, int nr);
+void *pci_request_mmio(struct pci_dev *pdev, int nr);
+void pci_release_io(struct pci_dev *pdev, int nr);
+void pci_release_mmio(struct pci_dev *pdev, int nr, void *addr);
+int pci_request_irq(struct pci_dev *pdev,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *name, void *dev);
+void pci_release_irq(struct pci_dev *pdev, void *dev);
+
/* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */

int pci_claim_resource(struct pci_dev *, int);

2002-06-14 23:57:25

by Jeff Garzik

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Kai Germaschewski wrote:
> On Fri, 14 Jun 2002, Jeff Garzik wrote:
>
>
>>We already have pci_request_regions() and currently PCI drivers should
>>use that.
>
>
> I have to admit I wasn't aware of that. It doesn't really help with the
> problem which started this thread, though.
>
>
>>Auto-ioremap would be bad, though... you would wind up wasting address
>>space for any case where MMIO areas are not 100% utilized (like network
>>cards that require use of PIO due to hardware bugs, but still export an
>>MMIO region for their NIC registers)
>
>
> auto-ioremap would be bad for pci_request_regions(), which just blindly
> allocates all regions. Let's show an example of what I was thinking about,
> though.
>
> This is eepro100.c::eepro100_init_one() after the conversion
> - IMO it looks a lot simpler than the old code.
>
> --------------------------------------------------------------
> #ifdef USE_IO
> ioaddr = pci_request_io(pdev, 1);
> if (!ioaddr)
> goto err_out_none;
>
> if (speedo_debug > 2)
> printk("Found Intel i82557 PCI Speedo at I/O %#lx.\n", ioaddr);
> #else
> ioaddr = (unsigned long) pci_request_mmio(pdev, 0);
> if (!ioaddr)
> goto err_out_none;
>
> if (speedo_debug > 2)
> printk("Found Intel i82557 PCI Speedo, MMIO at %#lx.\n",
> pci_resource_start(pdev, 0));
> #endif
> if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)
> cards_found++;
> else
> goto err_out_release;
>
> return 0;
>
> err_out_release:
> #ifdef USE_IO
> pci_release_io(pdev, 1);
> #else
> pci_release_mmio(pdev, 0, (void *)ioaddr);
> #endif
> err_out_none:
> return -ENODEV;
> --------------------------------------------------------------
>
> We only request the regions we're going to use, so the others may even
> stay unassigned and disabled.
>
> So my idea looks something like this:
>
> unsigned long
> pci_request_io(struct pci_dev *pdev, int nr);
>
> void *
> pci_request_mmio(struct pci_dev *pdev, int nr);
>
> void
> pci_release_io(struct pci_dev *pdev, int nr);
>
> void
> pci_release_mmio(struct pci_dev *pdev, int nr, void *addr);
>
> int
> pci_request_irq(struct pci_dev *pdev,
> void (*handler)(int, void *, struct pt_regs *),
> unsigned long flags, const char *name, void *dev);
>
> void
> pci_release_irq(struct pci_dev *pdev, void *dev);
>
> These functions return directly what we need: an address for
> in/out[bwl], a cookie for read/write[bwl] - well, and the irq
> which however is only for informational purposes.
>
> It probably makes sense to split the pci_request_irq() into
> pci_assign_irq() and pci_request_irq(), since we want to delay the
> pci_request_irq() until we really need it.
>
> The advantages are:
> o saves the ioremap etc.
> o tells the PCI layer explicitly which resources we use, so
> it doesn't have to take the all or nothing pci_enable_device()/
> pci_request_resources() approach
> o adds appropriate printk(KERN_INFO) when request_region etc fails,
> saving thousands of places where we need do the printk() by hand,
> and fixing the other thousands of places where we don't printk() so the
> user has no idea why the driver wouldn't load.


Thanks for the patch, I can see where you're headed more clearly.

Comments:
* You absolutely need a separate _assign_irq(). request_irq() and
free_irq() are used today as the points which enable and disable an irq
for a device.

* You want to keep pci_enable_device(), such that, in driver code it
does not need to be moved. This is an important hook for hotplug PCI
and cardbus and such things, which need a point where they may enable
the device as a whole. One important function pci_enable_device() does
now, for example, is bring the PCI device to D0 full-power-on state.

* Remember that you must handle two cases here: 1) BIOS-pre-assigned
region values, and 2) on-the-fly assigned values. Drivers needs to work
transparently such that, on a desktop PCI system, pci_request_regions()
is _really_ all the reservation they need. And the same driver, using
the same code, should handle cardbus and other systems that are having
resources assigned to them dynamically. I don't really care that much
how's it's implemented behind-the-scenes, as long as the end-result
driver code handles both these cases without a forest of "if's" and
"ifdef's"

Jeff


2002-06-15 02:44:58

by Paul Mackerras

[permalink] [raw]
Subject:

Linus Torvalds writes:

> > Unknown bridge resource 0: assuming transparent
> > Unknown bridge resource 1: assuming transparent
> > Unknown bridge resource 2: assuming transparent
>
> This is the problem.

BTW, this "assuming transparent" bit continually causes us problems on
RS/6000 machines that have a PCI-PCI bus. If none of the cards behind
the bridge have any I/O resources, the firmware will set up the bridge
with the I/O window closed, by setting the base register to one more
than the limit register, which is correct according to the Intel
document describing PCI-PCI bridges.

Then the bridge probing code comes along and says "assuming
transparent", which is wrong. The aperture is closed and the bridge
should have no I/O space resource.

I would really like the relevant code in pci_read_bridge_bases to look
like this:

if ((base || limit) && base <= limit) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
res->start = base;
res->end = limit + 0xfff;
res->name = child->name;
} else if (base == limit + 0x1000) {
/* Firmware/BIOS has deactivated this window */
res->start = res->end = 0;
res->flags = 0;
printk(KERN_ERR "Bridge %s resource %d was deactivated by"
" firmware\n", dev->slot_name, 0);
} else {
/*
* Ugh. We don't know enough about this bridge. Just assume
* that it's entirely transparent.
*/
printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 0);
child->resource[0] = child->parent->resource[0];
}

The (base || limit) part instead of just testing base is needed
because we sometimes get PCI-PCI bridges that are legitimately set up
with the bridge having an aperture starting at I/O address 0.

IIRC someone told me that we had to do the "assuming transparent" bit
because of buggy PCI-PCI bridges used on some PCs. Can anyone
enlighten me on the details of that?

Paul.

2002-06-15 10:57:13

by Ingo Oeser

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Hi,

On Fri, Jun 14, 2002 at 06:25:15PM -0500, Kai Germaschewski wrote:
> We only request the regions we're going to use, so the others may even
> stay unassigned and disabled.
[...]
> These functions return directly what we need: an address for
> in/out[bwl], a cookie for read/write[bwl] - well, and the irq
> which however is only for informational purposes.

I like it!

This also allows us to remove the anal checking & cleanup
duplicated in each and every driver to be removed.

So your solution will save lots of code at least in all PCI-only
drivers.

I even wrote my own routine that does exactly that, to save the code.

Some people can not use pci_enable_resources(), because sometimes
one of the resources is a PCI-Interface chip, that has a
different driver, which enabled one resource already itself.

So splitting this out alone is already a win.

Regards

Ingo Oeser
--
Science is what we can tell a computer. Art is everything else. --- D.E.Knuth

2002-06-15 18:48:21

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On Fri, 14 Jun 2002, Jeff Garzik wrote:
>
> Can someone clarify for me the need of pci_request_irq??
>
> pci_enable_device() assigns the IRQ in routing, but it is not enabled
> until you call request_irq. I don't see any simplification that can be
> done in the PCI API.

The irq _is_ enabled ona hardware level.

Which can be a total disaster if there are shared PCI irq's, and the
interrupt is "screaming" (ie an active level-sensitive thing).

We've had this on cardbus, for example, where we need to do an
"pci_emable_device()" in order to get access to the PCI IO mappings, which
are needed to shut the device up.

Right now the solution to a screaming device can be something as nasty as

cli();
pci_enable_device();
disable_irq(dev->irq);
sti();

/* IRQ handling needs this ioremapped */
membase = ioremap(dev->resource[]);
request_irq(dev->irq);

/* Now we can enable the irq, because we have a valid handler */
enable_irq(dev->irq);

which is horribly stupid. We really want to do

pci_enable_mem(dev);
membase = ioremap(dev->resource[]);

pci_request_irq(dev, irq_handler);

where "pci_request_irq()" enables the interrupt and adds an interrupt
handler atomically.

> The only thing I've wanted is a cross-platform way to detect if
> pdev->irq returned by pci_enable_device is valid.

It's required to be valid, because if it isn't, then the platform is
broken. There are no cross-platform issues: complain to the platform
vendor and/or the linux code for that architecture.

Linus

2002-06-15 19:05:24

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On Sat, 15 Jun 2002, Linus Torvalds wrote:
>
> Right now the solution to a screaming device can be something as nasty as
>
> cli();
> pci_enable_device();
> disable_irq(dev->irq);
> sti();
>
> /* IRQ handling needs this ioremapped */
> membase = ioremap(dev->resource[]);
> request_irq(dev->irq);
>
> /* Now we can enable the irq, because we have a valid handler */
> enable_irq(dev->irq);

Side note: the other approach to screaming devices is to pray that they
don't happen.

Which is actually the approach Linux takes, and which tends to work
reasonably well. All PCI devices reset without pending interrupts, and
probably windows doesn't react well to the bios doing something stupid.

But it's actually happened for pcmcia depending on init order (and right
now linux pcmcia is just fairly careful about the ordering).

Linus

2002-06-15 19:39:30

by Kai Germaschewski

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

On Sat, 15 Jun 2002, Linus Torvalds wrote:

> On Sat, 15 Jun 2002, Linus Torvalds wrote:
> >
> > Right now the solution to a screaming device can be something as nasty as
> >
> > cli();
> > pci_enable_device();
> > disable_irq(dev->irq);
> > sti();
> >
> > /* IRQ handling needs this ioremapped */
> > membase = ioremap(dev->resource[]);
> > request_irq(dev->irq);
> >
> > /* Now we can enable the irq, because we have a valid handler */
> > enable_irq(dev->irq);
>
> Side note: the other approach to screaming devices is to pray that they
> don't happen.

I think there are situations where we don't have a choice but praying
anyway. Since there's no PCI_COMMAND_IRQ, the only way to suppress IRQs
AFAICS is to not route them (well, or ignore them, which is what we do if
there's no handler installed), but that's just not possible when the IRQ
line is shared with some other active device.

I still think it's probably a good idea to replace pci_enable_device()
by a more fine-grained API, which allows a driver author to specify
which exact resources he needs.

In the normal case, a driver would only use a subset of the following
three functions as needed:

int pci_request_irq(pci_dev, handler, ...);
unsigned long pci_request_io(pci_dev, nr);
unsigned long pci_request_mmio(pci_dev, nr);

(plus appropriate s/request/release/ of course)

Internally, they'd do the right thing, i.e. assign and enable resources as
needed.

At least for the _irq case an associated

int pci_assign_irq(pci_dev);

is useful, since some drivers (e.g. net, serial) only request their irq
when the device is opened (which make sense for performance reasons with
shared irqs), but it'd still be nice to fail the ::probe() when no IRQ can
be assigned.

So a complete API would be

pci_request_{irq,io,mmio}
pci_release_{irq,io,mmio}
pci_enable_{irq,io,mmio}
pci_assign_{irq,io,mmio}

but normally a driver would just use pci_request/release_*() + maybe
pci_assign_irq(), which will take care of the appropriate assign/enable
internally.

--Kai



2002-06-15 20:02:23

by Jeff Garzik

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Kai Germaschewski wrote:
> I still think it's probably a good idea to replace pci_enable_device()
> by a more fine-grained API, which allows a driver author to specify
> which exact resources he needs.

To repeat, pci_enable_device is not _just_ resource assignment.

It also provides:
1) power state management (wakes up the device)
2) an entry point which guarantees the bus layer that the driver is not
interested in the hardware at all before that point. Or IOW,
pci_enable_device is a bus layer hook for whatever "device
wakeup/appearing" needs that bus has. Sure, we are talking about moving
some of that functionality to other functions (pci_request_<foo>), but
that doesn't mean we should ditch the hook altogether.

Remember, we have a matching pair here: pci_enable_device,
pci_disable_device. Update the code that goes on between those two
calls, sure. But leave the calls there.


> So a complete API would be
>
> pci_request_{irq,io,mmio}
> pci_release_{irq,io,mmio}
> pci_enable_{irq,io,mmio}
> pci_assign_{irq,io,mmio}
>
> but normally a driver would just use pci_request/release_*() + maybe
> pci_assign_irq(), which will take care of the appropriate assign/enable
> internally.


That seems like a decent enough API, pending a bit of driver conversion
to see how well it works out in practice. So I'm ok with it (with the
pci_enable_device proviso, above)

Jeff



2002-06-15 20:11:05

by Jeff Garzik

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Linus Torvalds wrote:
> which is horribly stupid. We really want to do
>
> pci_enable_mem(dev);
> membase = ioremap(dev->resource[]);
>
> pci_request_irq(dev, irq_handler);
>
> where "pci_request_irq()" enables the interrupt and adds an interrupt
> handler atomically.

That seems ok to me. Note that we still want
pci_{enable,disable}_device to exist (as mentioned in the mail to
Kai)... I'm fine with moving a lot of pci_enable_device's duties to
pci_{assign,request,release}_{irq,io,mem} as long as we don't kill it
completely.


>>The only thing I've wanted is a cross-platform way to detect if
>>pdev->irq returned by pci_enable_device is valid.
>
>
> It's required to be valid, because if it isn't, then the platform is
> broken. There are no cross-platform issues: complain to the platform
> vendor and/or the linux code for that architecture.

Well, then I should either complain to myself, or to you ;-) Part of
this comes back to PCI irq routing. The actual situation encountered is,

When ia32 PCI irq routing messes up, or some other random reason why an
irq is not available for a PCI device, pdev->irq==0. So I test for that
in my code. Then DaveM bitches at me for my test (pdev->irq < 2) not
being cross-platform.

My suggested solution, if you like Kai's proposal, is to have
pci_assign_irq() or pci_request_irq() return an error if PCI IRQ routing
fails.

Jeff


P.S. Random tangent: the PCI layer could do a lot better job at
spreading devices across the available IRQs. I've seen devices
clustered on a single interrupt by the Linux PCI code, where their pci
irq routing masks indicating other, not-assigned-at-all irqs were available.


2002-06-15 21:58:36

by Linus Torvalds

[permalink] [raw]
Subject: Re: Cardbus



On Sat, 15 Jun 2002, Paul Mackerras wrote:
>
> IIRC someone told me that we had to do the "assuming transparent" bit
> because of buggy PCI-PCI bridges used on some PCs. Can anyone
> enlighten me on the details of that?

It has nothing to do with "buggy" PCI-PCI bridges, and everything to do
with the fact that a lot of bridges seem to extend on the official PCI
bridge interface in various ways. In particular, it seems to be fairly
common to have the _real_ bridging information in the chip-specific range
(PCI config area 0x40+) instead of in the official "2 mem resources, 2 IO
resources" place.

I think even some bog-standard Intel PCI bridge did exactly this. But all
my pdf files are at work right now.

Linus

2002-06-15 22:51:34

by Kai Germaschewski

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

On Sat, 15 Jun 2002, Jeff Garzik wrote:

> That seems ok to me. Note that we still want
> pci_{enable,disable}_device to exist (as mentioned in the mail to
> Kai)... I'm fine with moving a lot of pci_enable_device's duties to
> pci_{assign,request,release}_{irq,io,mem} as long as we don't kill it
> completely.

I'm aware that something like pci_enable_device() still is necessary, but
I moved this part of the functionality into pci_request_*.

pci_enable_device() does the equivalent of
{ pci_assign_irq(); pci_assign_mmio(); pci_assign_io() }
where these again internally do pci_set_power_state() (and could extended
to do whatever else necessary).

The main reason against pci_enable_device() is that it makes a smooth
transition impossible - We cannot change pci_enable_device()'s behavior in
a way that relies on all drivers using pci_request_*() already. And
introducing a new function under a new name seems pointless when it can be
hidden inside the new API as well.

What's not so nice is that it destroys the symmetry between
pci_enable_device() and pci_disable_device().

But I think I have an idea for that one as well: This new API will be used
in conjunction with the new-style pci_register_driver() etc interface,
where the PCI layer knows when we call ::probe() and ::remove(). So it'd
be actually even nicer to do the pci_set_power_state() etc before
::probe() is called, and pci_disable_device after::remove() has finished
(and on ::probe() error path)

How does that sound?

> When ia32 PCI irq routing messes up, or some other random reason why an
> irq is not available for a PCI device, pdev->irq==0. So I test for that
> in my code. Then DaveM bitches at me for my test (pdev->irq < 2) not
> being cross-platform.
>
> My suggested solution, if you like Kai's proposal, is to have
> pci_assign_irq() or pci_request_irq() return an error if PCI IRQ routing
> fails.

Yes, makes sense. Actually currently pci_enable_device() should return
an error when the IRQ routing fails - it does so when using ACPI routing,
but not when doing PIRQ routing, so I think that's a bug to be fixed in
arch/i386/pci/irq.c.

I decided to return an int from pci_*_irq, where < 0 means error. The
number returned otherwise shell only be used for printk("IRQ %d", ret),
anyway - pci_dev->irq stays opaque to the driver.

Proposed patch to follow in a minute.


--Kai


2002-06-15 23:01:46

by Kai Germaschewski

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

On Sat, 15 Jun 2002, Jeff Garzik wrote:

> > So a complete API would be
> >
> > pci_request_{irq,io,mmio}
> > pci_release_{irq,io,mmio}
> > pci_enable_{irq,io,mmio}
> > pci_assign_{irq,io,mmio}
> >
> > but normally a driver would just use pci_request/release_*() + maybe
> > pci_assign_irq(), which will take care of the appropriate assign/enable
> > internally.
>
>
> That seems like a decent enough API, pending a bit of driver conversion
> to see how well it works out in practice. So I'm ok with it (with the
> pci_enable_device proviso, above)

Okay, so here's a patch which actually compiles and works here.

TODO:
o move the pci_set_power_state() before calling pci_driver::probe()
add pci_disable_device() after pci_driver::remove()
o fix other archs.

Currently, each arch has a

pcibios_enable_device()

function, which now needs to be split into

pcibios_assign_irq()
pcibios_enable_irq()

IO/MMIO is all taken care of by the generic code currently. (Possibly we
need to add callbacks into arch-specific code there)

Apart from breaking each arch but i386/x86_64, the patch is ready, at
least from my point of view ;)

--Kai


Pull from http://linux-isdn.bkbits.net/linux-2.5.pci

(Merging changesets omitted for clarity)

-----------------------------------------------------------------------------
[email protected], 2002-06-15 14:04:46-05:00, [email protected]
PCI: Set pci_dev->driver before calling ::probe()

That's just preparation so that we can use pci_dev->driver inside
the probe() routine, e.g. for driver->name.

----------------------------------------------------------------------------
pci-driver.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)

-----------------------------------------------------------------------------
[email protected], 2002-06-15 15:19:22-05:00, [email protected]
PCI: Introduce pci_assign_irq() and pci_enable_irq()

The functions assign and route an IRQ on a PCI device, a bit inline
docu is available in drivers/pci/pci.c

Internally they call back into the arch specific
pcibios_assign/enable_irq(), which means everything but i386/x86_64
gets broken by this change (should be easy to fix, though).

Rename the function pointer pcibios_enable_irq to pcibios_enable_irq_func
to not clash with these functions.

----------------------------------------------------------------------------
arch/i386/pci/acpi.c | 2 -
arch/i386/pci/common.c | 18 +++++++++++++++-
arch/i386/pci/irq.c | 10 +++++----
arch/i386/pci/pci.h | 3 --
arch/x86_64/pci/acpi.c | 2 -
arch/x86_64/pci/common.c | 5 ++++
arch/x86_64/pci/irq.c | 10 +++++----
arch/x86_64/pci/pci.h | 3 --
drivers/pci/pci.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 2 +
10 files changed, 90 insertions(+), 15 deletions(-)

-----------------------------------------------------------------------------
[email protected], 2002-06-15 16:35:23-05:00, [email protected]
PCI: Introduce wrapper to set/clear PCI command bits

It'd be worth it even if we wouldn't make yet more use of it in
the next patch.

----------------------------------------------------------------------------
pci.c | 61 ++++++++++++++++++++++++++++++++-----------------------------
1 files changed, 32 insertions(+), 29 deletions(-)

-----------------------------------------------------------------------------
[email protected], 2002-06-15 16:38:20-05:00, [email protected]
PCI: Introduce pci_assign/enable_io/mmio functions

The main use of those will be internal to
pci_request/release_io/mmio. However, we export them, since
there'll always be hardware which needs special hacks...

----------------------------------------------------------------------------
drivers/pci/pci.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/pci.h | 7 ++
2 files changed, 128 insertions(+), 2 deletions(-)

-----------------------------------------------------------------------------
[email protected], 2002-06-15 17:23:10-05:00, [email protected]
PCI: Add pci_request_* and pci_release_* API

Docu is available inline. When switching a driver to this API,
calling pci_enable_device() is not necessary anymore, the needed
resources will be activated at pci_request_* time.

In particular, that means if your driver only uses MMIO, IO resources
on your card won't be assigned and enabled (it's possible that the
BIOS did that, though).

----------------------------------------------------------------------------
drivers/pci/pci.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 9 ++
2 files changed, 196 insertions(+)

-----------------------------------------------------------------------------
[email protected], 2002-06-15 17:31:38-05:00, [email protected]
PCI: Convert two sample drivers to new interface

eepro100 and ymfpci still work fine on my laptop after the change,
even when zeroing out their BARs during boot.

----------------------------------------------------------------------------
drivers/net/eepro100.c | 83 +++++++++++++++++++++----------------------------
sound/oss/ymfpci.c | 45 ++++++++++----------------
2 files changed, 54 insertions(+), 74 deletions(-)





=============================================================================
unified diffs follow for reference
=============================================================================

-----------------------------------------------------------------------------
[email protected], 2002-06-15 14:04:46-05:00, [email protected]
PCI: Set pci_dev->driver before calling ::probe()

That's just preparation so that we can use pci_dev->driver inside
the probe() routine, e.g. for driver->name.

---------------------------------------------------------------------------

diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
--- a/drivers/pci/pci-driver.c Sat Jun 15 17:59:18 2002
+++ b/drivers/pci/pci-driver.c Sat Jun 15 17:59:18 2002
@@ -48,12 +48,14 @@
const struct pci_device_id *id;

id = pci_match_device(drv->id_table, pci_dev);
- if (id)
- error = drv->probe(pci_dev, id);
- if (error >= 0) {
+ if (id) {
pci_dev->driver = drv;
- error = 0;
+ error = drv->probe(pci_dev, id);
}
+ if (error < 0)
+ pci_dev->driver = NULL;
+ else
+ error = 0;
}
return error;
}

-----------------------------------------------------------------------------
[email protected], 2002-06-15 15:19:22-05:00, [email protected]
PCI: Introduce pci_assign_irq() and pci_enable_irq()

The functions assign and route an IRQ on a PCI device, a bit inline
docu is available in drivers/pci/pci.c

Internally they call back into the arch specific
pcibios_assign/enable_irq(), which means everything but i386/x86_64
gets broken by this change (should be easy to fix, though).

Rename the function pointer pcibios_enable_irq to pcibios_enable_irq_func
to not clash with these functions.

---------------------------------------------------------------------------

diff -Nru a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
--- a/arch/i386/pci/acpi.c Sat Jun 15 17:59:19 2002
+++ b/arch/i386/pci/acpi.c Sat Jun 15 17:59:19 2002
@@ -13,7 +13,7 @@
printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi'\n");
pcibios_scanned++;
- pcibios_enable_irq = acpi_pci_irq_enable;
+ pcibios_enable_irq_func = acpi_pci_irq_enable;
} else
printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");

diff -Nru a/arch/i386/pci/common.c b/arch/i386/pci/common.c
--- a/arch/i386/pci/common.c Sat Jun 15 17:59:19 2002
+++ b/arch/i386/pci/common.c Sat Jun 15 17:59:19 2002
@@ -209,5 +209,21 @@
if ((err = pcibios_enable_resources(dev)) < 0)
return err;

- return pcibios_enable_irq(dev);
+ return pcibios_enable_irq_func(dev);
+}
+
+int pcibios_assign_irq(struct pci_dev *dev)
+{
+ return pcibios_enable_irq_func(dev);
+}
+
+/*
+ * We've done all the work in pcibios_assign_irq already.
+ * We may want to change this later to activate the actual routing at this
+ * point, though.
+ * It's only ever called after a successful pcibios_assign_irq()
+ */
+int pcibios_enable_irq(struct pci_dev *dev)
+{
+ return 0;
}
diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
--- a/arch/i386/pci/irq.c Sat Jun 15 17:59:19 2002
+++ b/arch/i386/pci/irq.c Sat Jun 15 17:59:19 2002
@@ -44,7 +44,7 @@
int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
};

-int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
+int (*pcibios_enable_irq_func)(struct pci_dev *dev);

/*
* Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
@@ -684,11 +684,13 @@
return 1;
}

+static int pirq_enable_irq(struct pci_dev *dev);
+
static int __init pcibios_irq_init(void)
{
DBG("PCI: IRQ init\n");

- if (pcibios_enable_irq)
+ if (pcibios_enable_irq_func)
return 0;

pirq_table = pirq_find_routing_table();
@@ -711,7 +713,7 @@
pirq_table = NULL;
}

- pcibios_enable_irq = pirq_enable_irq;
+ pcibios_enable_irq_func = pirq_enable_irq;

pcibios_fixup_irqs();
return 0;
@@ -794,7 +796,7 @@
pirq_penalty[irq] += 100;
}

-int pirq_enable_irq(struct pci_dev *dev)
+static int pirq_enable_irq(struct pci_dev *dev)
{
u8 pin;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
diff -Nru a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
--- a/arch/i386/pci/pci.h Sat Jun 15 17:59:19 2002
+++ b/arch/i386/pci/pci.h Sat Jun 15 17:59:19 2002
@@ -70,6 +70,5 @@
extern spinlock_t pci_config_lock;

void pcibios_fixup_irqs(void);
-int pirq_enable_irq(struct pci_dev *dev);

-extern int (*pcibios_enable_irq)(struct pci_dev *dev);
+extern int (*pcibios_enable_irq_func)(struct pci_dev *dev);
diff -Nru a/arch/x86_64/pci/acpi.c b/arch/x86_64/pci/acpi.c
--- a/arch/x86_64/pci/acpi.c Sat Jun 15 17:59:19 2002
+++ b/arch/x86_64/pci/acpi.c Sat Jun 15 17:59:19 2002
@@ -13,7 +13,7 @@
printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi'\n");
pcibios_scanned++;
- pcibios_enable_irq = acpi_pci_irq_enable;
+ pcibios_enable_irq_func = acpi_pci_irq_enable;
} else
printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");

diff -Nru a/arch/x86_64/pci/common.c b/arch/x86_64/pci/common.c
--- a/arch/x86_64/pci/common.c Sat Jun 15 17:59:19 2002
+++ b/arch/x86_64/pci/common.c Sat Jun 15 17:59:19 2002
@@ -194,3 +194,8 @@

return pcibios_enable_irq(dev);
}
+
+int pcibios_enable_irq(struct pci_dev *dev)
+{
+ return pcibios_enable_irq_func(dev);
+}
diff -Nru a/arch/x86_64/pci/irq.c b/arch/x86_64/pci/irq.c
--- a/arch/x86_64/pci/irq.c Sat Jun 15 17:59:19 2002
+++ b/arch/x86_64/pci/irq.c Sat Jun 15 17:59:19 2002
@@ -44,7 +44,7 @@
int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
};

-int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
+int (*pcibios_enable_irq_func)(struct pci_dev *dev);

/*
* Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
@@ -528,11 +528,13 @@
return 1;
}

+static int pirq_enable_irq(struct pci_dev *dev);
+
static int __init pcibios_irq_init(void)
{
DBG("PCI: IRQ init\n");

- if (pcibios_enable_irq)
+ if (pcibios_enable_irq_func)
return 0;

pirq_table = pirq_find_routing_table();
@@ -551,7 +553,7 @@
pirq_table = NULL;
}

- pcibios_enable_irq = pirq_enable_irq;
+ pcibios_enable_irq_func = pirq_enable_irq;

pcibios_fixup_irqs();
return 0;
@@ -634,7 +636,7 @@
pirq_penalty[irq] += 100;
}

-int pirq_enable_irq(struct pci_dev *dev)
+static int pirq_enable_irq(struct pci_dev *dev)
{
u8 pin;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
diff -Nru a/arch/x86_64/pci/pci.h b/arch/x86_64/pci/pci.h
--- a/arch/x86_64/pci/pci.h Sat Jun 15 17:59:19 2002
+++ b/arch/x86_64/pci/pci.h Sat Jun 15 17:59:19 2002
@@ -68,6 +68,5 @@
extern spinlock_t pci_config_lock;

void pcibios_fixup_irqs(void);
-int pirq_enable_irq(struct pci_dev *dev);

-extern int (*pcibios_enable_irq)(struct pci_dev *dev);
+extern int (*pcibios_enable_irq_func)(struct pci_dev *dev);
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c Sat Jun 15 17:59:19 2002
+++ b/drivers/pci/pci.c Sat Jun 15 17:59:19 2002
@@ -555,6 +555,56 @@
return 0;
}

+/**
+ * pci_assign_irq - Assign an IRQ to a PCI device
+ * @dev: PCI device
+ *
+ * Figure out the the routing from the IRQ pin to an actual IRQ
+ * vector on the processor.
+ * Make sure the device is in D0 state (woken up).
+ * Returns an IRQ number (only supposed to be use for printk() or
+ * similar), or a negative error code.
+ */
+int
+pci_assign_irq(struct pci_dev *dev)
+{
+ int retval;
+
+ pci_set_power_state(dev, 0);
+
+ retval = pcibios_assign_irq(dev);
+ if (retval < 0)
+ return retval;
+
+ return dev->irq;
+}
+
+/**
+ * pci_enable_irq - Enable an IRQ on a PCI device
+ * @dev: PCI device
+ *
+ * Route an IRQ pin to an actual IRQ vector on the processor.
+ * Make sure the device is in D0 state (woken up).
+ * Returns an IRQ number (only supposed to be use for printk() or
+ * similar), or a negative error code.
+ */
+int
+pci_enable_irq(struct pci_dev *dev)
+{
+ int retval;
+
+ retval = pci_assign_irq(dev);
+ if (retval < 0)
+ return retval;
+
+ retval = pcibios_enable_irq(dev);
+ if (retval < 0)
+ return retval;
+
+ return dev->irq;
+}
+
+
static int __devinit pci_init(void)
{
struct pci_dev *dev;
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h Sat Jun 15 17:59:19 2002
+++ b/include/linux/pci.h Sat Jun 15 17:59:19 2002
@@ -500,6 +500,8 @@

void pcibios_fixup_bus(struct pci_bus *);
int pcibios_enable_device(struct pci_dev *);
+int pcibios_assign_irq(struct pci_dev *dev);
+int pcibios_enable_irq(struct pci_dev *dev);
char *pcibios_setup (char *str);

/* Used only when drivers/pci/setup.c is used */

-----------------------------------------------------------------------------
[email protected], 2002-06-15 16:35:23-05:00, [email protected]
PCI: Introduce wrapper to set/clear PCI command bits

It'd be worth it even if we wouldn't make yet more use of it in
the next patch.

---------------------------------------------------------------------------

diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c Sat Jun 15 17:59:20 2002
+++ b/drivers/pci/pci.c Sat Jun 15 17:59:20 2002
@@ -239,6 +239,34 @@
return 0;
}

+static void
+pci_set_command(struct pci_dev *dev, u16 mask)
+{
+ u16 cmd;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+ if ((cmd | mask) != cmd) {
+ printk(KERN_DEBUG "PCI: Enabling device %s (%04x -> %04x)\n",
+ dev->slot_name, cmd, cmd | mask);
+ pci_write_config_word(dev, PCI_COMMAND, cmd | mask);
+ }
+}
+
+static void
+pci_clear_command(struct pci_dev *dev, u16 mask)
+{
+ u16 cmd;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+ if ((cmd & ~mask) != cmd) {
+ printk(KERN_DEBUG "PCI: Disabling device %s (%04x -> %04x)\n",
+ dev->slot_name, cmd, cmd & ~mask);
+ pci_write_config_word(dev, PCI_COMMAND, cmd & ~mask);
+ }
+}
+
/**
* pci_enable_device - Initialize device before it's used by a driver.
* @dev: PCI device to be initialized
@@ -268,13 +296,7 @@
void
pci_disable_device(struct pci_dev *dev)
{
- u16 pci_command;
-
- pci_read_config_word(dev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_MASTER) {
- pci_command &= ~PCI_COMMAND_MASTER;
- pci_write_config_word(dev, PCI_COMMAND, pci_command);
- }
+ pci_clear_command(dev, PCI_COMMAND_MASTER);
}

/**
@@ -426,14 +448,7 @@
void
pci_set_master(struct pci_dev *dev)
{
- u16 cmd;
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- if (! (cmd & PCI_COMMAND_MASTER)) {
- DBG("PCI: Enabling bus mastering for device %s\n", dev->slot_name);
- cmd |= PCI_COMMAND_MASTER;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
+ pci_set_command(dev, PCI_COMMAND_MASTER);
pcibios_set_master(dev);
}

@@ -494,7 +509,6 @@
pci_set_mwi(struct pci_dev *dev)
{
int rc;
- u16 cmd;

#ifdef HAVE_ARCH_PCI_MWI
rc = pcibios_prep_mwi(dev);
@@ -505,12 +519,7 @@
if (rc)
return rc;

- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- if (! (cmd & PCI_COMMAND_INVALIDATE)) {
- DBG("PCI: Enabling Mem-Wr-Inval for device %s\n", dev->slot_name);
- cmd |= PCI_COMMAND_INVALIDATE;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
+ pci_set_command(dev, PCI_COMMAND_INVALIDATE);

return 0;
}
@@ -524,13 +533,7 @@
void
pci_clear_mwi(struct pci_dev *dev)
{
- u16 cmd;
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- if (cmd & PCI_COMMAND_INVALIDATE) {
- cmd &= ~PCI_COMMAND_INVALIDATE;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
+ pci_clear_command(dev, PCI_COMMAND_INVALIDATE);
}

int

-----------------------------------------------------------------------------
[email protected], 2002-06-15 16:38:20-05:00, [email protected]
PCI: Introduce pci_assign/enable_io/mmio functions

The main use of those will be internal to
pci_request/release_io/mmio. However, we export them, since
there'll always be hardware which needs special hacks...

---------------------------------------------------------------------------

diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c Sat Jun 15 17:59:22 2002
+++ b/drivers/pci/pci.c Sat Jun 15 17:59:22 2002
@@ -280,6 +280,13 @@
{
int err;

+ /* FIXME: this should be turned into
+ * pci_enable_irq(dev);
+ * pci_enable_mmio(dev);
+ * pci_enable_io(dev);
+ * after splitting the per arch pcibios_enable_device()
+ * into the appropriate parts
+ */
pci_set_power_state(dev, 0);
if ((err = pcibios_enable_device(dev)) < 0)
return err;
@@ -562,9 +569,9 @@
* pci_assign_irq - Assign an IRQ to a PCI device
* @dev: PCI device
*
+ * Make sure the device is in D0 state (woken up).
* Figure out the the routing from the IRQ pin to an actual IRQ
* vector on the processor.
- * Make sure the device is in D0 state (woken up).
* Returns an IRQ number (only supposed to be use for printk() or
* similar), or a negative error code.
*/
@@ -586,8 +593,8 @@
* pci_enable_irq - Enable an IRQ on a PCI device
* @dev: PCI device
*
- * Route an IRQ pin to an actual IRQ vector on the processor.
* Make sure the device is in D0 state (woken up).
+ * Route an IRQ pin to an actual IRQ vector on the processor.
* Returns an IRQ number (only supposed to be use for printk() or
* similar), or a negative error code.
*/
@@ -607,6 +614,111 @@
return dev->irq;
}

+static int
+pci_assign_resources(struct pci_dev *dev, unsigned long flags)
+{
+ int nr, retval = 0;
+ struct resource *r;
+
+ pci_set_power_state(dev, 0);
+
+ for (nr = 0; nr < PCI_ROM_RESOURCE; nr++) {
+ r = &dev->resource[nr];
+
+ /* Skip if other type */
+ if ((r->flags ^ flags) & (IORESOURCE_IO | IORESOURCE_MEM))
+ continue;
+
+ /* If unassigned, try to assign */
+ if (!r->start && r->end) {
+ retval = pci_assign_resource(dev, nr);
+ if (retval < 0)
+ break;
+ }
+ }
+ return retval;
+}
+
+/**
+ * pci_assign_mmio - Assign MMIO resources on a PCI device
+ * @dev: PCI device
+ *
+ * Make sure the device is in D0 state (woken up).
+ * Assign all as of yet unassigned MMIO resources for
+ * the PCI device.
+ * Returns 0 on success, or a negative error code.
+ */
+int
+pci_assign_mmio(struct pci_dev *dev)
+{
+ return pci_assign_resources(dev, IORESOURCE_MEM);
+}
+
+/**
+ * pci_assign_io - Assign IO resources on a PCI device
+ * @dev: PCI device
+ *
+ * Make sure the device is in D0 state (woken up).
+ * Assign all as of yet unassigned IO resources for
+ * the PCI device.
+ * Returns 0 on success, or a negative error code.
+ */
+int
+pci_assign_io(struct pci_dev *dev)
+{
+ return pci_assign_resources(dev, IORESOURCE_IO);
+}
+
+static int
+pci_enable_resources(struct pci_dev *dev, unsigned long flags)
+{
+ int retval;
+
+ retval = pci_assign_resources(dev, flags);
+ if (retval < 0)
+ return retval;
+
+ if (flags & IORESOURCE_IO)
+ pci_set_command(dev, PCI_COMMAND_IO);
+ if (flags & IORESOURCE_MEM)
+ pci_set_command(dev, PCI_COMMAND_MEMORY);
+
+ return 0;
+}
+
+/**
+ * pci_enable_mmio - Enable IO resources on a PCI device
+ * @dev: PCI device
+ *
+ * Make sure the device is in D0 state (woken up).
+ * Assign all as of yet unassigned IO resources for
+ * the PCI device.
+ * Enable MMIO in the PCI COMMAND config word
+ * Returns 0 on success, or a negative error code.
+ */
+int
+pci_enable_mmio(struct pci_dev *dev)
+{
+ return pci_enable_resources(dev, IORESOURCE_MEM);
+}
+
+/**
+ * pci_enable_io - Enable IO resources on a PCI device
+ * @dev: PCI device
+ *
+ * Make sure the device is in D0 state (woken up).
+ * Assign all as of yet unassigned IO resources for
+ * the PCI device.
+ * Enable IO in the PCI COMMAND config word
+ * Returns 0 on success, or a negative error code.
+ */
+int
+pci_enable_io(struct pci_dev *dev)
+{
+ return pci_enable_resources(dev, IORESOURCE_IO);
+}
+
+

static int __devinit pci_init(void)
{
@@ -654,6 +766,13 @@
EXPORT_SYMBOL(pci_save_state);
EXPORT_SYMBOL(pci_restore_state);
EXPORT_SYMBOL(pci_enable_wake);
+
+EXPORT_SYMBOL(pci_assign_irq);
+EXPORT_SYMBOL(pci_assign_mmio);
+EXPORT_SYMBOL(pci_assign_io);
+EXPORT_SYMBOL(pci_enable_irq);
+EXPORT_SYMBOL(pci_enable_mmio);
+EXPORT_SYMBOL(pci_enable_io);

/* Obsolete functions */

diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h Sat Jun 15 17:59:22 2002
+++ b/include/linux/pci.h Sat Jun 15 17:59:22 2002
@@ -576,6 +576,13 @@
int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_assign_resource(struct pci_dev *dev, int i);

+int pci_assign_irq(struct pci_dev *dev);
+int pci_enable_irq(struct pci_dev *dev);
+int pci_assign_mmio(struct pci_dev *dev);
+int pci_assign_io(struct pci_dev *dev);
+int pci_enable_mmio(struct pci_dev *dev);
+int pci_enable_io(struct pci_dev *dev);
+
/* Power management related routines */
int pci_save_state(struct pci_dev *dev, u32 *buffer);
int pci_restore_state(struct pci_dev *dev, u32 *buffer);

-----------------------------------------------------------------------------
[email protected], 2002-06-15 17:23:10-05:00, [email protected]
PCI: Add pci_request_* and pci_release_* API

Docu is available inline. When switching a driver to this API,
calling pci_enable_device() is not necessary anymore, the needed
resources will be activated at pci_request_* time.

In particular, that means if your driver only uses MMIO, IO resources
on your card won't be assigned and enabled (it's possible that the
BIOS did that, though).

---------------------------------------------------------------------------

diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c Sat Jun 15 17:59:23 2002
+++ b/drivers/pci/pci.c Sat Jun 15 17:59:23 2002
@@ -614,6 +614,57 @@
return dev->irq;
}

+/**
+ * pci_request_irq - Register an interrupt handler for a PCI device
+ * @dev: PCI device
+ * @handler: Function to be called when the IRQ occurs
+ * @irqflags: Interrupt type flags
+ * @dev_id: A cookie passed back to the handler function
+ *
+ * Make sure the device is in D0 state (woken up).
+ * Route an IRQ pin to an actual IRQ vector on the processor.
+ * Register a handler for this IRQ vector.
+ * Returns an IRQ number (only supposed to be use for printk() or
+ * similar), or a negative error code.
+ */
+int
+pci_request_irq(struct pci_dev *dev,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, void *dev_id)
+{
+ int retval;
+
+ BUG_ON(!(flags & SA_SHIRQ));
+
+ retval = pcibios_assign_irq(dev);
+ if (retval < 0)
+ return retval;
+
+ retval = request_irq(dev->irq, handler, flags, dev->slot_name, dev_id);
+ if (retval < 0)
+ return retval;
+
+ retval = pcibios_enable_irq(dev);
+ if (retval < 0)
+ free_irq(dev->irq, dev_id);
+
+ return retval;
+}
+
+/**
+ * pci_release_irq - Unregister an interrupt handler for a PCI device
+ * @dev: PCI device
+ * @dev_id: Same cookie you passed when calling pci_request_irq()
+ *
+ * Unregister an IRQ handler previously registered with
+ * pci_request_irq().
+ */
+void
+pci_release_irq(struct pci_dev *dev, void *dev_id)
+{
+ free_irq(dev->irq, dev_id);
+}
+
static int
pci_assign_resources(struct pci_dev *dev, unsigned long flags)
{
@@ -718,7 +769,136 @@
return pci_enable_resources(dev, IORESOURCE_IO);
}

+static unsigned long
+pci_request_resources(struct pci_dev *pdev, unsigned int nr,
+ unsigned long flags, struct resource *root)
+{
+ struct pci_driver *drv = pci_dev_driver(pdev);
+ char *drv_name = drv ? drv->name : "unknown";
+ struct resource *res;
+
+ BUG_ON(nr >= PCI_ROM_RESOURCE);
+
+ /* Make sure we have the right type (IO/MMIO) */
+ if ((pci_resource_flags(pdev, nr) ^ flags) &
+ (IORESOURCE_IO | IORESOURCE_MEM))
+ goto err;
+
+ /* Assign and enable all resources of this type */
+ pci_enable_resources(pdev, flags);
+
+ res = __request_region(root, pci_resource_start(pdev, nr),
+ pci_resource_len(pdev, nr), drv_name);
+ if (!res)
+ goto err;
+
+ return res->start;
+
+ err:
+ /* Print extensive info so that drivers don't have to do it
+ themselves */
+ printk(KERN_INFO
+ "%s: failed to get %s(%d) for %s, %#lx-%#lx flags %#lx.\n",
+ pdev->slot_name, (flags == IORESOURCE_IO ? "IO" : "MMIO"),
+ nr, drv_name,
+ pci_resource_start(pdev, nr),
+ pci_resource_flags(pdev, nr),
+ pci_resource_end(pdev, nr));

+ return 0;
+}
+
+/**
+ * pci_request_mmio - Register a MMIO region on a PCI device
+ * @dev: PCI device
+ * @nr: The index of the Base Address Register (BAR)
+ *
+ * Make sure the device is in D0 state (woken up).
+ * Assign all as of yet unassigned MMIO resources for
+ * the PCI device.
+ * Enable MMIO in the PCI COMMAND config word
+ * Register the requested MMIO region with the kernel
+ * resource management.
+ * Map the MMIO region.
+ * Returns a cookie to be used with the MMIO functions
+ * (readb, writeb, ...), or NULL on error.
+ * In case of failure it also printk's extensive information
+ * about what went wrong (so you don't need to do that in your
+ * driver)
+ */
+void *
+pci_request_mmio(struct pci_dev *pdev, unsigned int nr)
+{
+ unsigned long base;
+ void *addr;
+
+ base = pci_request_resources(pdev, nr, IORESOURCE_MEM, &iomem_resource);
+ if (!base)
+ return 0;
+
+ addr = ioremap(base, pci_resource_len(pdev, nr));
+ if (!addr)
+ release_region(base, pci_resource_len(pdev, nr));
+
+ return addr;
+}
+
+/**
+ * pci_request_io - Register an IO region on a PCI device
+ * @dev: PCI device
+ * @nr: The index of the Base Address Register (BAR)
+ *
+ * Make sure the device is in D0 state (woken up).
+ * Assign all as of yet unassigned IO resources for
+ * the PCI device.
+ * Enable IO in the PCI COMMAND config word
+ * Register the requested IO region with the kernel
+ * resource management.
+ * Returns an IO port to be used with the IO functions
+ * (inb, outb, ...), or 0 on error.
+ * In case of failure it also printk's extensive information
+ * about what went wrong (so you don't need to do that in your
+ * driver)
+ */
+unsigned long
+pci_request_io(struct pci_dev *dev, unsigned int nr)
+{
+ return pci_request_resources(dev, nr, IORESOURCE_IO, &ioport_resource);
+}
+
+/**
+ * pci_release_mmio - Release an MMIO region on a PCI device
+ * @dev: PCI device
+ * @nr: The index of the Base Address Register (BAR)
+ * @addr: The cookie returned from pci_request_mmio()
+ *
+ * Unmaps and unregisters a MMIO region previously
+ * registered by pci_request_mmio().
+ */
+void
+pci_release_mmio(struct pci_dev *dev, unsigned int nr, void *addr)
+{
+ iounmap(addr);
+ __release_region(&iomem_resource,
+ pci_resource_start(dev, nr),
+ pci_resource_len(dev, nr));
+}
+
+/**
+ * pci_release_io - Release an IO region on a PCI device
+ * @dev: PCI device
+ * @nr: The index of the Base Address Register (BAR)
+ *
+ * Unregisters an IO region previously registered by
+ * pci_request_io().
+ */
+void
+pci_release_io(struct pci_dev *dev, unsigned int nr)
+{
+ __release_region(&ioport_resource,
+ pci_resource_start(dev, nr),
+ pci_resource_len(dev, nr));
+}

static int __devinit pci_init(void)
{
@@ -766,6 +946,13 @@
EXPORT_SYMBOL(pci_save_state);
EXPORT_SYMBOL(pci_restore_state);
EXPORT_SYMBOL(pci_enable_wake);
+
+EXPORT_SYMBOL(pci_request_irq);
+EXPORT_SYMBOL(pci_request_mmio);
+EXPORT_SYMBOL(pci_request_io);
+EXPORT_SYMBOL(pci_release_irq);
+EXPORT_SYMBOL(pci_release_mmio);
+EXPORT_SYMBOL(pci_release_io);

EXPORT_SYMBOL(pci_assign_irq);
EXPORT_SYMBOL(pci_assign_mmio);
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h Sat Jun 15 17:59:23 2002
+++ b/include/linux/pci.h Sat Jun 15 17:59:23 2002
@@ -576,6 +576,15 @@
int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_assign_resource(struct pci_dev *dev, int i);

+int pci_request_irq(struct pci_dev *dev,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, void *dev_id);
+void *pci_request_mmio(struct pci_dev *pdev, unsigned int nr);
+unsigned long pci_request_io(struct pci_dev *dev, unsigned int nr);
+void pci_release_irq(struct pci_dev *dev, void *dev_id);
+void pci_release_mmio(struct pci_dev *dev, unsigned int nr, void *addr);
+void pci_release_io(struct pci_dev *dev, unsigned int nr);
+
int pci_assign_irq(struct pci_dev *dev);
int pci_enable_irq(struct pci_dev *dev);
int pci_assign_mmio(struct pci_dev *dev);

-----------------------------------------------------------------------------
[email protected], 2002-06-15 17:31:38-05:00, [email protected]
PCI: Convert two sample drivers to new interface

eepro100 and ymfpci still work fine on my laptop after the change,
even when zeroing out their BARs during boot.

---------------------------------------------------------------------------

diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c Sat Jun 15 17:59:24 2002
+++ b/drivers/net/eepro100.c Sat Jun 15 17:59:24 2002
@@ -558,6 +558,7 @@
static int __devinit eepro100_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+ u16 cmd;
unsigned long ioaddr;
int irq;
int acpi_idle_state = 0, pm;
@@ -567,65 +568,55 @@
if (speedo_debug > 0 && did_version++ == 0)
printk(version);

- /* save power state before pci_enable_device overwrites it */
+ /* save power state before pci_request_* overwrites it */
pm = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (pm) {
u16 pwr_command;
pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command);
acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
}
-
- if (pci_enable_device(pdev))
- goto err_out_free_mmio_region;
-
- pci_set_master(pdev);
-
- if (!request_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1), "eepro100")) {
- printk (KERN_ERR "eepro100: cannot reserve I/O ports\n");
+ irq = pci_assign_irq(pdev);
+ if (irq < 0)
goto err_out_none;
- }
- if (!request_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0), "eepro100")) {
- printk (KERN_ERR "eepro100: cannot reserve MMIO region\n");
- goto err_out_free_pio_region;
- }

- irq = pdev->irq;
#ifdef USE_IO
- ioaddr = pci_resource_start(pdev, 1);
+ ioaddr = pci_request_io(pdev, 1);
+ if (!ioaddr)
+ goto err_out_none;
+
if (speedo_debug > 2)
- printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
+ printk("Found Intel i82557 PCI Speedo at I/O %#lx IRQ %d.\n",
ioaddr, irq);
#else
- ioaddr = (unsigned long)ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (!ioaddr) {
- printk (KERN_ERR "eepro100: cannot remap MMIO region %lx @ %lx\n",
- pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));
- goto err_out_free_mmio_region;
- }
+ /* Even if using MMIO, the hardware won't work
+ unless IO is enabled, too */
+ if (pci_enable_io(pdev) < 0)
+ goto err_out_none;
+
+ ioaddr = (unsigned long) pci_request_mmio(pdev, 0);
+ if (!ioaddr)
+ goto err_out_none;
+
if (speedo_debug > 2)
- printk("Found Intel i82557 PCI Speedo, MMIO at %#lx, IRQ %d.\n",
+ printk("Found Intel i82557 PCI Speedo, MMIO at %#lx IRQ %d.\n",
pci_resource_start(pdev, 0), irq);
#endif
-
+ pci_set_master(pdev);

if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)
cards_found++;
else
- goto err_out_iounmap;
+ goto err_out_disable;

return 0;

-err_out_iounmap: ;
-#ifndef USE_IO
- iounmap ((void *)ioaddr);
+ err_out_disable:
+ pci_disable_device(pdev);
+#ifdef USE_IO
+ pci_release_io(pdev, 1);
+#else
+ pci_release_mmio(pdev, 0, (void *)ioaddr);
#endif
-err_out_free_mmio_region:
- release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-err_out_free_pio_region:
- release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
err_out_none:
return -ENODEV;
}
@@ -803,7 +794,6 @@
pci_set_drvdata (pdev, dev);

dev->base_addr = ioaddr;
- dev->irq = pdev->irq;

sp = dev->priv;
sp->pdev = pdev;
@@ -924,7 +914,7 @@
int retval;

if (speedo_debug > 1)
- printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
+ printk(KERN_DEBUG "%s: speedo_open()\n", dev->name);

MOD_INC_USE_COUNT;

@@ -939,11 +929,12 @@
sp->in_interrupt = 0;

/* .. we can safely take handler calls during init. */
- retval = request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev);
- if (retval) {
+ retval = pci_request_irq(sp->pdev, &speedo_interrupt, SA_SHIRQ, dev);
+ if (retval < 0) {
MOD_DEC_USE_COUNT;
return retval;
}
+ dev->irq = retval;

dev->if_port = sp->default_port;

@@ -1834,7 +1825,7 @@
/* Shutting down the chip nicely fails to disable flow control. So.. */
outl(PortPartialReset, ioaddr + SCBPort);

- free_irq(dev->irq, dev);
+ pci_release_irq(sp->pdev, dev);

/* Print a few items for debugging. */
if (speedo_debug > 3)
@@ -2253,11 +2244,10 @@

unregister_netdev(dev);

- release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
- release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-
-#ifndef USE_IO
- iounmap((char *)dev->base_addr);
+#ifdef USE_IO
+ pci_release_io(pdev, 1);
+#else
+ pci_release_mmio(pdev, 0, (void *) dev->base_addr);
#endif

pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
@@ -2348,7 +2338,6 @@

/*
* Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
diff -Nru a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c
--- a/sound/oss/ymfpci.c Sat Jun 15 17:59:24 2002
+++ b/sound/oss/ymfpci.c Sat Jun 15 17:59:24 2002
@@ -2496,16 +2496,15 @@
static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_device_id *ent)
{
u16 ctrl;
- unsigned long base;
ymfpci_t *codec;
+ int irq, err;

- int err;
-
+#if 0
if ((err = pci_enable_device(pcidev)) != 0) {
printk(KERN_ERR "ymfpci: pci_enable_device failed\n");
return err;
}
- base = pci_resource_start(pcidev, 0);
+#endif

if ((codec = kmalloc(sizeof(ymfpci_t), GFP_KERNEL)) == NULL) {
printk(KERN_ERR "ymfpci: no core\n");
@@ -2520,25 +2519,16 @@
codec->pci = pcidev;

pci_read_config_byte(pcidev, PCI_REVISION_ID, &codec->rev);
-
- if (request_mem_region(base, 0x8000, "ymfpci") == NULL) {
- printk(KERN_ERR "ymfpci: unable to request mem region\n");
+
+ codec->reg_area_virt = pci_request_mmio(pcidev, 0);
+ if (!codec->reg_area_virt)
goto out_free;
- }
-
- if ((codec->reg_area_virt = ioremap(base, 0x8000)) == NULL) {
- printk(KERN_ERR "ymfpci: unable to map registers\n");
- goto out_release_region;
- }

pci_set_master(pcidev);

- printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",
- (char *)ent->driver_data, base, pcidev->irq);
-
ymfpci_aclink_reset(pcidev);
if (ymfpci_codec_ready(codec, 0, 1) < 0)
- goto out_unmap;
+ goto out_release_mmio;

#ifdef CONFIG_SOUND_YMFPCI_LEGACY
if (assigned == 0) {
@@ -2556,16 +2546,16 @@
goto out_disable_dsp;
ymf_memload(codec);

- if (request_irq(pcidev->irq, ymf_interrupt, SA_SHIRQ, "ymfpci", codec) != 0) {
- printk(KERN_ERR "ymfpci: unable to request IRQ %d\n",
- pcidev->irq);
+ irq = pci_request_irq(pcidev, ymf_interrupt, SA_SHIRQ, codec);
+ if (irq < 0) {
+ printk(KERN_ERR "ymfpci: unable to request IRQ %d\n", irq);
goto out_memfree;
}

/* register /dev/dsp */
if ((codec->dev_audio = register_sound_dsp(&ymf_fops, -1)) < 0) {
printk(KERN_ERR "ymfpci: unable to register dsp\n");
- goto out_free_irq;
+ goto out_release_irq;
}

/*
@@ -2591,6 +2581,9 @@
}
#endif /* CONFIG_SOUND_YMFPCI_LEGACY */

+ printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",
+ (char *)ent->driver_data, pci_resource_start(pcidev, 0), irq);
+
/* put it into driver list */
list_add_tail(&codec->ymf_devs, &ymf_devs);
pci_set_drvdata(pcidev, codec);
@@ -2599,8 +2592,8 @@

out_unregister_sound_dsp:
unregister_sound_dsp(codec->dev_audio);
- out_free_irq:
- free_irq(pcidev->irq, codec);
+ out_release_irq:
+ pci_release_irq(pcidev, codec);
out_memfree:
ymfpci_memfree(codec);
out_disable_dsp:
@@ -2608,10 +2601,8 @@
ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL);
ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
ymfpci_writel(codec, YDSXGR_STATUS, ~0);
- out_unmap:
- iounmap(codec->reg_area_virt);
- out_release_region:
- release_mem_region(pci_resource_start(pcidev, 0), 0x8000);
+ out_release_mmio:
+ pci_release_mmio(pcidev, 0, codec->reg_area_virt);
out_free:
kfree(codec);
return -ENODEV;


2002-06-16 04:57:08

by Linus Torvalds

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work



On Mon, 10 Jun 2002, Patrick Mochel wrote:
>
> Sorry about the delay. Could you please try this patch and let me know if
> it helps? It attempts to treat cardbus more like PCI, and let the PCI
> helpers do the probing.

Peter, can you just remove this patch from your kernel, I don't know how
to fix it. It does something bad to all the resource allocations. The
child resources don't find the parent any more, and you can see the result
in /proc/iomem and /proc/ioport clearly. The cardbus devices are not seen
as "children" of the cardbus controller any more from a resource
standpoint.

So can you go back to the setup before applying this patch, and do a
debugging run of that version instead?

Linus


2002-06-16 07:11:06

by Eric W. Biederman

[permalink] [raw]
Subject: Re: Cardbus

Linus Torvalds <[email protected]> writes:

> On Sat, 15 Jun 2002, Paul Mackerras wrote:
> >
> > IIRC someone told me that we had to do the "assuming transparent" bit
> > because of buggy PCI-PCI bridges used on some PCs. Can anyone
> > enlighten me on the details of that?
>
> It has nothing to do with "buggy" PCI-PCI bridges, and everything to do
> with the fact that a lot of bridges seem to extend on the official PCI
> bridge interface in various ways. In particular, it seems to be fairly
> common to have the _real_ bridging information in the chip-specific range
> (PCI config area 0x40+) instead of in the official "2 mem resources, 2 IO
> resources" place.

As additional detail this works for the bridge manufactures because they
can get the BIOS to do the hard work, and the os doesn't have to touch it.
For any component that isn't designed to be part of a plug-in card,
there isn't a compelling reason for the vendors to follow a standard
interface for configuring it. Only the use case must follow a
standard interface.

Eric

2002-06-16 07:40:38

by Peter Osterlund

[permalink] [raw]
Subject: Re: 2.5.20 - Xircom PCI Cardbus doesn't work

Linus Torvalds <[email protected]> writes:

> On Mon, 10 Jun 2002, Patrick Mochel wrote:
> >
> > Sorry about the delay. Could you please try this patch and let me know if
> > it helps? It attempts to treat cardbus more like PCI, and let the PCI
> > helpers do the probing.
>
> Peter, can you just remove this patch from your kernel, I don't know how
> to fix it. It does something bad to all the resource allocations. The
> child resources don't find the parent any more, and you can see the result
> in /proc/iomem and /proc/ioport clearly. The cardbus devices are not seen
> as "children" of the cardbus controller any more from a resource
> standpoint.
>
> So can you go back to the setup before applying this patch, and do a
> debugging run of that version instead?

Sure, with an unpatched 2.5.21 kernel, bringing up eth0 fails during
boot. Tobias Diedrich posted a one-line patch that fixes this problem
for me:

--- linux-2.5.20/drivers/pcmcia/cardbus.c Sat May 25 03:55:22 2002
+++ linux-2.5.20/drivers/pcmcia/cardbus.c Sun Jun 9 02:27:35 2002
@@ -284,6 +284,7 @@
dev->dev.parent = bus->dev;
strcpy(dev->dev.name, dev->name);
strcpy(dev->dev.bus_id, dev->slot_name);
+ dev->dev.bus = &pci_bus_type;
device_register(&dev->dev);

/* FIXME: Do we need to enable the expansion ROM? */

But he said he didn't know if it was the right fix, and noone has
commented on that yet.

All tests I have done so far with 2.5.21 based kernels produce an oops
at shutdown, which makes the machine hang instead of rebooting or
powering off. I'm not sure if it's related to cardbus devices though.
It could also be caused by the broken cdrom drive in that machine.

Turning off swap:
Turning off quotas:
Unmounting file systems:
Unmounting proc file system:
Halting system...
flushing ide devices: hda <1>Unable to handle kernel NULL pointer dereference at
virtual address 00000004
c017aed3
*pde = 00000000
Oops: 0002
CPU: 0
EIP: 0010:[<c017aed3>] Not tainted
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010202
eax: c02c6d24 ebx: c3ad2000 ecx: 00000000 edx: 00000000
esi: c02c6d0c edi: c0262460 ebp: 00000000 esp: c3ad3e50
ds: 0018 es: 0018 ss: 0018
Stack: c02c6d0c c02c6bb4 00000001 c017b24d c02c6d0c c02c6bb0 c01b03dc c02c6d0c
c02c6bb0 c01a9af6 c02c6bb0 c0261f9c 00000000 00000003 bffffcc8 c011e27c
c0261f9c 00000003 00000000 00000001 c3ad2000 fee1dead c011e6ce c02a8b88
Call Trace: [<c017b24d>] [<c01b03dc>] [<c01a9af6>] [<c011e27c>] [<c011e6ce>]
[<c010fde9>] [<c011c810>] [<c011c8a7>] [<c011cc45>] [<c011d81d>] [<c01380ea>]
[<c0136bc0>] [<c0136c31>] [<c0106ee7>]
Code: 89 4a 04 89 11 89 46 18 89 40 04 8b 43 10 48 89 43 10 8b 43

>>EIP; c017aed3 <do_driver_detach+23/70> <=====
Trace; c017b24d <device_read_power+d/40>
Trace; c01b03dc <idedisk_ioctl+8c/300>
Trace; c01a9af6 <drive_is_flashcard+96/a0>
Trace; c011e27c <notifier_call_chain+1c/40>
Trace; c011e6ce <sys_reboot+17e/2a0>
Trace; c010fde9 <wake_up_process+9/10>
Trace; c011c810 <deliver_signal+50/60>
Trace; c011c8a7 <send_sig_info+87/b0>
Trace; c011cc45 <kill_something_info+165/190>
Trace; c011d81d <sys_kill+4d/60>
Trace; c01380ea <fput+ea/110>
Trace; c0136bc0 <filp_close+a0/b0>
Trace; c0136c31 <sys_close+61/90>
Trace; c0106ee7 <syscall_call+7/b>
Code; c017aed3 <do_driver_detach+23/70>
00000000 <_EIP>:
Code; c017aed3 <do_driver_detach+23/70> <=====
0: 89 4a 04 mov %ecx,0x4(%edx) <=====
Code; c017aed6 <do_driver_detach+26/70>
3: 89 11 mov %edx,(%ecx)
Code; c017aed8 <do_driver_detach+28/70>
5: 89 46 18 mov %eax,0x18(%esi)
Code; c017aedb <do_driver_detach+2b/70>
8: 89 40 04 mov %eax,0x4(%eax)
Code; c017aede <do_driver_detach+2e/70>
b: 8b 43 10 mov 0x10(%ebx),%eax
Code; c017aee1 <do_driver_detach+31/70>
e: 48 dec %eax
Code; c017aee2 <do_driver_detach+32/70>
f: 89 43 10 mov %eax,0x10(%ebx)
Code; c017aee5 <do_driver_detach+35/70>
12: 8b 43 00 mov 0x0(%ebx),%eax

--
Peter Osterlund - [email protected]
http://w1.894.telia.com/~u89404340

2002-06-16 11:56:57

by Paul Mackerras

[permalink] [raw]
Subject: Re: Cardbus

Linus Torvalds writes:

> It has nothing to do with "buggy" PCI-PCI bridges, and everything to do
> with the fact that a lot of bridges seem to extend on the official PCI
> bridge interface in various ways. In particular, it seems to be fairly
> common to have the _real_ bridging information in the chip-specific range
> (PCI config area 0x40+) instead of in the official "2 mem resources, 2 IO
> resources" place.

OK, that makes sense. (The "buggy" wasn't intended as any kind of
put-down, it was just what I had been told.)

What ends up in the official places? Zeroes, maybe?

Can we discriminate between these bridges, and bridges which use the
official places but where the firmware has closed an aperture? I
really would like the code not to assume the bridge is transparent in
the latter case.

Paul.