From proski at gnu.org  Mon May  5 03:17:25 2003
From: proski at gnu.org (Pavel Roskin)
Date: Mon May  5 07:17:30 2003
Subject: Crash when unloading yenta_socket in Linux 2.5.69
Message-ID: <Pine.LNX.4.44.0305050156570.2491-200000@localhost.localdomain>

Hello!

Linux 2.5.69 crashes if I insert module "yenta_socket" and then remove it.  
The backtrace is attached. 

Debugging shows that the crash happens at the following statement in 
yenta_config_init():

exca_writeb(socket, I365_GBLCTL, 0x00);

That's the first exca_writeb() called in that function.

It seems to me that ether shutdown_socket() should be called earlier in 
pcmcia_unregister_socket(), or it should know that the socket is about to 
be shut down, so it would avoid unnecessary initialization.

I switched to using CONFIG_HIGHMEM4G recently, maybe that triggers the 
problem.

-- 
Regards,
Pavel Roskin

-------------- next part --------------
Linux Kernel Card Services 3.1.22
  options:  [pci] [cardbus] [pm]
Yenta IRQ list 0000, PCI irq12
Socket status: 30000010
Unable to handle kernel paging request at virtual address fb34181e
 printing eip:
fb348706
*pde = 3642c067
*pte = 00000000
Oops: 0002 [#1]
CPU:    0
EIP:    0060:[<fb348706>]    Not tainted
EFLAGS: 00010212
EIP is at yenta_config_init+0x196/0x1f0 [yenta_socket]
eax: fb34181e   ebx: fb34a880   ecx: 8000503c   edx: 00000cfe
esi: c1aedc00   edi: fb35e820   ebp: f6091dec   esp: f6091dd0
ds: 007b   es: 007b   ss: 0068
Process rmmod (pid: 2533, threadinfo=f6090000 task=f62becc0)
Stack: fb34181e fb34937c 00000076 00000500 05c01e74 fb34a880 00000000 f6091e04 
       fb348774 fb34a880 f6091e2c 00000286 fb34a880 f6091e24 fb348ed2 fb34a880 
       c01776df f7122b24 c1bffe10 00000286 f7768a00 f6091e30 fb347032 fb34a880 
Call Trace:
 [<fb34937c>] +0x8/0x4c [yenta_socket]
 [<fb34a880>] +0x0/0x840 [yenta_socket]
 [<fb348774>] yenta_init+0x14/0x50 [yenta_socket]
 [<fb34a880>] +0x0/0x840 [yenta_socket]
 [<fb34a880>] +0x0/0x840 [yenta_socket]
 [<fb348ed2>] ti1250_init+0x12/0xc0 [yenta_socket]
 [<fb34a880>] +0x0/0x840 [yenta_socket]
 [<c01776df>] remove_proc_entry+0xaf/0x110
 [<fb347032>] +0x32/0x40 [yenta_socket]
 [<fb34a880>] +0x0/0x840 [yenta_socket]
 [<fb3562ec>] init_socket+0x2c/0x30 [pcmcia_core]
 [<fb356667>] shutdown_socket+0x17/0xf0 [pcmcia_core]
 [<fb35650a>] pcmcia_unregister_socket+0x6a/0x140 [pcmcia_core]
 [<fb34a904>] +0x84/0x840 [yenta_socket]
 [<fb35e884>] pcmcia_socket+0x0/0x3c [pcmcia_core]
 [<fb34a914>] +0x94/0x840 [yenta_socket]
 [<fb35e820>] pcmcia_socket_class+0x0/0x64 [pcmcia_core]
 [<c023050f>] class_device_del+0xcf/0xe0
 [<fb34a914>] +0x94/0x840 [yenta_socket]
 [<fb35e878>] pcmcia_socket_class+0x58/0x64 [pcmcia_core]
 [<fb35e864>] pcmcia_socket_class+0x44/0x64 [pcmcia_core]
 [<fb34a914>] +0x94/0x840 [yenta_socket]
 [<fb34a4a8>] pci_cardbus_driver+0x28/0xa0 [yenta_socket]
 [<c0230534>] class_device_unregister+0x14/0x20
 [<fb34a914>] +0x94/0x840 [yenta_socket]
 [<fb34a880>] +0x0/0x840 [yenta_socket]
 [<fb3473d4>] cardbus_remove+0x34/0x50 [yenta_socket]
 [<fb34a914>] +0x94/0x840 [yenta_socket]
 [<fb34a4a8>] pci_cardbus_driver+0x28/0xa0 [yenta_socket]
 [<c01d8e06>] pci_device_remove+0x36/0x40
 [<c022f7ce>] device_release_driver+0x5e/0x60
 [<fb34a4ec>] pci_cardbus_driver+0x6c/0xa0 [yenta_socket]
 [<fb34a4ec>] pci_cardbus_driver+0x6c/0xa0 [yenta_socket]
 [<c022f7f2>] driver_detach+0x22/0x40
 [<c022fac5>] bus_remove_driver+0x55/0x90
 [<fb34a4a8>] pci_cardbus_driver+0x28/0xa0 [yenta_socket]
 [<fb34a4b0>] pci_cardbus_driver+0x30/0xa0 [yenta_socket]
 [<fb34a4a8>] pci_cardbus_driver+0x28/0xa0 [yenta_socket]
 [<fb34a740>] +0x0/0x140 [yenta_socket]
 [<c022fefa>] driver_unregister+0x1a/0x42
 [<fb34a4a8>] pci_cardbus_driver+0x28/0xa0 [yenta_socket]
 [<c014045f>] unmap_vma_list+0x1f/0x30
 [<fb349372>] +0x12/0x14 [yenta_socket]
 [<fb34a4a8>] pci_cardbus_driver+0x28/0xa0 [yenta_socket]
 [<c012d8f6>] sys_delete_module+0x1d6/0x240
 [<c01408a7>] sys_munmap+0x57/0x80
 [<c0109289>] sysenter_past_esp+0x52/0x71

Code: c6 00 00 c7 44 24 04 7c 93 34 fb c7 44 24 08 76 00 00 00 8b 
 
From rmk at arm.linux.org.uk  Mon May  5 11:32:17 2003
From: rmk at arm.linux.org.uk (Russell King)
Date: Mon May  5 10:32:26 2003
Subject: Crash when unloading yenta_socket in Linux 2.5.69
In-Reply-To: <Pine.LNX.4.44.0305050156570.2491-200000@localhost.localdomain>;
	from proski@gnu.org on Mon, May 05, 2003 at 02:17:25AM -0400
References: <Pine.LNX.4.44.0305050156570.2491-200000@localhost.localdomain>
Message-ID: <20030505103217.A27052@flint.arm.linux.org.uk>

On Mon, May 05, 2003 at 02:17:25AM -0400, Pavel Roskin wrote:
> Linux 2.5.69 crashes if I insert module "yenta_socket" and then remove it.  
> The backtrace is attached. 

Hmm, I guess something went wrong with Greg's device class changes.  I'll
take a look sometime between now and tomorrow.

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


From linux at brodo.de  Mon May  5 14:09:07 2003
From: linux at brodo.de (linux@brodo.de)
Date: Mon May  5 12:09:57 2003
Subject: AW: Crash when unloading yenta_socket in Linux 2.5.69
Message-ID: <20030505110907.1B2C583AE@voodoo.strato-webmail.de>

> On Mon, May 05, 2003 at 02:17:25AM -0400, Pavel Roskin wrote:
> > Linux 2.5.69 crashes if I insert module "yenta_socket" and then remove
it.  
> > The backtrace is attached. 
> 
> Hmm, I guess something went wrong with Greg's device class changes. 
I'll
> take a look sometime between now and tomorrow.

The socket initialization re-work and the new pccard_ops (struct
pcmcia_socket *) patch[*] are almost ready, will send them out this
evening. Russell, could you upgrade the SA1x00-drivers then, please? 

Hopefully I'll have the yenta.c and pci_socket.c merge done by the end of
this week.

     Dominik

[*] I had to do both things at once so that pci_socket.c doesn't break, so
it'll be a quite large diff :-(

From proski at gnu.org  Mon May  5 10:53:42 2003
From: proski at gnu.org (Pavel Roskin)
Date: Mon May  5 14:53:48 2003
Subject: Crash when unloading yenta_socket in Linux 2.5.69
In-Reply-To: <20030505103217.A27052@flint.arm.linux.org.uk>
Message-ID: <Pine.LNX.4.44.0305050949490.2523-100000@localhost.localdomain>

On Mon, 5 May 2003, Russell King wrote:

> On Mon, May 05, 2003 at 02:17:25AM -0400, Pavel Roskin wrote:
> > Linux 2.5.69 crashes if I insert module "yenta_socket" and then remove it.  
> > The backtrace is attached. 
> 
> Hmm, I guess something went wrong with Greg's device class changes.  I'll
> take a look sometime between now and tomorrow.

Maybe.  I'm also getting an oops without high memory support, but it looks 
very differently.  It happens in class_device_del().  The output of dmesg 
is attached.

By the way, there are no problems on unload with plx9052 version 0.1.1, 
which was also updated to the new class API.  It's here, as usually:
http://www.red-bean.com/~proski/plx9052/

-- 
Regards,
Pavel Roskin


From proski at gnu.org  Tue May  6 02:51:23 2003
From: proski at gnu.org (Pavel Roskin)
Date: Tue May  6 06:51:23 2003
Subject: Crash when unloading yenta_socket in Linux 2.5.69
In-Reply-To: <Pine.LNX.4.44.0305050949490.2523-100000@localhost.localdomain>
Message-ID: <Pine.LNX.4.44.0305060132020.2546-200000@localhost.localdomain>

On Mon, 5 May 2003, Pavel Roskin wrote:

> Maybe.  I'm also getting an oops without high memory support, but it looks 
> very differently.  It happens in class_device_del().  The output of dmesg 
> is attached.

In both cases, the same thing happens, it's just that the crash happens in
different places.  (I believe the high memory configuration crashes
earlier because of better sanity checks.)

socket->base is unmapped in yenta_close(), which is called by
cardbus_remove().  The value of socket->base is not changed to NULL, so it
becomes invalid.

Then cardbus_remove() calls class_device_unregister(), which calls 
pcmcia_unregister_socket(), which it turn tries to access memory space 
of the socket.

The attached patch fixes the problem.

-- 
Regards,
Pavel Roskin
-------------- next part --------------
--- linux.orig/drivers/pcmcia/pci_socket.c
+++ linux/drivers/pcmcia/pci_socket.c
@@ -196,9 +196,9 @@ static void __devexit cardbus_remove (st
 	pci_socket_t *socket = pci_get_drvdata(dev);
 
 	/* note: we are already unregistered from the cs core */
+	class_device_unregister(&socket->cls_d.class_dev);
 	if (socket->op && socket->op->close)
 		socket->op->close(socket);
-	class_device_unregister(&socket->cls_d.class_dev);
 	pci_set_drvdata(dev, NULL);
 }
 
From proski at gnu.org  Tue May  6 04:12:28 2003
From: proski at gnu.org (Pavel Roskin)
Date: Tue May  6 08:12:31 2003
Subject: Crash when unloading yenta_socket in Linux 2.5.69
In-Reply-To: <Pine.LNX.4.44.0305060132020.2546-200000@localhost.localdomain>
Message-ID: <Pine.LNX.4.44.0305060305320.2854-100000@localhost.localdomain>

On Tue, 6 May 2003, Pavel Roskin wrote:

> In both cases, the same thing happens, it's just that the crash happens
> in different places.  (I believe the high memory configuration crashes
> earlier because of better sanity checks.)

Hopefully the last reply to myself.  The crash in class_device_del() has
been tracked down to my plx9052 driver, which wasn't calling
class_device_unregister().  It was my error that I loaded and unloaded
that module and assumed that everything was fine.

After fixing plx9052 and applying the patch for cardbus_remove() from the
previous message there are no more kernel panics.  For today, at least :-)

-- 
Regards,
Pavel Roskin


From hch at lst.de  Thu May  8 15:28:05 2003
From: hch at lst.de (Christoph Hellwig)
Date: Thu May  8 13:28:23 2003
Subject: [PATCH] kill register_pccard_driver
Message-ID: <20030508142805.A23673@lst.de>

I tried to get as much in as possible through the maintainers but
didn't get much feedback.. (Except two batches included and Kai
ACKing the ISDN stuff).

So here's a big patch to move the reamining users over to
pcmcia_register_driver and kill it off.


--- 1.15/drivers/char/pcmcia/synclink_cs.c	Sat Apr 26 12:16:19 2003
+++ edited/drivers/char/pcmcia/synclink_cs.c	Thu May  8 09:12:11 2003
@@ -3170,9 +3170,17 @@
 	}
 }
 
+static struct pcmcia_driver mgslpc_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "synclink_cs",
+	};
+	.attach		= mgslpc_attach,
+	.detach		= mgslpc_detach,
+
 static int __init synclink_cs_init(void)
 {
-    servinfo_t serv;
+    int error;
 
     if (break_on_load) {
 	    mgslpc_get_text_ptr();
@@ -3181,13 +3189,9 @@
 
     printk("%s %s\n", driver_name, driver_version);
 
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	    printk(KERN_NOTICE "synclink_cs: Card Services release "
-		   "does not match!\n");
-	    return -1;
-    }
-    register_pccard_driver(&dev_info, &mgslpc_attach, &mgslpc_detach);
+    error = pcmcia_register_driver(&mgslpc_driver);
+    if (error)
+	    return error;
 
     /* Initialize the tty_driver structure */
 	
@@ -3274,7 +3278,9 @@
 		printk("%s(%d) failed to unregister callout driver err=%d\n",
 		       __FILE__,__LINE__,rc);
 
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&mgslpc_driver);
+
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL) {
 		del_timer(&dev_list->release);
 		if (dev_list->state & DEV_CONFIG)
--- 1.9/drivers/ide/legacy/ide-cs.c	Sat Apr 26 12:16:19 2003
+++ edited/drivers/ide/legacy/ide-cs.c	Thu May  8 08:55:20 2003
@@ -470,28 +470,25 @@
     return 0;
 } /* ide_event */
 
-/*====================================================================*/
+static struct pcmcia_driver ide_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "ide_cs",
+	},
+	.attach		= ide_attach,
+	.detach		= ide_detach,
+};
 
 static int __init init_ide_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "ide-cs: Card Services release "
-	       "does not match!\n");
-	return -EINVAL;
-    }
-    register_pccard_driver(&dev_info, &ide_attach, &ide_detach);
-    return 0;
+	return pcmcia_register_driver(&ide_cs_driver);
 }
 
 static void __exit exit_ide_cs(void)
 {
-    DEBUG(0, "ide-cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	ide_detach(dev_list);
+	pcmcia_unregister_driver(&ide_cs_driver);
+	while (dev_list != NULL)
+		ide_detach(dev_list);
 }
 
 module_init(init_ide_cs);
--- 1.7/drivers/isdn/hardware/avm/avm_cs.c	Sat Apr 26 12:16:19 2003
+++ edited/drivers/isdn/hardware/avm/avm_cs.c	Thu May  8 08:55:20 2003
@@ -510,29 +510,30 @@
     return 0;
 } /* avmcs_event */
 
-/*====================================================================*/
+static struct pcmcia_driver avmcs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "avmcs_cs",
+	},
+	.attach		= avmcs_attach,
+	.detach		= avmcs_detach,
+};
 
 static int __init avmcs_init(void)
 {
-    servinfo_t serv;
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "avm_cs: Card Services release "
-	       "does not match!\n");
-	return -1;
-    }
-    register_pccard_driver(&dev_info, &avmcs_attach, &avmcs_detach);
-    return 0;
+	return pcmcia_register_driver(&avmcs_driver);
 }
 
 static void __exit avmcs_exit(void)
 {
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL) {
-	if (dev_list->state & DEV_CONFIG)
-	    avmcs_release((u_long)dev_list);
-	avmcs_detach(dev_list);
-    }
+	pcmcia_unregister_driver(&avmcs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL) {
+		if (dev_list->state & DEV_CONFIG)
+			avmcs_release((u_long)dev_list);
+		avmcs_detach(dev_list);
+	}
 }
 
 module_init(avmcs_init);
--- 1.4/drivers/isdn/hisax/avma1_cs.c	Sat Apr 26 12:16:19 2003
+++ edited/drivers/isdn/hisax/avma1_cs.c	Thu May  8 08:55:21 2003
@@ -515,30 +521,30 @@
     return 0;
 } /* avma1cs_event */
 
-/*====================================================================*/
+static struct pcmcia_driver avma1cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "avma1_cs",
+	},
+	.attach		= avma1cs_attach,
+	.detach		= avma1cs_detach,
+};
 
 static int __init init_avma1_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-        printk(KERN_NOTICE "avma1_cs: Card Services release "
-               "does not match!\n");
-        return -1;
-    }
-    register_pccard_driver(&dev_info, &avma1cs_attach, &avma1cs_detach);
-    return 0;
+	return pcmcia_register_driver(&avma1cs_driver);
 }
 
 static void __exit exit_avma1_cs(void)
 {
-    DEBUG(0, "avma1_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	if (dev_list->state & DEV_CONFIG)
-	    avma1cs_release((u_long)dev_list);
-        avma1cs_detach(dev_list);
+	pcmcia_unregister_driver(&avma1cs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL) {
+		if (dev_list->state & DEV_CONFIG)
+			avma1cs_release((u_long)dev_list);
+		avma1cs_detach(dev_list);
+	}
 }
 
 module_init(init_avma1_cs);
--- 1.5/drivers/isdn/hisax/elsa_cs.c	Sat Apr 26 12:16:20 2003
+++ edited/drivers/isdn/hisax/elsa_cs.c	Thu May  8 08:55:21 2003
@@ -531,28 +531,27 @@
     return 0;
 } /* elsa_cs_event */
 
-/*====================================================================*/
+static struct pcmcia_driver elsa_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "elsa_cs",
+	},
+	.attach		= elsa_cs_attach,
+	.detach		= elsa_cs_detach,
+};
 
 static int __init init_elsa_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-        printk(KERN_NOTICE "elsa_cs: Card Services release "
-               "does not match!\n");
-        return -1;
-    }
-    register_pccard_driver(&dev_info, &elsa_cs_attach, &elsa_cs_detach);
-    return 0;
+	return pcmcia_register_driver(&elsa_cs_driver);
 }
 
 static void __exit exit_elsa_cs(void)
 {
-    DEBUG(0, "elsa_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-        elsa_cs_detach(dev_list);
+	pcmcia_unregister_driver(&elsa_cs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL)
+		elsa_cs_detach(dev_list);
 }
 
 module_init(init_elsa_cs);
--- 1.8/drivers/isdn/hisax/sedlbauer_cs.c	Sat Apr 26 12:16:20 2003
+++ edited/drivers/isdn/hisax/sedlbauer_cs.c	Thu May  8 08:55:21 2003
@@ -633,34 +633,32 @@
     return 0;
 } /* sedlbauer_event */
 
-/*====================================================================*/
+static struct pcmcia_driver sedlbauer_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "sedlbauer_cs",
+	},
+	.attach		= sedlbauer_attach,
+	.detach		= sedlbauer_detach,
+};
 
 static int __init init_sedlbauer_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "sedlbauer_cs: Card Services release "
-	       "does not match!\n");
-	return -1;
-    }
-    register_pccard_driver(&dev_info, &sedlbauer_attach, &sedlbauer_detach);
-    return 0;
+	return pcmcia_register_driver(&sedlbauer_driver);
 }
 
 static void __exit exit_sedlbauer_cs(void)
 {
-    DEBUG(0, "sedlbauer_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL) {
-	del_timer(&dev_list->release);
-	if (dev_list->state & DEV_CONFIG)
-	    sedlbauer_release((u_long)dev_list);
-	sedlbauer_detach(dev_list);
-    }
+	pcmcia_unregister_driver(&sedlbauer_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL) {
+		del_timer(&dev_list->release);
+		if (dev_list->state & DEV_CONFIG)
+			sedlbauer_release((u_long)dev_list);
+		sedlbauer_detach(dev_list);
+	}
 }
 
 module_init(init_sedlbauer_cs);
 module_exit(exit_sedlbauer_cs);
-
--- 1.3/drivers/mtd/maps/pcmciamtd.c	Sat Apr 26 12:16:20 2003
+++ edited/drivers/mtd/maps/pcmciamtd.c	Thu May  8 09:14:32 2003
@@ -836,17 +836,18 @@
 	return link;
 }
 
+static struct pcmcia_driver pcmciamtd_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "pcmciamtd",
+	},
+	.attach		= pcmciamtd_attach,
+	.detach		= pcmciamtd_detach,
+};
 
 static int __init init_pcmciamtd(void)
 {
-	servinfo_t serv;
-
 	info(DRIVER_DESC " " DRIVER_VERSION);
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		err("Card Services release does not match!");
-		return -1;
-	}
 
 	if(buswidth && buswidth != 1 && buswidth != 2) {
 		info("bad buswidth (%d), using default", buswidth);
@@ -860,8 +861,8 @@
 		info("bad mem_type (%d), using default", mem_type);
 		mem_type = 0;
 	}
-	register_pccard_driver(&dev_info, &pcmciamtd_attach, &pcmciamtd_detach);
-	return 0;
+
+	return pcmcia_register_driver(&pcmciamtd_driver);
 }
 
 
@@ -870,7 +871,10 @@
 	struct list_head *temp1, *temp2;
 
 	DEBUG(1, DRIVER_DESC " unloading");
-	unregister_pccard_driver(&dev_info);
+
+	pcmcia_unregister_driver(&pcmciamtd_driver);
+
+	/* XXX: this really needs to move into generic code.. */
 	list_for_each_safe(temp1, temp2, &dev_list) {
 		dev_link_t *link = &list_entry(temp1, struct pcmciamtd_dev, list)->link;
 		if (link && (link->state & DEV_CONFIG)) {
--- 1.15/drivers/net/wireless/netwave_cs.c	Sat Apr 26 12:16:23 2003
+++ edited/drivers/net/wireless/netwave_cs.c	Thu May  8 08:55:22 2003
@@ -1741,31 +1741,28 @@
     return 0;
 }
 
-static int __init init_netwave_cs(void) {
-    servinfo_t serv;
+static struct pcmcia_driver netwave_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "netwave_cs",
+	},
+	.attach		= netwave_attach,
+	.detach		= netwave_detach,
+};
 
-    DEBUG(0, "%s\n", version);
-
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk("netwave_cs: Card Services release does not match!\n");
-	return -1;
-    }
- 
-    register_pccard_driver(&dev_info, &netwave_attach, &netwave_detach);
-	
-    return 0;
+static int __init init_netwave_cs(void)
+{
+	return pcmcia_register_driver(&netwave_driver);
 }
 
-static void __exit exit_netwave_cs(void) {
-    DEBUG(1, "netwave_cs: unloading\n");
-
-    unregister_pccard_driver(&dev_info);
+static void __exit exit_netwave_cs(void)
+{
+	pcmcia_unregister_driver(&netwave_driver);
 
-    /* Do some cleanup of the device list */
-    netwave_flush_stale_links();
-    if(dev_list != NULL)	/* Critical situation */
-        printk("netwave_cs: devices remaining when removing module\n");
+	/* Do some cleanup of the device list */
+	netwave_flush_stale_links();
+	if (dev_list != NULL)	/* Critical situation */
+		printk("netwave_cs: devices remaining when removing module\n");
 }
 
 module_init(init_netwave_cs);
--- 1.19/drivers/net/wireless/orinoco_cs.c	Sat Apr 26 12:16:24 2003
+++ edited/drivers/net/wireless/orinoco_cs.c	Thu May  8 08:55:22 2003
@@ -687,29 +687,27 @@
  * become const */
 static char version[] __initdata = "orinoco_cs.c 0.13a (David Gibson <hermes@gibson.dropbear.id.au> and others)";
 
+static struct pcmcia_driver orinoco_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "orinoco_cs",
+	},
+	.attach		= orinoco_cs_attach,
+	.detach		= orinoco_cs_detach,
+};
+
 static int __init
 init_orinoco_cs(void)
 {
-	servinfo_t serv;
-
 	printk(KERN_DEBUG "%s\n", version);
 
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "orinoco_cs: Card Services release "
-		       "does not match!\n");
-		return -1;
-	}
-
-	register_pccard_driver(&dev_info, &orinoco_cs_attach, &orinoco_cs_detach);
-
-	return 0;
+	return pcmcia_register_driver(&orinoco_driver);
 }
 
 static void __exit
 exit_orinoco_cs(void)
 {
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&orinoco_driver);
 
 	if (dev_list)
 		DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
--- 1.20/drivers/net/wireless/wavelan_cs.c	Sat Apr 26 12:16:25 2003
+++ edited/drivers/net/wireless/wavelan_cs.c	Thu May  8 08:55:23 2003
@@ -5422,77 +5422,28 @@
   return 0;
 }
 
-/****************************** MODULE ******************************/
-/*
- * Module entry points : insertion & removal
- */
+static struct pcmcia_driver wavelan_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "wavelan_cs",
+	},
+	.attach		= wavelan_attach,
+	.detach		= wavelan_detach,
+};
 
-/*------------------------------------------------------------------*/
-/*
- * Module insertion : initialisation of the module.
- * Register the card with cardmgr...
- */
 static int __init
 init_wavelan_cs(void)
 {
-  servinfo_t	serv;
-
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "-> init_wavelan_cs()\n");
-#ifdef DEBUG_VERSION_SHOW
-  printk(KERN_DEBUG "%s", version);
-#endif
-#endif
-
-  CardServices(GetCardServicesInfo, &serv);
-  if(serv.Revision != CS_RELEASE_CODE)
-    {
-#ifdef DEBUG_CONFIG_ERRORS
-      printk(KERN_WARNING "init_wavelan_cs: Card Services release does not match!\n");
-#endif
-      return -1;
-    }
-
-  register_pccard_driver(&dev_info, &wavelan_attach, &wavelan_detach);
-
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "<- init_wavelan_cs()\n");
-#endif
-  return 0;
+	return pcmcia_register_driver(&wavelan_driver);
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Module removal
- */
 static void __exit
 exit_wavelan_cs(void)
 {
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "-> cleanup_module()\n");
-#endif
-#ifdef DEBUG_BASIC_SHOW
-  printk(KERN_NOTICE "wavelan_cs: unloading\n");
-#endif
-
-  /* Do some cleanup of the device list */
-  wv_flush_stale_links();
-
-  /* If there remain some devices... */
-#ifdef DEBUG_CONFIG_ERRORS
-  if(dev_list != NULL)
-    {
-      /* Honestly, if this happen we are in a deep s**t */
-      printk(KERN_INFO "wavelan_cs: devices remaining when removing module\n");
-      printk(KERN_INFO "Please flush your disks and reboot NOW !\n");
-    }
-#endif
-
-  unregister_pccard_driver(&dev_info);
+	/* Do some cleanup of the device list */
+	wv_flush_stale_links();
 
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "<- cleanup_module()\n");
-#endif
+	pcmcia_unregister_driver(&wavelan_driver);
 }
 
 module_init(init_wavelan_cs);
--- 1.7/drivers/parport/parport_cs.c	Sat Apr 26 12:16:25 2003
+++ edited/drivers/parport/parport_cs.c	Thu May  8 09:08:36 2003
@@ -390,28 +390,27 @@
     return 0;
 } /* parport_event */
 
-/*====================================================================*/
+static struct pcmcia_driver parport_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "parport_cs",
+	},
+	.attach		= parport_attach,
+	.detach		= parport_detach,
+};
 
 static int __init init_parport_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "parport_cs: Card Services release "
-	       "does not match!\n");
-	return -EINVAL;
-    }
-    register_pccard_driver(&dev_info, &parport_attach, &parport_detach);
-    return 0;
+	return pcmcia_register_driver(&parport_cs_driver);
 }
 
 static void __exit exit_parport_cs(void)
 {
-    DEBUG(0, "parport_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	parport_detach(dev_list);
+	pcmcia_unregister_driver(&parport_cs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL)
+		parport_detach(dev_list);
 }
 
 module_init(init_parport_cs);
--- 1.27/drivers/pcmcia/ds.c	Tue Apr 29 18:46:18 2003
+++ edited/drivers/pcmcia/ds.c	Thu May  8 09:14:52 2003
@@ -182,50 +182,6 @@
 }
 EXPORT_SYMBOL(pcmcia_unregister_driver);
 
-
-int register_pccard_driver(dev_info_t *dev_info,
-			   dev_link_t *(*attach)(void),
-			   void (*detach)(dev_link_t *))
-{
-    struct pcmcia_driver *driver;
-
-    DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info);
-    driver = get_pcmcia_driver(dev_info);
-    if (driver)
-	    return -EBUSY;
-
-    driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
-    if (!driver) return -ENOMEM;
-    memset(driver, 0, sizeof(struct pcmcia_driver));
-    driver->drv.name = (char *)dev_info;
-    pcmcia_register_driver(driver);
-
-    driver->attach = attach;
-    driver->detach = detach;
-
-    return 0;
-} /* register_pccard_driver */
-
-/*====================================================================*/
-
-int unregister_pccard_driver(dev_info_t *dev_info)
-{
-    struct pcmcia_driver *driver;
-
-    DEBUG(0, "ds: unregister_pccard_driver('%s')\n",
-	  (char *)dev_info);
-
-    driver = get_pcmcia_driver(dev_info);
-    if (!driver)
-	return -ENODEV;
-    
-    pcmcia_unregister_driver(driver);
-    kfree(driver);
-    return 0;
-} /* unregister_pccard_driver */
-
-/*====================================================================*/
-
 #ifdef CONFIG_PROC_FS
 static int proc_read_drivers_callback(struct device_driver *driver, void *d)
 {
@@ -877,11 +833,6 @@
 	.write		= ds_write,
 	.poll		= ds_poll,
 };
-
-EXPORT_SYMBOL(register_pccard_driver);
-EXPORT_SYMBOL(unregister_pccard_driver);
-
-/*====================================================================*/
 
 static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int socket_nr)
 {
--- 1.10/include/pcmcia/ds.h	Sat Apr 26 12:16:27 2003
+++ edited/include/pcmcia/ds.h	Thu May  8 09:03:43 2003
@@ -156,12 +156,6 @@
 int pcmcia_register_driver(struct pcmcia_driver *driver);
 void pcmcia_unregister_driver(struct pcmcia_driver *driver);
 
-/* legacy driver registration interface.  don't use in new code */
-int register_pccard_driver(dev_info_t *dev_info,
-			   dev_link_t *(*attach)(void),
-			   void (*detach)(dev_link_t *));
-int unregister_pccard_driver(dev_info_t *dev_info);
-
 /* error reporting */
 void cs_error(client_handle_t handle, int func, int ret);
 

From hch at lst.de  Thu May  8 18:54:59 2003
From: hch at lst.de (Christoph Hellwig)
Date: Thu May  8 16:55:07 2003
Subject: [PATCH] kill register_pccard_driver
In-Reply-To: <20030508142805.A23673@lst.de>;
	from hch@lst.de on Thu, May 08, 2003 at 02:28:05PM +0200
References: <20030508142805.A23673@lst.de>
Message-ID: <20030508175459.A26109@lst.de>

On Thu, May 08, 2003 at 02:28:05PM +0200, Christoph Hellwig wrote:
> I tried to get as much in as possible through the maintainers but
> didn't get much feedback.. (Except two batches included and Kai
> ACKing the ISDN stuff).
> 
> So here's a big patch to move the reamining users over to
> pcmcia_register_driver and kill it off.

Willy noticed the synclink_cs part was flawed.  Fixed patch below.


--- 1.15/drivers/char/pcmcia/synclink_cs.c	Sat Apr 26 12:16:19 2003
+++ edited/drivers/char/pcmcia/synclink_cs.c	Thu May  8 15:13:55 2003
@@ -3170,9 +3170,18 @@
 	}
 }
 
+static struct pcmcia_driver mgslpc_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "synclink_cs",
+	},
+	.attach		= mgslpc_attach,
+	.detach		= mgslpc_detach,
+};
+
 static int __init synclink_cs_init(void)
 {
-    servinfo_t serv;
+    int error;
 
     if (break_on_load) {
 	    mgslpc_get_text_ptr();
@@ -3181,13 +3190,9 @@
 
     printk("%s %s\n", driver_name, driver_version);
 
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	    printk(KERN_NOTICE "synclink_cs: Card Services release "
-		   "does not match!\n");
-	    return -1;
-    }
-    register_pccard_driver(&dev_info, &mgslpc_attach, &mgslpc_detach);
+    error = pcmcia_register_driver(&mgslpc_driver);
+    if (error)
+	    return error;
 
     /* Initialize the tty_driver structure */
 	
@@ -3274,7 +3279,9 @@
 		printk("%s(%d) failed to unregister callout driver err=%d\n",
 		       __FILE__,__LINE__,rc);
 
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&mgslpc_driver);
+
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL) {
 		del_timer(&dev_list->release);
 		if (dev_list->state & DEV_CONFIG)
--- 1.9/drivers/ide/legacy/ide-cs.c	Sat Apr 26 12:16:19 2003
+++ edited/drivers/ide/legacy/ide-cs.c	Thu May  8 15:11:57 2003
@@ -470,28 +470,25 @@
     return 0;
 } /* ide_event */
 
-/*====================================================================*/
+static struct pcmcia_driver ide_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "ide_cs",
+	},
+	.attach		= ide_attach,
+	.detach		= ide_detach,
+};
 
 static int __init init_ide_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "ide-cs: Card Services release "
-	       "does not match!\n");
-	return -EINVAL;
-    }
-    register_pccard_driver(&dev_info, &ide_attach, &ide_detach);
-    return 0;
+	return pcmcia_register_driver(&ide_cs_driver);
 }
 
 static void __exit exit_ide_cs(void)
 {
-    DEBUG(0, "ide-cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	ide_detach(dev_list);
+	pcmcia_unregister_driver(&ide_cs_driver);
+	while (dev_list != NULL)
+		ide_detach(dev_list);
 }
 
 module_init(init_ide_cs);
--- 1.7/drivers/isdn/hardware/avm/avm_cs.c	Sat Apr 26 12:16:19 2003
+++ edited/drivers/isdn/hardware/avm/avm_cs.c	Thu May  8 15:11:57 2003
@@ -510,29 +510,30 @@
     return 0;
 } /* avmcs_event */
 
-/*====================================================================*/
+static struct pcmcia_driver avmcs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "avmcs_cs",
+	},
+	.attach		= avmcs_attach,
+	.detach		= avmcs_detach,
+};
 
 static int __init avmcs_init(void)
 {
-    servinfo_t serv;
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "avm_cs: Card Services release "
-	       "does not match!\n");
-	return -1;
-    }
-    register_pccard_driver(&dev_info, &avmcs_attach, &avmcs_detach);
-    return 0;
+	return pcmcia_register_driver(&avmcs_driver);
 }
 
 static void __exit avmcs_exit(void)
 {
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL) {
-	if (dev_list->state & DEV_CONFIG)
-	    avmcs_release((u_long)dev_list);
-	avmcs_detach(dev_list);
-    }
+	pcmcia_unregister_driver(&avmcs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL) {
+		if (dev_list->state & DEV_CONFIG)
+			avmcs_release((u_long)dev_list);
+		avmcs_detach(dev_list);
+	}
 }
 
 module_init(avmcs_init);
--- 1.4/drivers/isdn/hisax/avma1_cs.c	Sat Apr 26 12:16:19 2003
+++ edited/drivers/isdn/hisax/avma1_cs.c	Thu May  8 15:11:57 2003
@@ -515,30 +521,30 @@
     return 0;
 } /* avma1cs_event */
 
-/*====================================================================*/
+static struct pcmcia_driver avma1cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "avma1_cs",
+	},
+	.attach		= avma1cs_attach,
+	.detach		= avma1cs_detach,
+};
 
 static int __init init_avma1_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-        printk(KERN_NOTICE "avma1_cs: Card Services release "
-               "does not match!\n");
-        return -1;
-    }
-    register_pccard_driver(&dev_info, &avma1cs_attach, &avma1cs_detach);
-    return 0;
+	return pcmcia_register_driver(&avma1cs_driver);
 }
 
 static void __exit exit_avma1_cs(void)
 {
-    DEBUG(0, "avma1_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	if (dev_list->state & DEV_CONFIG)
-	    avma1cs_release((u_long)dev_list);
-        avma1cs_detach(dev_list);
+	pcmcia_unregister_driver(&avma1cs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL) {
+		if (dev_list->state & DEV_CONFIG)
+			avma1cs_release((u_long)dev_list);
+		avma1cs_detach(dev_list);
+	}
 }
 
 module_init(init_avma1_cs);
===== drivers/isdn/hisax/elsa_cs.c 1.5 vs edited =====
--- 1.5/drivers/isdn/hisax/elsa_cs.c	Sat Apr 26 12:16:20 2003
+++ edited/drivers/isdn/hisax/elsa_cs.c	Thu May  8 15:11:57 2003
@@ -531,28 +531,27 @@
     return 0;
 } /* elsa_cs_event */
 
-/*====================================================================*/
+static struct pcmcia_driver elsa_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "elsa_cs",
+	},
+	.attach		= elsa_cs_attach,
+	.detach		= elsa_cs_detach,
+};
 
 static int __init init_elsa_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-        printk(KERN_NOTICE "elsa_cs: Card Services release "
-               "does not match!\n");
-        return -1;
-    }
-    register_pccard_driver(&dev_info, &elsa_cs_attach, &elsa_cs_detach);
-    return 0;
+	return pcmcia_register_driver(&elsa_cs_driver);
 }
 
 static void __exit exit_elsa_cs(void)
 {
-    DEBUG(0, "elsa_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-        elsa_cs_detach(dev_list);
+	pcmcia_unregister_driver(&elsa_cs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL)
+		elsa_cs_detach(dev_list);
 }
 
 module_init(init_elsa_cs);
===== drivers/isdn/hisax/sedlbauer_cs.c 1.8 vs edited =====
--- 1.8/drivers/isdn/hisax/sedlbauer_cs.c	Sat Apr 26 12:16:20 2003
+++ edited/drivers/isdn/hisax/sedlbauer_cs.c	Thu May  8 15:11:57 2003
@@ -633,34 +633,32 @@
     return 0;
 } /* sedlbauer_event */
 
-/*====================================================================*/
+static struct pcmcia_driver sedlbauer_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "sedlbauer_cs",
+	},
+	.attach		= sedlbauer_attach,
+	.detach		= sedlbauer_detach,
+};
 
 static int __init init_sedlbauer_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "sedlbauer_cs: Card Services release "
-	       "does not match!\n");
-	return -1;
-    }
-    register_pccard_driver(&dev_info, &sedlbauer_attach, &sedlbauer_detach);
-    return 0;
+	return pcmcia_register_driver(&sedlbauer_driver);
 }
 
 static void __exit exit_sedlbauer_cs(void)
 {
-    DEBUG(0, "sedlbauer_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL) {
-	del_timer(&dev_list->release);
-	if (dev_list->state & DEV_CONFIG)
-	    sedlbauer_release((u_long)dev_list);
-	sedlbauer_detach(dev_list);
-    }
+	pcmcia_unregister_driver(&sedlbauer_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL) {
+		del_timer(&dev_list->release);
+		if (dev_list->state & DEV_CONFIG)
+			sedlbauer_release((u_long)dev_list);
+		sedlbauer_detach(dev_list);
+	}
 }
 
 module_init(init_sedlbauer_cs);
 module_exit(exit_sedlbauer_cs);
-
--- 1.3/drivers/mtd/maps/pcmciamtd.c	Sat Apr 26 12:16:20 2003
+++ edited/drivers/mtd/maps/pcmciamtd.c	Thu May  8 15:11:57 2003
@@ -836,17 +836,18 @@
 	return link;
 }
 
+static struct pcmcia_driver pcmciamtd_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "pcmciamtd",
+	},
+	.attach		= pcmciamtd_attach,
+	.detach		= pcmciamtd_detach,
+};
 
 static int __init init_pcmciamtd(void)
 {
-	servinfo_t serv;
-
 	info(DRIVER_DESC " " DRIVER_VERSION);
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		err("Card Services release does not match!");
-		return -1;
-	}
 
 	if(buswidth && buswidth != 1 && buswidth != 2) {
 		info("bad buswidth (%d), using default", buswidth);
@@ -860,8 +861,8 @@
 		info("bad mem_type (%d), using default", mem_type);
 		mem_type = 0;
 	}
-	register_pccard_driver(&dev_info, &pcmciamtd_attach, &pcmciamtd_detach);
-	return 0;
+
+	return pcmcia_register_driver(&pcmciamtd_driver);
 }
 
 
@@ -870,7 +871,10 @@
 	struct list_head *temp1, *temp2;
 
 	DEBUG(1, DRIVER_DESC " unloading");
-	unregister_pccard_driver(&dev_info);
+
+	pcmcia_unregister_driver(&pcmciamtd_driver);
+
+	/* XXX: this really needs to move into generic code.. */
 	list_for_each_safe(temp1, temp2, &dev_list) {
 		dev_link_t *link = &list_entry(temp1, struct pcmciamtd_dev, list)->link;
 		if (link && (link->state & DEV_CONFIG)) {
--- 1.18/drivers/net/pcmcia/pcnet_cs.c	Sat Apr 26 12:16:22 2003
+++ edited/drivers/net/pcmcia/pcnet_cs.c	Thu May  8 13:47:46 2003
@@ -1620,16 +1620,7 @@
 
 static int __init init_pcnet_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "pcnet_cs: Card Services release "
-	       "does not match!\n");
-	return -EINVAL;
-    }
-    pcmcia_register_driver(&pcnet_driver);
-    return 0;
+    return pcmcia_register_driver(&pcnet_driver);
 }
 
 static void __exit exit_pcnet_cs(void)
--- 1.15/drivers/net/wireless/netwave_cs.c	Sat Apr 26 12:16:23 2003
+++ edited/drivers/net/wireless/netwave_cs.c	Thu May  8 15:11:57 2003
@@ -1741,31 +1741,28 @@
     return 0;
 }
 
-static int __init init_netwave_cs(void) {
-    servinfo_t serv;
+static struct pcmcia_driver netwave_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "netwave_cs",
+	},
+	.attach		= netwave_attach,
+	.detach		= netwave_detach,
+};
 
-    DEBUG(0, "%s\n", version);
-
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk("netwave_cs: Card Services release does not match!\n");
-	return -1;
-    }
- 
-    register_pccard_driver(&dev_info, &netwave_attach, &netwave_detach);
-	
-    return 0;
+static int __init init_netwave_cs(void)
+{
+	return pcmcia_register_driver(&netwave_driver);
 }
 
-static void __exit exit_netwave_cs(void) {
-    DEBUG(1, "netwave_cs: unloading\n");
-
-    unregister_pccard_driver(&dev_info);
+static void __exit exit_netwave_cs(void)
+{
+	pcmcia_unregister_driver(&netwave_driver);
 
-    /* Do some cleanup of the device list */
-    netwave_flush_stale_links();
-    if(dev_list != NULL)	/* Critical situation */
-        printk("netwave_cs: devices remaining when removing module\n");
+	/* Do some cleanup of the device list */
+	netwave_flush_stale_links();
+	if (dev_list != NULL)	/* Critical situation */
+		printk("netwave_cs: devices remaining when removing module\n");
 }
 
 module_init(init_netwave_cs);
--- 1.19/drivers/net/wireless/orinoco_cs.c	Sat Apr 26 12:16:24 2003
+++ edited/drivers/net/wireless/orinoco_cs.c	Thu May  8 15:11:57 2003
@@ -687,29 +687,27 @@
  * become const */
 static char version[] __initdata = "orinoco_cs.c 0.13a (David Gibson <hermes@gibson.dropbear.id.au> and others)";
 
+static struct pcmcia_driver orinoco_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "orinoco_cs",
+	},
+	.attach		= orinoco_cs_attach,
+	.detach		= orinoco_cs_detach,
+};
+
 static int __init
 init_orinoco_cs(void)
 {
-	servinfo_t serv;
-
 	printk(KERN_DEBUG "%s\n", version);
 
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "orinoco_cs: Card Services release "
-		       "does not match!\n");
-		return -1;
-	}
-
-	register_pccard_driver(&dev_info, &orinoco_cs_attach, &orinoco_cs_detach);
-
-	return 0;
+	return pcmcia_register_driver(&orinoco_driver);
 }
 
 static void __exit
 exit_orinoco_cs(void)
 {
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&orinoco_driver);
 
 	if (dev_list)
 		DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
--- 1.20/drivers/net/wireless/wavelan_cs.c	Sat Apr 26 12:16:25 2003
+++ edited/drivers/net/wireless/wavelan_cs.c	Thu May  8 15:11:57 2003
@@ -5422,77 +5422,28 @@
   return 0;
 }
 
-/****************************** MODULE ******************************/
-/*
- * Module entry points : insertion & removal
- */
+static struct pcmcia_driver wavelan_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "wavelan_cs",
+	},
+	.attach		= wavelan_attach,
+	.detach		= wavelan_detach,
+};
 
-/*------------------------------------------------------------------*/
-/*
- * Module insertion : initialisation of the module.
- * Register the card with cardmgr...
- */
 static int __init
 init_wavelan_cs(void)
 {
-  servinfo_t	serv;
-
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "-> init_wavelan_cs()\n");
-#ifdef DEBUG_VERSION_SHOW
-  printk(KERN_DEBUG "%s", version);
-#endif
-#endif
-
-  CardServices(GetCardServicesInfo, &serv);
-  if(serv.Revision != CS_RELEASE_CODE)
-    {
-#ifdef DEBUG_CONFIG_ERRORS
-      printk(KERN_WARNING "init_wavelan_cs: Card Services release does not match!\n");
-#endif
-      return -1;
-    }
-
-  register_pccard_driver(&dev_info, &wavelan_attach, &wavelan_detach);
-
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "<- init_wavelan_cs()\n");
-#endif
-  return 0;
+	return pcmcia_register_driver(&wavelan_driver);
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Module removal
- */
 static void __exit
 exit_wavelan_cs(void)
 {
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "-> cleanup_module()\n");
-#endif
-#ifdef DEBUG_BASIC_SHOW
-  printk(KERN_NOTICE "wavelan_cs: unloading\n");
-#endif
-
-  /* Do some cleanup of the device list */
-  wv_flush_stale_links();
-
-  /* If there remain some devices... */
-#ifdef DEBUG_CONFIG_ERRORS
-  if(dev_list != NULL)
-    {
-      /* Honestly, if this happen we are in a deep s**t */
-      printk(KERN_INFO "wavelan_cs: devices remaining when removing module\n");
-      printk(KERN_INFO "Please flush your disks and reboot NOW !\n");
-    }
-#endif
-
-  unregister_pccard_driver(&dev_info);
+	/* Do some cleanup of the device list */
+	wv_flush_stale_links();
 
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "<- cleanup_module()\n");
-#endif
+	pcmcia_unregister_driver(&wavelan_driver);
 }
 
 module_init(init_wavelan_cs);
--- 1.7/drivers/parport/parport_cs.c	Sat Apr 26 12:16:25 2003
+++ edited/drivers/parport/parport_cs.c	Thu May  8 15:11:57 2003
@@ -390,28 +390,27 @@
     return 0;
 } /* parport_event */
 
-/*====================================================================*/
+static struct pcmcia_driver parport_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "parport_cs",
+	},
+	.attach		= parport_attach,
+	.detach		= parport_detach,
+};
 
 static int __init init_parport_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "parport_cs: Card Services release "
-	       "does not match!\n");
-	return -EINVAL;
-    }
-    register_pccard_driver(&dev_info, &parport_attach, &parport_detach);
-    return 0;
+	return pcmcia_register_driver(&parport_cs_driver);
 }
 
 static void __exit exit_parport_cs(void)
 {
-    DEBUG(0, "parport_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	parport_detach(dev_list);
+	pcmcia_unregister_driver(&parport_cs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL)
+		parport_detach(dev_list);
 }
 
 module_init(init_parport_cs);
--- 1.27/drivers/pcmcia/ds.c	Tue Apr 29 18:46:18 2003
+++ edited/drivers/pcmcia/ds.c	Thu May  8 15:11:57 2003
@@ -182,50 +182,6 @@
 }
 EXPORT_SYMBOL(pcmcia_unregister_driver);
 
-
-int register_pccard_driver(dev_info_t *dev_info,
-			   dev_link_t *(*attach)(void),
-			   void (*detach)(dev_link_t *))
-{
-    struct pcmcia_driver *driver;
-
-    DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info);
-    driver = get_pcmcia_driver(dev_info);
-    if (driver)
-	    return -EBUSY;
-
-    driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
-    if (!driver) return -ENOMEM;
-    memset(driver, 0, sizeof(struct pcmcia_driver));
-    driver->drv.name = (char *)dev_info;
-    pcmcia_register_driver(driver);
-
-    driver->attach = attach;
-    driver->detach = detach;
-
-    return 0;
-} /* register_pccard_driver */
-
-/*====================================================================*/
-
-int unregister_pccard_driver(dev_info_t *dev_info)
-{
-    struct pcmcia_driver *driver;
-
-    DEBUG(0, "ds: unregister_pccard_driver('%s')\n",
-	  (char *)dev_info);
-
-    driver = get_pcmcia_driver(dev_info);
-    if (!driver)
-	return -ENODEV;
-    
-    pcmcia_unregister_driver(driver);
-    kfree(driver);
-    return 0;
-} /* unregister_pccard_driver */
-
-/*====================================================================*/
-
 #ifdef CONFIG_PROC_FS
 static int proc_read_drivers_callback(struct device_driver *driver, void *d)
 {
@@ -877,11 +833,6 @@
 	.write		= ds_write,
 	.poll		= ds_poll,
 };
-
-EXPORT_SYMBOL(register_pccard_driver);
-EXPORT_SYMBOL(unregister_pccard_driver);
-
-/*====================================================================*/
 
 static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int socket_nr)
 {
 static struct uart_driver sunsab_reg = {
 	.owner			= THIS_MODULE,
 	.driver_name		= "serial",
-#ifdef CONFIG_DEVFS_FS
-	.dev_name		= "tts/",
-#else
+	.devfs_name		= "tts/",
 	.dev_name		= "ttyS",
-#endif
 	.major			= TTY_MAJOR,
 };
 
--- 1.10/include/pcmcia/ds.h	Sat Apr 26 12:16:27 2003
+++ edited/include/pcmcia/ds.h	Thu May  8 15:11:57 2003
@@ -156,12 +156,6 @@
 int pcmcia_register_driver(struct pcmcia_driver *driver);
 void pcmcia_unregister_driver(struct pcmcia_driver *driver);
 
-/* legacy driver registration interface.  don't use in new code */
-int register_pccard_driver(dev_info_t *dev_info,
-			   dev_link_t *(*attach)(void),
-			   void (*detach)(dev_link_t *));
-int unregister_pccard_driver(dev_info_t *dev_info);
-
 /* error reporting */
 void cs_error(client_handle_t handle, int func, int ret);
 

From linux at brodo.de  Sat May 10 18:05:05 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sat May 10 16:06:29 2003
Subject: [PATCHES] please test: pcmcia socket registration update
Message-ID: <20030510150505.GA23491@brodo.de>

Skipped content of type multipart/mixed-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030510/66f4414b/attachment.bin
From proski at gnu.org  Mon May 12 14:08:10 2003
From: proski at gnu.org (Pavel Roskin)
Date: Mon May 12 18:08:03 2003
Subject: [PATCH] Fallback to PCI IRQs for TI bridges
In-Reply-To: <3EBD2F2B.8070104@yahoo.com>
References: <3EBD2F2B.8070104@yahoo.com>
Message-ID: <Pine.LNX.4.55.0305121241110.1420@marabou.research.att.com>

On Sat, 10 May 2003, Tim Small wrote:

> I wonder if I could hassle you guys into taking a quick look at this
> forum thread regarding a problem I'm having getting a TI1031 based
> PCI->PCMCIA bridge to work?

OK, but next time please copy to a mailing list.  I hate writing personal
e-mails when the discussion should remain open and archived.  The new
PCMCIA list would be the best place: linux-pcmcia@lists.infradead.org

P.S. Adding cc: after some internal struggle :-)

> https://sourceforge.net/forum/forum.php?thread_id=863984&forum_id=43629

OK, my understanding is that your patch may be correct.  I'm not
familiar with the internals of PCI implementation to judge.  However, it
may happen that you only need pci_read_irq(dev) and nothing else.  You may
want the attached patch that is less intrusive in terms of affected
devices (as opposed to affected lines of code).

> I'm referring back to this thread:
>
> http://lists.insecure.org/lists/linux-kernel/2003/Mar/0012.html

My patch may be needed as well, but it does a different thing - it
reprograms bridge-specific registers to use PCI IRQ is ISA IRQ wasn't
found.  Your patch fixes finding PCI IRQ for certain devices.

My TI and Ricoh cards are listed as "CardBus bridge", so they have their
IRQs determined from the PCI config space (if I understand the whole
situation correctly).  Your card identifies itself as a PCMCIA bridge, so
the kernel doesn't know its PCI IRQ.  Reprogramming the bridge registers
would be insufficient in this case.

I don't see corresponding code in drivers/pci/pci.c in Linux 2.5.69.  It
may happen that it will work for you without changes.

-- 
Regards,
Pavel Roskin-------------- next part --------------
--- linux.orig/drivers/pci/pci.c
+++ linux/drivers/pci/pci.c
@@ -1405,12 +1405,17 @@ int pci_setup_device(struct pci_dev * de
 		break;
 
 	case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
-		if (class != PCI_CLASS_BRIDGE_CARDBUS)
+		switch (class) {
+		case PCI_CLASS_BRIDGE_CARDBUS:
+			pci_read_bases(dev, 1, 0);
+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
+			/* fallthrough */
+		case PCI_CLASS_BRIDGE_PCMCIA:
+			pci_read_irq(dev);
+		default:
 			goto bad;
-		pci_read_irq(dev);
-		pci_read_bases(dev, 1, 0);
-		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
-		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
+		}
 		break;
 
 	default:				    /* unknown header */
From tim_small at yahoo.com  Tue May 13 02:24:41 2003
From: tim_small at yahoo.com (Tim Small)
Date: Tue May 13 01:24:58 2003
Subject: [PATCH] Fallback to PCI IRQs for TI bridges
In-Reply-To: <Pine.LNX.4.55.0305121241110.1420@marabou.research.att.com>
References: <3EBD2F2B.8070104@yahoo.com>
	<Pine.LNX.4.55.0305121241110.1420@marabou.research.att.com>
Message-ID: <3EC03B49.5040502@yahoo.com>

Pavel Roskin wrote:

>>https://sourceforge.net/forum/forum.php?thread_id=863984&forum_id=43629
>>    
>>
>
>OK, my understanding is that your patch may be correct.  I'm not
>familiar with the internals of PCI implementation to judge.  However, it
>may happen that you only need pci_read_irq(dev) and nothing else.  You may
>want the attached patch that is less intrusive in terms of affected
>devices (as opposed to affected lines of code).
>  
>
OK, a couple of quick questions...  Why would you want to do these 
things for a PCI<->Cardbus bridge, but not for a PCI <-> PCMCIA bridge?  
In fact, I'm not very sure what the first line does at all, but I assume 
the second two lines are needed to populate the device structure with 
the codes that would be used by device drivers to search for the device 
(and /proc/pci etc.).  I'm pretty much stabbing around in the dark at 
the moment, so any explanation would be helpful ;-)..

+			pci_read_bases(dev, 1, 0);
+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);



>>I'm referring back to this thread:
>>
>>http://lists.insecure.org/lists/linux-kernel/2003/Mar/0012.html
>>    
>>
>
>My patch may be needed as well, but it does a different thing - it
>reprograms bridge-specific registers to use PCI IRQ is ISA IRQ wasn't
>found.  Your patch fixes finding PCI IRQ for certain devices.
>  
>
Yep - there are two ways to wire up the interupt pins for this chip, you 
can either wire pins to the ISA IRQ lines, or wire (some of the same) 
pins to the PCI INTA, and INTB lines.  Since this card is a PCI slot 
device, it is wired up in the second way.  The pin outputs are 
switchable in software by programming some of the bridge registers.

I've just found this FreeBSD code - search for "pcic_pci_ti113x_func" in 
http://gatekeeper.dec.com/pub/BSD/FreeBSD/FreeBSD-stable/src/sys/pccard/pcic_pci.c

>My TI and Ricoh cards are listed as "CardBus bridge", so they have their
>IRQs determined from the PCI config space (if I understand the whole
>situation correctly).
>
>Your card identifies itself as a PCMCIA bridge, so
>the kernel doesn't know its PCI IRQ.  Reprogramming the bridge registers
>would be insufficient in this case.
>  
>
Hmm, where do the two IRQs (10, and 12) come from?  I was assuming the 
PCI setup code (BIOS or kernel) is setting up routing of the INT lines 
from the PCI slot to these IRQs?  I think the problem is that the 
chipset also has to be set up to deliver interrupts to the INT lines (as 
in above FreeBSD code), as I think this is how my particular card is 
wired up (rather than using IRQSER to deliver ISA IRQs over a PCI slot), 
not completely sure about that, but it would tie in with the behaviour I 
am seeing, and the w2k problem here:

http://support.microsoft.com/default.aspx?scid=kb;en-us;257458

>I don't see corresponding code in drivers/pci/pci.c in Linux 2.5.69.  It
>may happen that it will work for you without changes.
>  
>
I haven't tried 2.5.69 yet.  I will try this, and a bit more code 
hacking tomorrow, and I'll have a read of the 1131 datasheet to see how 
the 1031 differs.  Here are some docs, but I haven't had a chance to 
have a close look yet..

http://www-s.ti.com/sc/ds/pci1031.pdf   (datasheet)

http://www-s.ti.com/sc/ds/pci1131.pdf  (datasheet)

http://www-s.ti.com/sc/psheets/scpa007/scpa007.pdf  (1131 interrupt app 
note)


So I think I have to:

. Work out how to read/write the relevant registers to set up the IRQ 
routing.
.  See if there is some way to probe which interrupt scheme is being 
used, otherwise add the different schemes as a module option.

Does this sound sane?  Is there some way to get a yenta so generate a 
'test' interrupt, I wonder?


Thanks for the input!

Tim.

>------------------------------------------------------------------------
>
>--- linux.orig/drivers/pci/pci.c
>+++ linux/drivers/pci/pci.c
>@@ -1405,12 +1405,17 @@ int pci_setup_device(struct pci_dev * de
> 		break;
> 
> 	case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
>-		if (class != PCI_CLASS_BRIDGE_CARDBUS)
>+		switch (class) {
>+		case PCI_CLASS_BRIDGE_CARDBUS:
>+			pci_read_bases(dev, 1, 0);
>+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
>+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
>+			/* fallthrough */
>+		case PCI_CLASS_BRIDGE_PCMCIA:
>+			pci_read_irq(dev);
>+		default:
> 			goto bad;
>-		pci_read_irq(dev);
>-		pci_read_bases(dev, 1, 0);
>-		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
>-		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
>+		}
> 		break;
> 
> 	default:				    /* unknown header */
>  
>



From proski at gnu.org  Tue May 13 03:09:47 2003
From: proski at gnu.org (Pavel Roskin)
Date: Tue May 13 07:09:52 2003
Subject: [PATCH] Fallback to PCI IRQs for TI bridges
In-Reply-To: <3EC03B49.5040502@yahoo.com>
Message-ID: <Pine.LNX.4.44.0305130121440.6036-100000@localhost.localdomain>

On Tue, 13 May 2003, Tim Small wrote:

> OK, a couple of quick questions...  Why would you want to do these 
> things for a PCI<->Cardbus bridge, but not for a PCI <-> PCMCIA bridge?  
> In fact, I'm not very sure what the first line does at all, but I assume 
> the second two lines are needed to populate the device structure with 
> the codes that would be used by device drivers to search for the device 
> (and /proc/pci etc.).  I'm pretty much stabbing around in the dark at 
> the moment, so any explanation would be helpful ;-)..

The same is true for me.

> +			pci_read_bases(dev, 1, 0);

Note that the last argument is 0, not PCI_ROM_ADDRESS (0x30) as for normal 
devices.  I'm looking at Linux 2.5.69 now, file drivers/pci/probe.c, and 
my understanding of pci_read_bases() is that setting rom=0 skips reading 
part from that from ROM.

> +			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
> +			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);

Pure PCMCIA bridges may not have these registers.  It may be better to
read PCI_SUBSYSTEM_VENDOR_ID and PCI_SUBSYSTEM_ID respectively, like it's
done for normal devices.  On the other hand, PCI_HEADER_TYPE_CARDBUS might
mean that you have those registers.

The output of "lspci -x -s 00:14" may be useful to see the dump of the 
configuration space for your bridges.  Perhaps you need to talk to PCI 
specialists.

> Hmm, where do the two IRQs (10, and 12) come from?

You have two different PCI functions, 00:14.0 and 00:14.1, and they have 
different IRQs.

> >I don't see corresponding code in drivers/pci/pci.c in Linux 2.5.69.  It
> >may happen that it will work for you without changes.

I missed it completely.  Essentially the same code is in 
pci_setup_device(), file drivers/pci/probe.c

I'm afraid I'm a wrong person to continue this discussion.  I have to 
choose what I'm working on.  Otherwise I spend too much time and make too 
many errors.

-- 
Regards,
Pavel Roskin



From proski at gnu.org  Wed May 14 19:48:19 2003
From: proski at gnu.org (Pavel Roskin)
Date: Wed May 14 23:48:19 2003
Subject: [PATCH] validate_mem without CONFIG_ISA - 2.4.x backport
In-Reply-To: <Pine.LNX.4.55.0304211234350.15138@marabou.research.att.com>
References: <Pine.LNX.4.55.0304211234350.15138@marabou.research.att.com>
Message-ID: <Pine.LNX.4.55.0305141843260.11636@marabou.research.att.com>

Hello!

My patch to fix a crash in validate_mem() without CONFIG_ISA defined
(http://lists.infradead.org/pipermail/linux-pcmcia/2003-April/000039.html)
needs to be applied to 2.4.x kernels as well.  The patch against
2.4.21-rc2-ac2 is attached.

Can anybody apply or forward the patch or I should send it in Marcelo
and/or Alan myself?

-- 
Regards,
Pavel Roskin-------------- next part --------------
--- linux.orig/drivers/pcmcia/rsrc_mgr.c
+++ linux/drivers/pcmcia/rsrc_mgr.c
@@ -419,14 +419,17 @@ void validate_mem(int (*is_valid)(u_long
 void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
 		  int force_low, socket_info_t *s)
 {
-    resource_map_t *m;
+    resource_map_t *m, *n;
     static int done = 0;
     
     if (!probe_mem || done++)
 	return;
-    for (m = mem_db.next; m != &mem_db; m = m->next)
+
+    for (m = mem_db.next; m != &mem_db; m = n) {
+	n = m->next;
 	if (do_mem_probe(m->base, m->num, is_valid, do_cksum, s))
 	    return;
+    }
 }
 
 #endif /* CONFIG_ISA */
From rmk at arm.linux.org.uk  Thu May 15 00:57:28 2003
From: rmk at arm.linux.org.uk (Russell King)
Date: Wed May 14 23:57:26 2003
Subject: [PATCH] validate_mem without CONFIG_ISA - 2.4.x backport
In-Reply-To: <Pine.LNX.4.55.0305141843260.11636@marabou.research.att.com>;
	from proski@gnu.org on Wed, May 14, 2003 at 06:48:19PM -0400
References: <Pine.LNX.4.55.0304211234350.15138@marabou.research.att.com>
	<Pine.LNX.4.55.0305141843260.11636@marabou.research.att.com>
Message-ID: <20030514235728.A5453@flint.arm.linux.org.uk>

On Wed, May 14, 2003 at 06:48:19PM -0400, Pavel Roskin wrote:
> Hello!
> 
> My patch to fix a crash in validate_mem() without CONFIG_ISA defined
> (http://lists.infradead.org/pipermail/linux-pcmcia/2003-April/000039.html)
> needs to be applied to 2.4.x kernels as well.  The patch against
> 2.4.21-rc2-ac2 is attached.
> 
> Can anybody apply or forward the patch or I should send it in Marcelo
> and/or Alan myself?

Please send it to Alan and/or Marcelo.  I'm not looking after the 2.4
code.

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


From linux at brodo.de  Sat May 17 23:12:18 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sat May 17 21:19:01 2003
Subject: patches follow, and re kill register_pccard_drivers patch
Message-ID: <20030517201218.GA1749@brodo.de>

A couple of PCMCIA-related patches will follow. Sorry for the delay. But now
they seem to be working.

And Russell: What's your opinion about Christoph Hellwig's "kill
register_pccard_driver" patch? I'd like to see it merged ASAP.

	Dominik
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030517/23fa4bce/attachment.bin
From linux at brodo.de  Sat May 17 23:13:27 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sat May 17 21:19:08 2003
Subject: [PATCH] pcmcia: split socket initialization
Message-ID: <20030517201327.GC1749@brodo.de>

Split up the socket initialization in cs.c into two pieces:

	pcmcia_register_socket / pcmcia_unregister_socket 
will focus on registering sockets with the device core in future, set
all necessary fields etc.

	pcmcia_add_socket / pcmcia_remove_socket 
will use an interface to the device class "pcmcia_socket_class" in
future, and mainly take care of what initialization cs.c needs to work
properly.

	The actual "work" will be done in the next patch -- this one
only shuffles code around.

 drivers/pcmcia/cs.c |  160 +++++++++++++++++++++++++++++-----------------------
 include/pcmcia/ss.h |    1
 2 files changed, 93 insertions(+), 68 deletions(-)

diff -ruN linux-original/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- linux-original/drivers/pcmcia/cs.c	2003-05-17 20:57:56.000000000 +0200
+++ linux/drivers/pcmcia/cs.c	2003-05-17 20:56:37.000000000 +0200
@@ -322,6 +322,90 @@
 }
 
 
+static int pcmcia_add_socket(struct pcmcia_socket *socket)
+{
+	socket_info_t *s;
+	int ret;
+
+	s = (socket_info_t *) socket->s_info;
+	/* socket initialization */
+	s->ss_entry = socket->ops;
+	s->sock = socket->socket_no;
+
+	/* base address = 0, map = 0 */
+	s->cis_mem.flags = 0;
+	s->cis_mem.speed = cis_speed;
+	s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
+	INIT_LIST_HEAD(&s->cis_cache);
+	spin_lock_init(&s->lock);
+
+	init_socket(s);
+	s->ss_entry->inquire_socket(s->sock, &s->cap);
+
+	init_completion(&s->thread_done);
+	init_waitqueue_head(&s->thread_wait);
+	init_MUTEX(&s->skt_sem);
+	spin_lock_init(&s->thread_lock);
+	ret = kernel_thread(pccardd, s, CLONE_KERNEL);
+	if (ret < 0) {
+		/* pcmcia_unregister_socket(class_dev); */
+		return ret;
+	}
+
+	wait_for_completion(&s->thread_done);
+	BUG_ON(!s->thread);
+
+#ifdef CONFIG_PROC_FS
+	if (proc_pccard) {
+		char name[3];
+		sprintf(name, "%02d", s->sock);
+		s->proc = proc_mkdir(name, proc_pccard);
+		if (s->proc)
+			s->ss_entry->proc_setup(s->sock, s->proc);
+#ifdef PCMCIA_DEBUG
+		if (s->proc)
+			create_proc_read_entry("clients", 0, s->proc,
+					       proc_read_clients, s);
+#endif
+	}
+#endif
+	return 0;
+}
+
+
+static void pcmcia_remove_socket(struct pcmcia_socket *socket)
+{
+	client_t *client;
+	socket_info_t *s;
+
+	s = (socket_info_t *) socket->s_info;
+
+#ifdef CONFIG_PROC_FS
+	if (proc_pccard) {
+		char name[3];
+		sprintf(name, "%02d", s->sock);
+#ifdef PCMCIA_DEBUG
+		remove_proc_entry("clients", s->proc);
+#endif
+		remove_proc_entry(name, proc_pccard);
+	}
+#endif
+	if (s->thread) {
+		init_completion(&s->thread_done);
+		s->thread = NULL;
+		wake_up(&s->thread_wait);
+		wait_for_completion(&s->thread_done);
+	}
+	release_cis_mem(s);
+	while (s->clients) {
+		client = s->clients;
+		s->clients = s->clients->next;
+		kfree(client);
+	}
+	s->ss_entry = NULL;
+}
+
+
 /**
  * pcmcia_register_socket - add a new pcmcia socket device
  */
@@ -347,59 +431,20 @@
 
 	/* socket initialization */
 	for (i = 0; i < cls_d->nsock; i++) {
-		socket_info_t *s = &s_info[i];
-
-		s->ss_entry = cls_d->ops;
-		s->sock = i + cls_d->sock_offset;
-
-		/* base address = 0, map = 0 */
-		s->cis_mem.flags = 0;
-		s->cis_mem.speed = cis_speed;
-		s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
-		INIT_LIST_HEAD(&s->cis_cache);
-		spin_lock_init(&s->lock);
-
 		socket = kmalloc(sizeof(struct pcmcia_socket), GFP_KERNEL);
 		if (!socket)
 			return -ENOMEM;
 		memset(socket, 0, sizeof(struct pcmcia_socket));
 
-		socket->s_info = (void *) s;
-		socket->socket_no = s->sock;
+		socket->s_info = (void *) &s_info[i];
+		socket->socket_no = i + cls_d->sock_offset;
+		socket->ops = cls_d->ops;
+
 		down(&pcmcia_socket_list_lock);
 		list_add_tail(&socket->socket_list, &pcmcia_socket_list);
 		up(&pcmcia_socket_list_lock);
 
-		init_socket(s);
-		s->ss_entry->inquire_socket(s->sock, &s->cap);
-
-		init_completion(&s->thread_done);
-		init_waitqueue_head(&s->thread_wait);
-		init_MUTEX(&s->skt_sem);
-		spin_lock_init(&s->thread_lock);
-		ret = kernel_thread(pccardd, s, CLONE_KERNEL);
-		if (ret < 0) {
-			pcmcia_unregister_socket(class_dev);
-			break;
-		}
-
-		wait_for_completion(&s->thread_done);
-		BUG_ON(!s->thread);
-
-#ifdef CONFIG_PROC_FS
-		if (proc_pccard) {
-			char name[3];
-			sprintf(name, "%02d", s->sock);
-			s->proc = proc_mkdir(name, proc_pccard);
-			if (s->proc)
-				s->ss_entry->proc_setup(i, s->proc);
-#ifdef PCMCIA_DEBUG
-			if (s->proc)
-				create_proc_read_entry("clients", 0, s->proc,
-				       proc_read_clients, s);
-#endif
-		}
-#endif
+		pcmcia_add_socket(socket);
 	}
 	return ret;
 } /* pcmcia_register_socket */
@@ -413,7 +458,6 @@
  	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
 	struct pcmcia_socket *socket;
 	unsigned int i;
-	client_t *client;
 	socket_info_t *s;
 
 	if (!cls_d)
@@ -433,29 +477,9 @@
 	found:
 		up(&pcmcia_socket_list_lock);
 
-#ifdef CONFIG_PROC_FS
-		if (proc_pccard) {
-			char name[3];
-			sprintf(name, "%02d", s->sock);
-#ifdef PCMCIA_DEBUG
-			remove_proc_entry("clients", s->proc);
-#endif
-			remove_proc_entry(name, proc_pccard);
-		}
-#endif
-		if (s->thread) {
-			init_completion(&s->thread_done);
-			s->thread = NULL;
-			wake_up(&s->thread_wait);
-			wait_for_completion(&s->thread_done);
-		}
-		release_cis_mem(s);
-		while (s->clients) {
-			client = s->clients;
-			s->clients = s->clients->next;
-			kfree(client);
-		}
-		s->ss_entry = NULL;
+
+		pcmcia_remove_socket(socket);
+
 		down(&pcmcia_socket_list_lock);
 		list_del(&socket->socket_list);
 		up(&pcmcia_socket_list_lock);
diff -ruN linux-original/include/pcmcia/ss.h linux/include/pcmcia/ss.h
--- linux-original/include/pcmcia/ss.h	2003-05-17 20:57:56.000000000 +0200
+++ linux/include/pcmcia/ss.h	2003-05-17 20:52:59.000000000 +0200
@@ -144,6 +144,7 @@
 
 struct pcmcia_socket {
 	struct list_head		socket_list;
+	struct pccard_operations	*ops;
 
 	/* deprecated */
 	unsigned int			socket_no;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030517/4e7d2be3/attachment.bin
From linux at brodo.de  Sat May 17 23:12:59 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sat May 17 21:19:10 2003
Subject: [PATCH] pcmcia: remove socket_table
Message-ID: <20030517201259.GB1749@brodo.de>

This patch removes the socket_table from cs.c and friends. A new
struct pcmcia_socket is introduced which will serve as main argument
on calls between cs.c and the socket drivers, and cs.c and other users
like ds.c .

 drivers/pcmcia/bulkmem.c     |    2
 drivers/pcmcia/cs.c          |  128 ++++++++++++++++++++++++++-----------------
 drivers/pcmcia/cs_internal.h |   11 +--
 drivers/pcmcia/rsrc_mgr.c    |   10 ++-
 include/pcmcia/ss.h          |    8 ++
 5 files changed, 99 insertions(+), 60 deletions(-)

diff -ruN linux-original/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c
--- linux-original/drivers/pcmcia/bulkmem.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/bulkmem.c	2003-05-17 19:39:01.000000000 +0200
@@ -538,7 +538,7 @@
     
     if ((handle == NULL) || CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
-    s = SOCKET(*handle);
+    s = get_s_info_by_nr((*handle)->Socket);
     if (open->Attributes & MEMORY_TYPE_AM)
 	region = s->a_region;
     else
diff -ruN linux-original/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- linux-original/drivers/pcmcia/cs.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/cs.c	2003-05-17 20:36:53.000000000 +0200
@@ -123,9 +123,9 @@
     0, SS_DETECT, 0, 0, 0
 };
 
-/* Table of sockets */
-socket_t sockets = 0;
-socket_info_t *socket_table[MAX_SOCK];
+/* list of sockets */
+LIST_HEAD(pcmcia_socket_list);
+DECLARE_MUTEX(pcmcia_socket_list_lock);
 
 #ifdef CONFIG_PROC_FS
 struct proc_dir_entry *proc_pccard = NULL;
@@ -307,6 +307,21 @@
 
 #define to_class_data(dev) dev->class_data
 
+socket_info_t * get_s_info_by_nr(unsigned int s_nr)
+{
+	struct pcmcia_socket *tmp;
+	down(&pcmcia_socket_list_lock);
+	list_for_each_entry(tmp, &pcmcia_socket_list, socket_list) {
+		if (tmp->socket_no == s_nr) {
+			up(&pcmcia_socket_list_lock);
+			return ((socket_info_t *) tmp->s_info);
+		}
+	}
+	up(&pcmcia_socket_list_lock);
+	return NULL;
+}
+
+
 /**
  * pcmcia_register_socket - add a new pcmcia socket device
  */
@@ -314,7 +329,8 @@
 {
 	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
 	socket_info_t *s_info;
-	unsigned int i, j, ret;
+	unsigned int i, ret;
+	struct pcmcia_socket *socket;
 
 	if (!cls_d)
 		return -EINVAL;
@@ -343,11 +359,16 @@
 		INIT_LIST_HEAD(&s->cis_cache);
 		spin_lock_init(&s->lock);
 
-		/* TBD: remove usage of socket_table, use class_for_each_dev instead */
-		for (j = 0; j < sockets; j++)
-			if (socket_table[j] == NULL) break;
-		socket_table[j] = s;
-		if (j == sockets) sockets++;
+		socket = kmalloc(sizeof(struct pcmcia_socket), GFP_KERNEL);
+		if (!socket)
+			return -ENOMEM;
+		memset(socket, 0, sizeof(struct pcmcia_socket));
+
+		socket->s_info = (void *) s;
+		socket->socket_no = s->sock;
+		down(&pcmcia_socket_list_lock);
+		list_add_tail(&socket->socket_list, &pcmcia_socket_list);
+		up(&pcmcia_socket_list_lock);
 
 		init_socket(s);
 		s->ss_entry->inquire_socket(s->sock, &s->cap);
@@ -368,7 +389,7 @@
 #ifdef CONFIG_PROC_FS
 		if (proc_pccard) {
 			char name[3];
-			sprintf(name, "%02d", j);
+			sprintf(name, "%02d", s->sock);
 			s->proc = proc_mkdir(name, proc_pccard);
 			if (s->proc)
 				s->ss_entry->proc_setup(i, s->proc);
@@ -389,9 +410,9 @@
  */
 void pcmcia_unregister_socket(struct class_device *class_dev)
 {
-	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
+ 	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
+	struct pcmcia_socket *socket;
 	unsigned int i;
-	int j, socket = -1;
 	client_t *client;
 	socket_info_t *s;
 
@@ -401,18 +422,21 @@
 	s = (socket_info_t *) cls_d->s_info;
 
 	for (i = 0; i < cls_d->nsock; i++) {
-		for (j = 0; j < MAX_SOCK; j++)
-			if (socket_table [j] == s) {
-				socket = j;
-				break;
-			}
-		if (socket < 0)
-			continue;
-		
+		down(&pcmcia_socket_list_lock);
+		list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+			if (socket->s_info == s)
+				goto found;
+		}
+		up(&pcmcia_socket_list_lock);
+		continue;
+
+	found:
+		up(&pcmcia_socket_list_lock);
+
 #ifdef CONFIG_PROC_FS
 		if (proc_pccard) {
 			char name[3];
-			sprintf(name, "%02d", socket);
+			sprintf(name, "%02d", s->sock);
 #ifdef PCMCIA_DEBUG
 			remove_proc_entry("clients", s->proc);
 #endif
@@ -432,10 +456,9 @@
 			kfree(client);
 		}
 		s->ss_entry = NULL;
-		socket_table[socket] = NULL;
-		for (j = socket; j < sockets-1; j++)
-			socket_table[j] = socket_table[j+1];
-		sockets--;
+		down(&pcmcia_socket_list_lock);
+		list_del(&socket->socket_list);
+		up(&pcmcia_socket_list_lock);
 
 		s++;
 	}
@@ -1018,9 +1041,9 @@
     client_t *client;
     socket_info_t *s;
 
-    if (CHECK_SOCKET(req->Socket))
-	return CS_BAD_SOCKET;
     s = SOCKET(req);
+    if (!s)
+	    return CS_BAD_SOCKET;
 
     client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL);
     if (!client) return CS_OUT_OF_RESOURCE;
@@ -1054,9 +1077,9 @@
     socket_info_t *s;
     memory_handle_t region;
     
-    if (CHECK_SOCKET(req->Socket))
-	return CS_BAD_SOCKET;
     s = SOCKET(req);
+    if (!s)
+	return CS_BAD_SOCKET;
     
     if (req->Attributes & REGION_TYPE_AM)
 	region = s->a_region;
@@ -1105,7 +1128,7 @@
 	    if (region->mtd == handle) region->mtd = NULL;
     }
     
-    sn = handle->Socket; s = socket_table[sn];
+    sn = handle->Socket; s = get_s_info_by_nr(sn);
 
     if ((handle->state & CLIENT_STALE) ||
 	(handle->Attributes & INFO_MASTER_CLIENT)) {
@@ -1208,9 +1231,15 @@
 
 int pcmcia_get_card_services_info(servinfo_t *info)
 {
+    unsigned int socket_count = 0;
+    struct list_head *tmp;
     info->Signature[0] = 'C';
     info->Signature[1] = 'S';
-    info->Count = sockets;
+    down(&pcmcia_socket_list_lock);
+    list_for_each(tmp, &pcmcia_socket_list)
+	    socket_count++;
+    up(&pcmcia_socket_list_lock);
+    info->Count = socket_count;
     info->Revision = CS_RELEASE_CODE;
     info->CSLevel = 0x0210;
     info->VendorString = (char *)release;
@@ -1227,15 +1256,17 @@
 int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
 {
     socket_t s;
+    socket_info_t *socket;
     if (req->Attributes & CLIENT_THIS_SOCKET)
 	s = req->Socket;
     else
 	s = 0;
-    if (CHECK_SOCKET(req->Socket))
+    socket = get_s_info_by_nr(s);
+    if (!socket)
 	return CS_BAD_SOCKET;
-    if (socket_table[s]->clients == NULL)
+    if (socket->clients == NULL)
 	return CS_NO_MORE_ITEMS;
-    *handle = socket_table[s]->clients;
+    *handle = socket->clients;
     return CS_SUCCESS;
 } /* get_first_client */
 
@@ -1249,7 +1280,7 @@
     if ((*handle)->next == NULL) {
 	if (req->Attributes & CLIENT_THIS_SOCKET)
 	    return CS_NO_MORE_ITEMS;
-	s = SOCKET(*handle);
+	s = get_s_info_by_nr((*handle)->Socket);
 	if (s->clients == NULL)
 	    return CS_NO_MORE_ITEMS;
 	*handle = s->clients;
@@ -1267,7 +1298,7 @@
     int w;
 
     if (idx == 0)
-	s = SOCKET((client_handle_t)*handle);
+	s = get_s_info_by_nr(((client_handle_t)*handle)->Socket);
     else
 	s = (*handle)->sock;
     if (!(s->state & SOCKET_PRESENT))
@@ -1518,14 +1549,15 @@
 
 int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
 {
-    client_t *client;
-    socket_info_t *s;
-    socket_t ns;
+    struct pcmcia_socket *socket;
+    client_t *client = NULL;
+    socket_info_t *s = NULL;
     
     /* Look for unbound client with matching dev_info */
-    client = NULL;
-    for (ns = 0; ns < sockets; ns++) {
-	client = socket_table[ns]->clients;
+    down(&pcmcia_socket_list_lock);
+    list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+	s = (socket_info_t *) socket->s_info;
+	client = s->clients;
 	while (client != NULL) {
 	    if ((strcmp(client->dev_info, (char *)req->dev_info) == 0)
 		&& (client->state & CLIENT_UNBOUND)) break;
@@ -1533,10 +1565,10 @@
 	}
 	if (client != NULL) break;
     }
+    up(&pcmcia_socket_list_lock);
     if (client == NULL)
 	return CS_OUT_OF_RESOURCE;
 
-    s = socket_table[ns];
     if (++s->real_clients == 1) {
 	register_callback(s, &parse_events, s);
 	parse_events(s, SS_DETECT);
@@ -1544,7 +1576,7 @@
 
     *handle = client;
     client->state &= ~CLIENT_UNBOUND;
-    client->Socket = ns;
+    client->Socket = socket->socket_no;
     client->Attributes = req->Attributes;
     client->EventMask = req->EventMask;
     client->event_handler = req->event_handler;
@@ -1573,8 +1605,8 @@
 	  client, client->Socket, client->dev_info);
     if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
 	EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
-    if ((socket_table[ns]->state & SOCKET_PRESENT) &&
-	!(socket_table[ns]->state & SOCKET_SETUP_PENDING)) {
+    if ((s->state & SOCKET_PRESENT) &&
+	!(s->state & SOCKET_SETUP_PENDING)) {
 	if (client->EventMask & CS_EVENT_CARD_INSERTION)
 	    EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
 	else
@@ -1745,7 +1777,7 @@
     
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
-    i = handle->Socket; s = socket_table[i];
+    i = handle->Socket; s = get_s_info_by_nr(i);
     if (!(s->state & SOCKET_PRESENT))
 	return CS_NO_CARD;
     
@@ -2014,7 +2046,7 @@
     
     if (CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
-    s = SOCKET(*handle);
+    s = get_s_info_by_nr((*handle)->Socket);
     if (!(s->state & SOCKET_PRESENT))
 	return CS_NO_CARD;
     if (req->Attributes & (WIN_PAGED | WIN_SHARED))
diff -ruN linux-original/drivers/pcmcia/cs_internal.h linux/drivers/pcmcia/cs_internal.h
--- linux-original/drivers/pcmcia/cs_internal.h	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/cs_internal.h	2003-05-17 20:39:52.000000000 +0200
@@ -184,10 +184,8 @@
 #define CHECK_HANDLE(h) \
     (((h) == NULL) || ((h)->client_magic != CLIENT_MAGIC))
 
-#define CHECK_SOCKET(s) \
-    (((s) >= sockets) || (socket_table[s]->ss_entry == NULL))
-
-#define SOCKET(h) (socket_table[(h)->Socket])
+socket_info_t * get_s_info_by_nr(unsigned int socket);
+#define SOCKET(h) (get_s_info_by_nr(h->Socket))
 #define CONFIG(h) (&SOCKET(h)->config[(h)->Function])
 
 #define CHECK_REGION(r) \
@@ -250,9 +248,8 @@
 int proc_read_mem(char *buf, char **start, off_t pos,
 		  int count, int *eof, void *data);
 
-#define MAX_SOCK 8
-extern socket_t sockets;
-extern socket_info_t *socket_table[MAX_SOCK];
+extern struct semaphore pcmcia_socket_list_lock;
+extern struct list_head pcmcia_socket_list;
 
 #ifdef CONFIG_PROC_FS
 extern struct proc_dir_entry *proc_pccard;
diff -ruN linux-original/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- linux-original/drivers/pcmcia/rsrc_mgr.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/rsrc_mgr.c	2003-05-17 19:39:15.000000000 +0200
@@ -726,7 +726,7 @@
 static int adjust_memory(adjust_t *adj)
 {
     u_long base, num;
-    int i, ret;
+    int ret;
 
     base = adj->resource.memory.Base;
     num = adj->resource.memory.Size;
@@ -743,9 +743,11 @@
     case REMOVE_MANAGED_RESOURCE:
 	ret = sub_interval(&mem_db, base, num);
 	if (ret == CS_SUCCESS) {
-	    for (i = 0; i < sockets; i++) {
-		release_cis_mem(socket_table[i]);
-	    }
+		struct pcmcia_socket *tmp;
+		down(&pcmcia_socket_list_lock);
+		list_for_each_entry(tmp, &pcmcia_socket_list, socket_list)
+			release_cis_mem(tmp->s_info);
+		up(&pcmcia_socket_list_lock);
 	}
 	break;
     default:
diff -ruN linux-original/include/pcmcia/ss.h linux/include/pcmcia/ss.h
--- linux-original/include/pcmcia/ss.h	2003-05-17 18:27:29.000000000 +0200
+++ linux/include/pcmcia/ss.h	2003-05-17 19:39:26.000000000 +0200
@@ -142,6 +142,14 @@
  *  Calls to set up low-level "Socket Services" drivers
  */
 
+struct pcmcia_socket {
+	struct list_head		socket_list;
+
+	/* deprecated */
+	unsigned int			socket_no;
+	void				*s_info; /* socket_info_t */
+};
+
 struct pcmcia_socket_class_data {
 	unsigned int nsock;			/* number of sockets */
 	unsigned int sock_offset;		/* socket # (which is
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030517/c807501f/attachment.bin
From linux at brodo.de  Sat May 17 23:16:03 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sat May 17 21:19:13 2003
Subject: [PATCH] pcmcia: socket callbacks now use "struct pcmcia_socket"
Message-ID: <20030517201603.GE1749@brodo.de>

Passing a "socket number" between the core and the socket drivers is
awful. Change it to "struct pcmcia_socket" (which will be filled with
more life later).

 drivers/pcmcia/bulkmem.c     |    6 +++---
 drivers/pcmcia/cistpl.c      |    4 ++--
 drivers/pcmcia/cs.c          |   30 ++++++++++++++----------------
 drivers/pcmcia/cs_internal.h |    3 +--
 drivers/pcmcia/i82092.c      |   36 +++++++++++++++++++++++-------------
 drivers/pcmcia/i82092aa.h    |   20 ++++++++++----------
 drivers/pcmcia/i82365.c      |   34 +++++++++++++++++++++++-----------
 drivers/pcmcia/pci_socket.c  |   40 ++++++++++++++++++++--------------------
 drivers/pcmcia/rsrc_mgr.c    |    2 +-
 drivers/pcmcia/tcic.c        |   35 ++++++++++++++++++-----------------
 include/pcmcia/ss.h          |   22 ++++++++++++----------
 11 files changed, 127 insertions(+), 105 deletions(-)


diff -ruN linux-original/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c
--- linux-original/drivers/pcmcia/bulkmem.c	2003-05-17 20:57:56.000000000 +0200
+++ linux/drivers/pcmcia/bulkmem.c	2003-05-17 21:39:27.000000000 +0200
@@ -259,7 +259,7 @@
 	win->ctl.flags |= MAP_ATTRIB;
     win->ctl.speed = req->AccessSpeed;
     win->ctl.card_start = req->CardOffset;
-    win->sock->ss_entry->set_mem_map(win->sock->sock, &win->ctl);
+    win->sock->sock->ops->set_mem_map(win->sock->sock, &win->ctl);
     return CS_SUCCESS;
 }
 
@@ -272,7 +272,7 @@
 	return CS_BAD_VPP;
     s = SOCKET(handle);
     s->socket.Vpp = req->Vpp1;
-    if (s->ss_entry->set_socket(s->sock, &s->socket))
+    if (s->sock->ops->set_socket(s->sock, &s->socket))
 	return CS_BAD_VPP;
     return CS_SUCCESS;
 }
@@ -287,7 +287,7 @@
 	s->socket.csc_mask |= SS_READY;
     else
 	s->socket.csc_mask &= ~SS_READY;
-    if (s->ss_entry->set_socket(s->sock, &s->socket))
+    if (s->sock->ops->set_socket(s->sock, &s->socket))
 	return CS_GENERAL_FAILURE;
     return CS_SUCCESS;
 }
diff -ruN linux-original/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c
--- linux-original/drivers/pcmcia/cistpl.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/cistpl.c	2003-05-17 21:39:27.000000000 +0200
@@ -86,7 +86,7 @@
 {
     if (s->cis_mem.sys_start != 0) {
 	s->cis_mem.flags &= ~MAP_ACTIVE;
-	s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
+	s->sock->ops->set_mem_map(s->sock, &s->cis_mem);
 	if (!(s->cap.features & SS_CAP_STATIC_MAP))
 	    release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
 	iounmap(s->cis_virt);
@@ -119,7 +119,7 @@
     }
     mem->card_start = card_offset;
     mem->flags = flags;
-    s->ss_entry->set_mem_map(s->sock, mem);
+    s->sock->ops->set_mem_map(s->sock, mem);
     if (s->cap.features & SS_CAP_STATIC_MAP) {
 	if (s->cis_virt)
 	    iounmap(s->cis_virt);
diff -ruN linux-original/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- linux-original/drivers/pcmcia/cs.c	2003-05-17 22:03:15.000000000 +0200
+++ linux/drivers/pcmcia/cs.c	2003-05-17 21:39:27.000000000 +0200
@@ -238,44 +238,44 @@
 {
 	int error;
 
-	if (handler && !try_module_get(s->ss_entry->owner))
+	if (handler && !try_module_get(s->sock->ops->owner))
 		return -ENODEV;
-	error = s->ss_entry->register_callback(s->sock, handler, info);
+	error = s->sock->ops->register_callback(s->sock, handler, info);
 	if (!handler)
-		module_put(s->ss_entry->owner);
+		module_put(s->sock->ops->owner);
 	return error;
 }
 
 static int get_socket_status(socket_info_t *s, int *val)
 {
-	return s->ss_entry->get_status(s->sock, val);
+	return s->sock->ops->get_status(s->sock, val);
 }
 
 static int set_socket(socket_info_t *s, socket_state_t *state)
 {
-	return s->ss_entry->set_socket(s->sock, state);
+	return s->sock->ops->set_socket(s->sock, state);
 }
 
 static int set_io_map(socket_info_t *s, struct pccard_io_map *io)
 {
-	return s->ss_entry->set_io_map(s->sock, io);
+	return s->sock->ops->set_io_map(s->sock, io);
 }
 
 static int set_mem_map(socket_info_t *s, struct pccard_mem_map *mem)
 {
-	return s->ss_entry->set_mem_map(s->sock, mem);
+	return s->sock->ops->set_mem_map(s->sock, mem);
 }
 
 static int suspend_socket(socket_info_t *s)
 {
 	s->socket = dead_socket;
-	return s->ss_entry->suspend(s->sock);
+	return s->sock->ops->suspend(s->sock);
 }
 
 static int init_socket(socket_info_t *s)
 {
 	s->socket = dead_socket;
-	return s->ss_entry->init(s->sock);
+	return s->sock->ops->init(s->sock);
 }
 
 /*====================================================================*/
@@ -385,8 +385,7 @@
 	int ret;
 	s = (socket_info_t *) socket->s_info;
 	/* socket initialization */
-	s->ss_entry = socket->ops;
-	s->sock = socket->socket_no;
+	s->sock = socket;
 
 	/* base address = 0, map = 0 */
 	s->cis_mem.flags = 0;
@@ -396,7 +395,7 @@
 	spin_lock_init(&s->lock);
 
 	init_socket(s);
-	s->ss_entry->inquire_socket(s->sock, &s->cap);
+	socket->ops->inquire_socket(socket, &s->cap);
 
 	init_completion(&s->thread_done);
 	init_waitqueue_head(&s->thread_wait);
@@ -414,10 +413,10 @@
 #ifdef CONFIG_PROC_FS
 	if (proc_pccard) {
 		char name[3];
-		sprintf(name, "%02d", s->sock);
+		sprintf(name, "%02d", socket->socket_no);
 		s->proc = proc_mkdir(name, proc_pccard);
 		if (s->proc)
-			s->ss_entry->proc_setup(s->sock, s->proc);
+			socket->ops->proc_setup(socket, s->proc);
 #ifdef PCMCIA_DEBUG
 		if (s->proc)
 			create_proc_read_entry("clients", 0, s->proc,
@@ -440,7 +439,7 @@
 #ifdef CONFIG_PROC_FS
 	if (proc_pccard) {
 		char name[3];
-		sprintf(name, "%02d", s->sock);
+		sprintf(name, "%02d", socket->socket_no);
 #ifdef PCMCIA_DEBUG
 		remove_proc_entry("clients", s->proc);
 #endif
@@ -459,7 +458,6 @@
 		s->clients = s->clients->next;
 		kfree(client);
 	}
-	s->ss_entry = NULL;
 }
 
 
diff -ruN linux-original/drivers/pcmcia/cs_internal.h linux/drivers/pcmcia/cs_internal.h
--- linux-original/drivers/pcmcia/cs_internal.h	2003-05-17 20:57:56.000000000 +0200
+++ linux/drivers/pcmcia/cs_internal.h	2003-05-17 21:39:27.000000000 +0200
@@ -124,8 +124,7 @@
 
 typedef struct socket_info_t {
     spinlock_t			lock;
-    struct pccard_operations *	ss_entry;
-    u_int			sock;
+    struct pcmcia_socket *	sock;
     socket_state_t		socket;
     socket_cap_t		cap;
     u_int			state;
diff -ruN linux-original/drivers/pcmcia/i82092.c linux/drivers/pcmcia/i82092.c
--- linux-original/drivers/pcmcia/i82092.c	2003-05-17 22:03:15.000000000 +0200
+++ linux/drivers/pcmcia/i82092.c	2003-05-17 21:49:24.000000000 +0200
@@ -80,6 +80,7 @@
 /* The card can do upto 4 sockets, allocate a structure for each of them */
 
 struct socket_info {
+	int	number;
 	int	card_state; 	/*  0 = no socket,
 				    1 = empty socket, 
 				    2 = card but not initialized,
@@ -144,6 +145,8 @@
 		sockets[i].cap.map_size = 0x1000;
 		sockets[i].cap.irq_mask = 0;
 		sockets[i].cap.pci_irq  = dev->irq;
+
+		sockets[i].number = i;
 		
 		if (card_present(i)) {
 			sockets[i].card_state = 3;
@@ -443,7 +446,7 @@
 
 
       
-static int i82092aa_init(unsigned int s)
+static int i82092aa_init(struct pcmcia_socket *sock)
 {
 	int i;
         pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -452,21 +455,21 @@
         enter("i82092aa_init");
                         
         mem.sys_stop = 0x0fff;
-        i82092aa_set_socket(s, &dead_socket);
+        i82092aa_set_socket(sock, &dead_socket);
         for (i = 0; i < 2; i++) {
         	io.map = i;
-                i82092aa_set_io_map(s, &io);
+                i82092aa_set_io_map(sock, &io);
 	}
         for (i = 0; i < 5; i++) {
         	mem.map = i;
-                i82092aa_set_mem_map(s, &mem);
+                i82092aa_set_mem_map(sock, &mem);
 	}
 	
 	leave("i82092aa_init");
 	return 0;
 }
                                                                                                                                                                                                                                               
-static int i82092aa_suspend(unsigned int sock)
+static int i82092aa_suspend(struct pcmcia_socket *sock)
 {
 	int retval;
 	enter("i82092aa_suspend");
@@ -475,8 +478,9 @@
         return retval;
 }
        
-static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	enter("i82092aa_register_callback");
 	sockets[sock].handler = handler;
         sockets[sock].info = info;
@@ -484,8 +488,9 @@
 	return 0;
 } /* i82092aa_register_callback */
                                         
-static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int i82092aa_inquire_socket(struct pcmcia_socket *socket, socket_cap_t *cap)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	enter("i82092aa_inquire_socket");
 	*cap = sockets[sock].cap;
 	leave("i82092aa_inquire_socket");
@@ -493,8 +498,9 @@
 } /* i82092aa_inquire_socket */
 
 
-static int i82092aa_get_status(unsigned int sock, u_int *value)
+static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned int status;
 	
 	enter("i82092aa_get_status");
@@ -535,8 +541,9 @@
 }
 
 
-static int i82092aa_get_socket(unsigned int sock, socket_state_t *state) 
+static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state) 
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned char reg,vcc,vpp;
 	
 	enter("i82092aa_get_socket");
@@ -606,8 +613,9 @@
 	return 0;
 }
 
-static int i82092aa_set_socket(unsigned int sock, socket_state_t *state) 
+static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) 
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned char reg;
 	
 	enter("i82092aa_set_socket");
@@ -702,8 +710,9 @@
 	return 0;
 }
 
-static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io)
+static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned char map, ioctl;
 	
 	enter("i82092aa_set_io_map");
@@ -745,8 +754,9 @@
 	return 0;
 }
 
-static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem)
+static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned short base, i;
 	unsigned char map;
 	
@@ -822,7 +832,7 @@
 	return 0;
 }
 
-static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void i82092aa_proc_setup(struct pcmcia_socket *socket, struct proc_dir_entry *base)
 {
 	
 }
diff -ruN linux-original/drivers/pcmcia/i82092aa.h linux/drivers/pcmcia/i82092aa.h
--- linux-original/drivers/pcmcia/i82092aa.h	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/i82092aa.h	2003-05-17 21:49:24.000000000 +0200
@@ -28,16 +28,16 @@
 
 
 
-static int i82092aa_get_status(unsigned int sock, u_int *value);
-static int i82092aa_get_socket(unsigned int sock, socket_state_t *state);
-static int i82092aa_set_socket(unsigned int sock, socket_state_t *state);
-static int i82092aa_set_io_map(unsigned int sock, struct pccard_io_map *io);
-static int i82092aa_set_mem_map(unsigned int sock, struct pccard_mem_map *mem);
-static int i82092aa_init(unsigned int s);
-static int i82092aa_suspend(unsigned int sock);
-static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info);
-static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap);
-static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base);
+static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value);
+static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state);
+static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state);
+static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io);
+static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem);
+static int i82092aa_init(struct pcmcia_socket *socket);
+static int i82092aa_suspend(struct pcmcia_socket *socket);
+static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info);
+static int i82092aa_inquire_socket(struct pcmcia_socket *socket, socket_cap_t *cap);
+static void i82092aa_proc_setup(struct pcmcia_socket *socket, struct proc_dir_entry *base);
 
 #endif
 
diff -ruN linux-original/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- linux-original/drivers/pcmcia/i82365.c	2003-05-17 22:03:15.000000000 +0200
+++ linux/drivers/pcmcia/i82365.c	2003-05-17 21:58:55.000000000 +0200
@@ -167,6 +167,7 @@
 typedef struct socket_info_t {
     u_short		type, flags;
     struct pcmcia_socket	socket;
+    unsigned int	number;
     socket_cap_t	cap;
     ioaddr_t		ioaddr;
     u_short		psock;
@@ -1014,8 +1015,9 @@
 
 /*====================================================================*/
 
-static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+static int pcic_register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
 {
+    unsigned int sock = container_of(s, struct socket_info_t, socket)->number;
     socket[sock].handler = handler;
     socket[sock].info = info;
     return 0;
@@ -1023,8 +1025,9 @@
 
 /*====================================================================*/
 
-static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int pcic_inquire_socket(struct pcmcia_socket *s, socket_cap_t *cap)
 {
+    unsigned int sock = container_of(s, struct socket_info_t, socket)->number;
     *cap = socket[sock].cap;
     return 0;
 } /* pcic_inquire_socket */
@@ -1371,9 +1374,9 @@
     return (p - buf);
 }
 
-static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void pcic_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
 {
-    socket_info_t *s = &socket[sock];
+    socket_info_t *s = container_of(sock, struct socket_info_t, socket);
 
     if (s->flags & IS_ALIVE)
     	return;
@@ -1421,8 +1424,10 @@
 #endif
 	
 
-static int pcic_get_status(unsigned int sock, u_int *value)
+static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
 {
+	unsigned int sock = container_of(s, struct socket_info_t, socket)->number;
+
 	if (socket[sock].flags & IS_ALIVE) {
 		*value = 0;
 		return -EINVAL;
@@ -1431,39 +1436,45 @@
 	LOCKED(i365_get_status(sock, value));
 }
 
-static int pcic_get_socket(unsigned int sock, socket_state_t *state)
+static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
+	unsigned int sock = container_of(s, struct socket_info_t, socket)->number;
+
 	if (socket[sock].flags & IS_ALIVE)
 		return -EINVAL;
 
 	LOCKED(i365_get_socket(sock, state));
 }
 
-static int pcic_set_socket(unsigned int sock, socket_state_t *state)
+static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
+	unsigned int sock = container_of(s, struct socket_info_t, socket)->number;
+
 	if (socket[sock].flags & IS_ALIVE)
 		return -EINVAL;
 
 	LOCKED(i365_set_socket(sock, state));
 }
 
-static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io)
+static int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
 {
+	unsigned int sock = container_of(s, struct socket_info_t, socket)->number;
 	if (socket[sock].flags & IS_ALIVE)
 		return -EINVAL;
 
 	LOCKED(i365_set_io_map(sock, io));
 }
 
-static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
 {
+	unsigned int sock = container_of(s, struct socket_info_t, socket)->number;
 	if (socket[sock].flags & IS_ALIVE)
 		return -EINVAL;
 
 	LOCKED(i365_set_mem_map(sock, mem));
 }
 
-static int pcic_init(unsigned int s)
+static int pcic_init(struct pcmcia_socket *s)
 {
 	int i;
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -1482,7 +1493,7 @@
 	return 0;
 }
 
-static int pcic_suspend(unsigned int sock)
+static int pcic_suspend(struct pcmcia_socket *sock)
 {
 	return pcic_set_socket(sock, &dead_socket);
 }
@@ -1558,6 +1569,7 @@
     for (i = 0; i < sockets; i++) {
 	    socket[i].socket.dev.dev = &i82365_device.dev;
 	    socket[i].socket.ops = &pcic_operations;
+	    socket[i].number = i;
 	    ret = pcmcia_register_socket(&socket[i].socket);	    
 	    if (ret && i--) {
 		    for (; i>= 0; i--)
diff -ruN linux-original/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c
--- linux-original/drivers/pcmcia/pci_socket.c	2003-05-17 22:03:15.000000000 +0200
+++ linux/drivers/pcmcia/pci_socket.c	2003-05-17 21:43:27.000000000 +0200
@@ -38,44 +38,44 @@
 #define MAX_SOCKETS (8)
 static pci_socket_t pci_socket_array[MAX_SOCKETS];
 
-static int pci_init_socket(unsigned int sock)
+static int pci_init_socket(struct pcmcia_socket *sock)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	if (socket->op && socket->op->init)
 		return socket->op->init(socket);
 	return -EINVAL;
 }
 
-static int pci_suspend_socket(unsigned int sock)
+static int pci_suspend_socket(struct pcmcia_socket *sock)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	if (socket->op && socket->op->suspend)
 		return socket->op->suspend(socket);
 	return -EINVAL;
 }
 
-static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+static int pci_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	socket->handler = handler;
 	socket->info = info;
 	return 0;
 }
 
-static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int pci_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	*cap = socket->cap;
 	return 0;
 }
 
-static int pci_get_status(unsigned int sock, unsigned int *value)
+static int pci_get_status(struct pcmcia_socket *sock, unsigned int *value)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	if (socket->op && socket->op->get_status)
 		return socket->op->get_status(socket, value);
@@ -83,45 +83,45 @@
 	return -EINVAL;
 }
 
-static int pci_get_socket(unsigned int sock, socket_state_t *state)
+static int pci_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	if (socket->op && socket->op->get_socket)
 		return socket->op->get_socket(socket, state);
 	return -EINVAL;
 }
 
-static int pci_set_socket(unsigned int sock, socket_state_t *state)
+static int pci_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	if (socket->op && socket->op->set_socket)
 		return socket->op->set_socket(socket, state);
 	return -EINVAL;
 }
 
-static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
+static int pci_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	if (socket->op && socket->op->set_io_map)
 		return socket->op->set_io_map(socket, io);
 	return -EINVAL;
 }
 
-static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+static int pci_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	if (socket->op && socket->op->set_mem_map)
 		return socket->op->set_mem_map(socket, mem);
 	return -EINVAL;
 }
 
-static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void pci_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
 {
-	pci_socket_t *socket = pci_socket_array + sock;
+	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
 
 	if (socket->op && socket->op->proc_setup)
 		socket->op->proc_setup(socket, base);
diff -ruN linux-original/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- linux-original/drivers/pcmcia/rsrc_mgr.c	2003-05-17 20:57:56.000000000 +0200
+++ linux/drivers/pcmcia/rsrc_mgr.c	2003-05-17 21:39:27.000000000 +0200
@@ -372,7 +372,7 @@
     s->cis_virt = ioremap(base, s->cap.map_size);
     s->cis_mem.card_start = 0;
     s->cis_mem.flags = MAP_ACTIVE;
-    s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
+    s->sock->ops->set_mem_map(s->sock, &s->cis_mem);
     /* Don't bother checking every word... */
     a = 0; b = -1;
     for (i = 0; i < s->cap.map_size; i += 44) {
diff -ruN linux-original/drivers/pcmcia/tcic.c linux/drivers/pcmcia/tcic.c
--- linux-original/drivers/pcmcia/tcic.c	2003-05-17 22:03:15.000000000 +0200
+++ linux/drivers/pcmcia/tcic.c	2003-05-17 22:02:15.000000000 +0200
@@ -642,18 +642,19 @@
 
 /*====================================================================*/
 
-static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info)
+static int tcic_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
 {
-    socket_table[lsock].handler = handler;
-    socket_table[lsock].info = info;
+    u_short psock = container_of(sock, socket_info_t, socket)->psock;
+    socket_table[psock].handler = handler;
+    socket_table[psock].info = info;
     return 0;
 } /* tcic_register_callback */
 
 /*====================================================================*/
 
-static int tcic_get_status(unsigned int lsock, u_int *value)
+static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, socket_info_t, socket)->psock;
     u_char reg;
 
     tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
@@ -677,7 +678,7 @@
   
 /*====================================================================*/
 
-static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
+static int tcic_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
 {
     *cap = tcic_cap;
     return 0;
@@ -685,9 +686,9 @@
 
 /*====================================================================*/
 
-static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
+static int tcic_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, socket_info_t, socket)->psock;
     u_char reg;
     u_short scf1, scf2;
     
@@ -738,9 +739,9 @@
 
 /*====================================================================*/
 
-static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
+static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, socket_info_t, socket)->psock;
     u_char reg;
     u_short scf1, scf2;
 
@@ -813,9 +814,9 @@
   
 /*====================================================================*/
 
-static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
+static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, socket_info_t, socket)->psock;
     u_int addr;
     u_short base, len, ioctl;
     
@@ -850,9 +851,9 @@
 
 /*====================================================================*/
 
-static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
+static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, socket_info_t, socket)->psock;
     u_short addr, ctl;
     u_long base, len, mmap;
 
@@ -894,11 +895,11 @@
 
 /*====================================================================*/
 
-static void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void tcic_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
 {
 }
 
-static int tcic_init(unsigned int s)
+static int tcic_init(struct pcmcia_socket *s)
 {
 	int i;
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -917,7 +918,7 @@
 	return 0;
 }
 
-static int tcic_suspend(unsigned int sock)
+static int tcic_suspend(struct pcmcia_socket *sock)
 {
 	return tcic_set_socket(sock, &dead_socket);
 }
diff -ruN linux-original/include/pcmcia/ss.h linux/include/pcmcia/ss.h
--- linux-original/include/pcmcia/ss.h	2003-05-17 22:03:15.000000000 +0200
+++ linux/include/pcmcia/ss.h	2003-05-17 21:40:33.000000000 +0200
@@ -124,18 +124,20 @@
 /*
  * Socket operations.
  */
+struct pcmcia_socket;
+
 struct pccard_operations {
 	struct module *owner;
-	int (*init)(unsigned int sock);
-	int (*suspend)(unsigned int sock);
-	int (*register_callback)(unsigned int sock, void (*handler)(void *, unsigned int), void * info);
-	int (*inquire_socket)(unsigned int sock, socket_cap_t *cap);
-	int (*get_status)(unsigned int sock, u_int *value);
-	int (*get_socket)(unsigned int sock, socket_state_t *state);
-	int (*set_socket)(unsigned int sock, socket_state_t *state);
-	int (*set_io_map)(unsigned int sock, struct pccard_io_map *io);
-	int (*set_mem_map)(unsigned int sock, struct pccard_mem_map *mem);
-	void (*proc_setup)(unsigned int sock, struct proc_dir_entry *base);
+	int (*init)(struct pcmcia_socket *sock);
+	int (*suspend)(struct pcmcia_socket *sock);
+	int (*register_callback)(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info);
+	int (*inquire_socket)(struct pcmcia_socket *sock, socket_cap_t *cap);
+	int (*get_status)(struct pcmcia_socket *sock, u_int *value);
+	int (*get_socket)(struct pcmcia_socket *sock, socket_state_t *state);
+	int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state);
+	int (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io);
+	int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem);
+	void (*proc_setup)(struct pcmcia_socket *sock, struct proc_dir_entry *base);
 };
 
 /*
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030517/d1eabde5/attachment.bin
From linux at brodo.de  Sat May 17 23:14:04 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sat May 17 21:19:17 2003
Subject: [PATCH] pcmcia: new socket initialization interface
Message-ID: <20030517201404.GD1749@brodo.de>

Add a more sane socket registration interface.

Previously, it was messed up because Greg's struct class hadn't been
invented when I wrote the code: there may be multiple sockets per
"struct device", and there is the need for one "struct class_device"
for each socket.

 drivers/pcmcia/cs.c         |  243 ++++++++++++++++++++------------------------
 drivers/pcmcia/ds.c         |   58 +++-------
 drivers/pcmcia/i82092.c     |   50 ++++-----
 drivers/pcmcia/i82365.c     |   43 ++++---
 drivers/pcmcia/pci_socket.c |   24 +---
 drivers/pcmcia/pci_socket.h |    2
 drivers/pcmcia/tcic.c       |   40 +++----
 include/pcmcia/ss.h         |   20 +--
 8 files changed, 217 insertions(+), 263 deletions(-)

diff -ruN linux-original/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- linux-original/drivers/pcmcia/cs.c	2003-05-17 21:19:17.000000000 +0200
+++ linux/drivers/pcmcia/cs.c	2003-05-17 21:22:45.000000000 +0200
@@ -303,7 +303,6 @@
 ======================================================================*/
 
 static int pccardd(void *__skt);
-void pcmcia_unregister_socket(struct class_device *dev);
 
 #define to_class_data(dev) dev->class_data
 
@@ -321,12 +320,69 @@
 	return NULL;
 }
 
+/**
+ * socket drivers are expected to use the following callbacks in their 
+ * .drv struct:
+ *  - pcmcia_socket_dev_suspend
+ *  - pcmcia_socket_dev_resume
+ * These functions check for the appropriate struct pcmcia_soket arrays,
+ * and pass them to the low-level functions pcmcia_{suspend,resume}_socket
+ */
+static int socket_resume(socket_info_t *skt);
+static int socket_suspend(socket_info_t *skt);
 
-static int pcmcia_add_socket(struct pcmcia_socket *socket)
+int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level)
 {
+	struct pcmcia_socket *socket;
 	socket_info_t *s;
-	int ret;
 
+	if (level != SUSPEND_SAVE_STATE)
+		return 0;
+
+	down(&pcmcia_socket_list_lock);
+	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+		if (socket->dev.dev != dev)
+			continue;
+		s = (socket_info_t *) socket->s_info;
+		down(&s->skt_sem);
+		socket_suspend(s);
+		up(&s->skt_sem);
+	}
+	up(&pcmcia_socket_list_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
+
+int pcmcia_socket_dev_resume(struct device *dev, u32 level)
+{
+	struct pcmcia_socket *socket;
+	socket_info_t *s;
+
+	if (level != RESUME_RESTORE_STATE)
+		return 0;
+
+	down(&pcmcia_socket_list_lock);
+	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+		if (socket->dev.dev != dev)
+			continue;
+		s = (socket_info_t *) socket->s_info;
+		down(&s->skt_sem);
+		socket_resume(s);
+		up(&s->skt_sem);
+	}
+	up(&pcmcia_socket_list_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_resume);
+
+
+static int pcmcia_add_socket(struct class_device *class_dev)
+{
+	struct pcmcia_socket *socket = class_get_devdata(class_dev);
+	socket_info_t *s;
+	int ret;
 	s = (socket_info_t *) socket->s_info;
 	/* socket initialization */
 	s->ss_entry = socket->ops;
@@ -373,8 +429,9 @@
 }
 
 
-static void pcmcia_remove_socket(struct pcmcia_socket *socket)
+static void pcmcia_remove_socket(struct class_device *class_dev)
 {
+	struct pcmcia_socket *socket = class_get_devdata(class_dev);
 	client_t *client;
 	socket_info_t *s;
 
@@ -409,85 +466,78 @@
 /**
  * pcmcia_register_socket - add a new pcmcia socket device
  */
-int pcmcia_register_socket(struct class_device *class_dev)
+unsigned int pcmcia_register_socket(struct pcmcia_socket *socket)
 {
-	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
-	socket_info_t *s_info;
-	unsigned int i, ret;
-	struct pcmcia_socket *socket;
-
-	if (!cls_d)
+	if (!socket || !socket->ops || !socket->dev.dev)
 		return -EINVAL;
 
-	DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", cls_d->ops);
+	DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", socket->ops);
 
-	s_info = kmalloc(cls_d->nsock * sizeof(struct socket_info_t), GFP_KERNEL);
-	if (!s_info)
+	socket->s_info = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL);
+	if (!socket->s_info)
 		return -ENOMEM;
-	memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t));
+	memset(socket->s_info, 0, sizeof(socket_info_t));
 
-	cls_d->s_info = s_info;
-	ret = 0;
+	/* try to obtain a socket number [yes, it gets ugly if we
+	 * register more than 2^sizeof(unsigned int) pcmcia 
+	 * sockets... but the socket number is deprecated 
+	 * anyways, so I don't care] */
+	down(&pcmcia_socket_list_lock);
+	if (list_empty(&pcmcia_socket_list))
+		socket->socket_no = 0;
+	else {
+		unsigned int found, i = 1;
+		struct pcmcia_socket *tmp;
+		do {
+			found = 1;
+			list_for_each_entry(tmp, &pcmcia_socket_list, socket_list) {
+				if (tmp->socket_no == i)
+					found = 0;
+			}
+			i++;
+		} while (!found);
+		socket->socket_no = i - 1;
+	}
+	list_add_tail(&socket->socket_list, &pcmcia_socket_list);
+	up(&pcmcia_socket_list_lock);
 
-	/* socket initialization */
-	for (i = 0; i < cls_d->nsock; i++) {
-		socket = kmalloc(sizeof(struct pcmcia_socket), GFP_KERNEL);
-		if (!socket)
-			return -ENOMEM;
-		memset(socket, 0, sizeof(struct pcmcia_socket));
-
-		socket->s_info = (void *) &s_info[i];
-		socket->socket_no = i + cls_d->sock_offset;
-		socket->ops = cls_d->ops;
+	/* set proper values in socket->dev */
+	socket->dev.class_data = socket;
+	socket->dev.class = &pcmcia_socket_class;
+	snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u\n", socket->socket_no);
 
+	if (class_device_register(&socket->dev)) {
+		kfree(socket->s_info);
 		down(&pcmcia_socket_list_lock);
-		list_add_tail(&socket->socket_list, &pcmcia_socket_list);
-		up(&pcmcia_socket_list_lock);
-
-		pcmcia_add_socket(socket);
+		list_del(&socket->socket_list);
+ 		up(&pcmcia_socket_list_lock);
+		return -EINVAL;
 	}
-	return ret;
+
+	return 0;
 } /* pcmcia_register_socket */
+EXPORT_SYMBOL(pcmcia_register_socket);
 
 
 /**
- * pcmcia_unregister_socket - remove a pcmcia socket device
+ * pcmcia_unregister_socket - unregister a socket from the core
  */
-void pcmcia_unregister_socket(struct class_device *class_dev)
+void pcmcia_unregister_socket(struct pcmcia_socket *socket)
 {
- 	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
-	struct pcmcia_socket *socket;
-	unsigned int i;
-	socket_info_t *s;
-
-	if (!cls_d)
+	if (!socket)
 		return;
 
-	s = (socket_info_t *) cls_d->s_info;
-
-	for (i = 0; i < cls_d->nsock; i++) {
-		down(&pcmcia_socket_list_lock);
-		list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
-			if (socket->s_info == s)
-				goto found;
-		}
-		up(&pcmcia_socket_list_lock);
-		continue;
-
-	found:
-		up(&pcmcia_socket_list_lock);
+	DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ops);
 
+	class_device_unregister(&socket->dev);
 
-		pcmcia_remove_socket(socket);
-
-		down(&pcmcia_socket_list_lock);
-		list_del(&socket->socket_list);
-		up(&pcmcia_socket_list_lock);
+	down(&pcmcia_socket_list_lock);
+	list_del(&socket->socket_list);
+	up(&pcmcia_socket_list_lock);
 
-		s++;
-	}
-	kfree(cls_d->s_info);
-} /* pcmcia_unregister_socket */
+	kfree(socket->s_info);
+}
+EXPORT_SYMBOL(pcmcia_unregister_socket);
 
 
 /*======================================================================
@@ -851,67 +901,7 @@
 	wake_up(&s->thread_wait);
 } /* parse_events */
 
-/*======================================================================
-
-    Another event handler, for power management events.
-
-    This does not comply with the latest PC Card spec for handling
-    power management events.
-    
-======================================================================*/
-
-void pcmcia_suspend_socket (socket_info_t *skt)
-{
-	down(&skt->skt_sem);
-	socket_suspend(skt);
-	up(&skt->skt_sem);
-}
-
-void pcmcia_resume_socket (socket_info_t *skt)
-{
-	down(&skt->skt_sem);
-	socket_resume(skt);
-	up(&skt->skt_sem);
-}
-
-
-int pcmcia_socket_dev_suspend(struct pcmcia_socket_class_data *cls_d, u32 state, u32 level)
-{
-	socket_info_t *s;
-	int i;
-
-	if ((!cls_d) || (level != SUSPEND_SAVE_STATE))
-		return 0;
-
-	s = (socket_info_t *) cls_d->s_info;
-
-	for (i = 0; i < cls_d->nsock; i++) {
-		pcmcia_suspend_socket(s);
-		s++;
-	}
 
-	return 0;
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
-
-int pcmcia_socket_dev_resume(struct pcmcia_socket_class_data *cls_d, u32 level)
-{
-	socket_info_t *s;
-	int i;
-
-	if ((!cls_d) || (level != RESUME_RESTORE_STATE))
-		return 0;
-
-	s = (socket_info_t *) cls_d->s_info;
-
-	for (i = 0; i < cls_d->nsock; i++) {
-		pcmcia_resume_socket(s);
-		s++;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_resume);
 
 
 /*======================================================================
@@ -2571,11 +2561,6 @@
 EXPORT_SYMBOL(proc_pccard);
 #endif
 
-EXPORT_SYMBOL(pcmcia_register_socket);
-EXPORT_SYMBOL(pcmcia_unregister_socket);
-EXPORT_SYMBOL(pcmcia_suspend_socket);
-EXPORT_SYMBOL(pcmcia_resume_socket);
-
 struct class pcmcia_socket_class = {
 	.name = "pcmcia_socket",
 };
@@ -2583,8 +2568,8 @@
 
 static struct class_interface pcmcia_socket = {
 	.class = &pcmcia_socket_class,
-	.add = &pcmcia_register_socket,
-	.remove = &pcmcia_unregister_socket,
+	.add = &pcmcia_add_socket,
+	.remove = &pcmcia_remove_socket,
 };
 
 
diff -ruN linux-original/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux-original/drivers/pcmcia/ds.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/ds.c	2003-05-17 21:05:08.000000000 +0200
@@ -883,13 +883,19 @@
 
 /*====================================================================*/
 
-static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int socket_nr)
+static int pcmcia_bus_add_socket(struct class_device *class_dev)
 {
+	struct pcmcia_socket *socket = class_dev->class_data;
+	struct device *dev;
 	client_reg_t client_reg;
 	bind_req_t bind;
-	struct pcmcia_bus_socket *s, *tmp_s;
+	struct pcmcia_bus_socket *s;
 	int ret;
-	int i;
+
+	if (!socket)
+		return -EINVAL;
+
+	dev = socket->dev.dev;
 
 	s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL);
 	if(!s)
@@ -906,19 +912,7 @@
 	init_waitqueue_head(&s->queue);
 	init_waitqueue_head(&s->request);
 
-	/* find the lowest, unused socket no. Please note that this is a
-	 * temporary workaround until "struct pcmcia_socket" is introduced
-	 * into cs.c which will include this number, and which will be
-	 * accessible to ds.c directly */
-	i = 0;
- next_try:
-	list_for_each_entry(tmp_s, &bus_socket_list, socket_list) {
-		if (tmp_s->socket_no == i) {
-			i++;
-			goto next_try;
-		}
-	}
-	s->socket_no = i;
+	s->socket_no = socket->socket_no;
 
 	/* initialize data */
 	s->socket_dev = dev;
@@ -952,44 +946,26 @@
 		return -EINVAL;
 	}
 
+	down_write(&bus_socket_list_rwsem);
 	list_add(&s->socket_list, &bus_socket_list);
+	up_write(&bus_socket_list_rwsem);
 
 	return 0;
 }
 
 
-static int pcmcia_bus_add_socket_dev(struct class_device *class_dev)
+static void pcmcia_bus_remove_socket(struct class_device *class_dev)
 {
-	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
-	unsigned int i;
-	unsigned int ret = 0;
-
-	if (!cls_d)
-		return -ENODEV;
-
-	down_write(&bus_socket_list_rwsem);
-        for (i = 0; i < cls_d->nsock; i++)
-		ret += pcmcia_bus_add_socket(class_dev->dev, i);
-	up_write(&bus_socket_list_rwsem);
-
-	return ret;
-}
-
-static void pcmcia_bus_remove_socket_dev(struct class_device *class_dev)
-{
-	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
+	struct pcmcia_socket *socket = class_dev->class_data;
 	struct list_head *list_loop;
 	struct list_head *tmp_storage;
 
-	if (!cls_d)
-		return;
-
 	flush_scheduled_work();
 
 	down_write(&bus_socket_list_rwsem);
 	list_for_each_safe(list_loop, tmp_storage, &bus_socket_list) {
 		struct pcmcia_bus_socket *bus_sock = container_of(list_loop, struct pcmcia_bus_socket, socket_list);
-		if (bus_sock->socket_dev == class_dev->dev) {
+		if (bus_sock->socket_no == socket->socket_no) {
 			pcmcia_deregister_client(bus_sock->handle);
 			list_del(&bus_sock->socket_list);
 			kfree(bus_sock);
@@ -1003,8 +979,8 @@
 /* the pcmcia_bus_interface is used to handle pcmcia socket devices */
 static struct class_interface pcmcia_bus_interface = {
 	.class = &pcmcia_socket_class,
-	.add = &pcmcia_bus_add_socket_dev,
-	.remove = &pcmcia_bus_remove_socket_dev,
+	.add = &pcmcia_bus_add_socket,
+	.remove = &pcmcia_bus_remove_socket,
 };
 
 
diff -ruN linux-original/drivers/pcmcia/i82092.c linux/drivers/pcmcia/i82092.c
--- linux-original/drivers/pcmcia/i82092.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/i82092.c	2003-05-17 21:05:08.000000000 +0200
@@ -44,14 +44,12 @@
 
 static int i82092aa_socket_suspend (struct pci_dev *dev, u32 state)
 {
-	struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
-	return pcmcia_socket_dev_suspend(cls_d, state, 0);
+	return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
 }
 
 static int i82092aa_socket_resume (struct pci_dev *dev)
 {
-	struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
-	return pcmcia_socket_dev_resume(cls_d, RESUME_RESTORE_STATE);
+	return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
 }
 
 static struct pci_driver i82092aa_pci_drv = {
@@ -94,7 +92,8 @@
 	void	(*handler)(void *info, u_int events); 
 				/* callback to the driver of the card */
 	void	*info;		/* to be passed to the handler */
-	
+
+	struct pcmcia_socket socket;	
 	struct pci_dev *dev;	/* The PCI device for the socket */
 };
 
@@ -107,7 +106,6 @@
 {
 	unsigned char configbyte;
 	int i, ret;
-	struct pcmcia_socket_class_data *cls_d;
 	
 	enter("i82092aa_pci_probe");
 	
@@ -166,26 +164,26 @@
 		goto err_out_free_res;
 	}
 
-	
-	cls_d = kmalloc(sizeof(*cls_d), GFP_KERNEL);
-	if (!cls_d) {
-		printk(KERN_ERR "i82092aa: kmalloc failed\n");
-		goto err_out_free_irq;
-	}
-	memset(cls_d, 0, sizeof(*cls_d));
-	cls_d->nsock = socket_count;
-	cls_d->ops = &i82092aa_operations;
-	pci_set_drvdata(dev, &cls_d);
-	cls_d->class_dev.class = &pcmcia_socket_class;
-	cls_d->class_dev.dev = &dev->dev;
-	strncpy(cls_d->class_dev.class_id, dev->dev.name, BUS_ID_SIZE);
-	class_set_devdata(&cls_d->class_dev, cls_d);
-	class_device_register(&cls_d->class_dev);
+	pci_set_drvdata(dev, &sockets[i].socket);
+
+	for (i = 0; i<socket_count; i++) {
+		sockets[i].socket.dev.dev = &dev->dev;
+		sockets[i].socket.ops = &i82092aa_operations;
+		ret = pcmcia_register_socket(&sockets[i].socket);
+		if (ret) {
+			goto err_out_free_sockets;
+		}
+	}
 
 	leave("i82092aa_pci_probe");
 	return 0;
 
-err_out_free_irq:
+err_out_free_sockets:
+	if (i) {
+		for (i--;i>=0;i--) {
+			pcmcia_unregister_socket(&sockets[i].socket);
+		}
+	}
 	free_irq(dev->irq, i82092aa_interrupt);
 err_out_free_res:
 	release_region(pci_resource_start(dev, 0), 2);
@@ -196,16 +194,14 @@
 
 static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
 {
-	struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
+	struct pcmcia_socket *socket = pci_get_drvdata(dev);
 
 	enter("i82092aa_pci_remove");
 	
 	free_irq(dev->irq, i82092aa_interrupt);
 
-	if (cls_d) {
-		class_device_unregister(&cls_d->class_dev);
-		kfree(cls_d);
-	}
+	if (socket)
+		pcmcia_unregister_socket(socket);
 
 	leave("i82092aa_pci_remove");
 }
diff -ruN linux-original/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- linux-original/drivers/pcmcia/i82365.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/i82365.c	2003-05-17 21:05:08.000000000 +0200
@@ -166,6 +166,7 @@
 
 typedef struct socket_info_t {
     u_short		type, flags;
+    struct pcmcia_socket	socket;
     socket_cap_t	cap;
     ioaddr_t		ioaddr;
     u_short		psock;
@@ -1502,15 +1503,11 @@
 
 /*====================================================================*/
 
-static struct pcmcia_socket_class_data i82365_data = {
-	.ops = &pcic_operations,
-};
-
 static struct device_driver i82365_driver = {
 	.name = "i82365",
 	.bus = &platform_bus_type,
-/*	.suspend = pcmcia_socket_dev_suspend,	FIXME?	*/
-/*	.resume = pcmcia_socket_dev_resume,	FIXME?	*/
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device i82365_device = {
@@ -1521,13 +1518,11 @@
 	},
 };
 
-static struct class_device i82365_class_data = {
-	.class = &pcmcia_socket_class,
-};
-
 static int __init init_i82365(void)
 {
     servinfo_t serv;
+    int i, ret;
+
     pcmcia_get_card_services_info(&serv);
     if (serv.Revision != CS_RELEASE_CODE) {
 	printk(KERN_NOTICE "i82365: Card Services release "
@@ -1551,19 +1546,25 @@
 	return -ENODEV;
     }
 
+    platform_device_register(&i82365_device);
+
     /* Set up interrupt handler(s) */
 #ifdef CONFIG_ISA
     if (grab_irq != 0)
 	request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
 #endif
-    
-    i82365_data.nsock = sockets;
-    i82365_class_data.dev = &i82365_device.dev;
-    i82365_class_data.class_data = &i82365_data;
-    strncpy(i82365_class_data.class_id, "i82365", BUS_ID_SIZE);
-    
-    platform_device_register(&i82365_device);
-    class_device_register(&i82365_class_data);
+
+    /* register sockets with the pcmcia core */
+    for (i = 0; i < sockets; i++) {
+	    socket[i].socket.dev.dev = &i82365_device.dev;
+	    socket[i].socket.ops = &pcic_operations;
+	    ret = pcmcia_register_socket(&socket[i].socket);	    
+	    if (ret && i--) {
+		    for (; i>= 0; i--)
+			    pcmcia_unregister_socket(&socket[i].socket);
+		    break;
+	    }
+    }
 
     /* Finally, schedule a polling interrupt */
     if (poll_interval != 0) {
@@ -1581,10 +1582,12 @@
 static void __exit exit_i82365(void)
 {
     int i;
+    for (i = 0; i < sockets; i++) {
+	    pcmcia_unregister_socket(&socket[i].socket);
 #ifdef CONFIG_PROC_FS
-    for (i = 0; i < sockets; i++) pcic_proc_remove(i);
+	    pcic_proc_remove(i);
 #endif
-    class_device_unregister(&i82365_class_data);
+    }
     platform_device_unregister(&i82365_device);
     if (poll_interval != 0)
 	del_timer_sync(&poll_timer);
diff -ruN linux-original/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c
--- linux-original/drivers/pcmcia/pci_socket.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/pci_socket.c	2003-05-17 21:05:08.000000000 +0200
@@ -148,15 +148,10 @@
 	
 	memset(socket, 0, sizeof(*socket));
 
-	/* prepare class_data */
-	socket->cls_d.sock_offset = nr;
-	socket->cls_d.nsock = 1; /* yenta is 1, no other low-level driver uses
-			     this yet */
-	socket->cls_d.ops = &pci_socket_operations;
-	socket->cls_d.class_dev.class = &pcmcia_socket_class;
-	socket->cls_d.class_dev.dev = &dev->dev;
-	strncpy(socket->cls_d.class_dev.class_id, dev->dev.bus_id, BUS_ID_SIZE);
-	class_set_devdata(&socket->cls_d.class_dev, &socket->cls_d);
+	/* prepare pcmcia_socket */
+	socket->socket.ops = &pci_socket_operations;
+	socket->socket.dev.dev = &dev->dev;
+	socket->socket.driver_data = socket;
 
 	/* prepare pci_socket_t */
 	socket->dev = dev;
@@ -168,7 +163,7 @@
 		socket->dev = NULL;
 		pci_set_drvdata(dev, NULL);
 	} else {
-		class_device_register(&socket->cls_d.class_dev);
+		pcmcia_register_socket(&socket->socket);
 	}
 	return err;
 }
@@ -198,23 +193,20 @@
 	/* note: we are already unregistered from the cs core */
 	if (socket->op && socket->op->close)
 		socket->op->close(socket);
-	class_device_unregister(&socket->cls_d.class_dev);
+	pcmcia_unregister_socket(&socket->socket);
 	pci_set_drvdata(dev, NULL);
 }
 
 static int cardbus_suspend (struct pci_dev *dev, u32 state)
 {
-	pci_socket_t *socket = pci_get_drvdata(dev);
-	return pcmcia_socket_dev_suspend(&socket->cls_d, state, 0);
+	return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
 }
 
 static int cardbus_resume (struct pci_dev *dev)
 {
-	pci_socket_t *socket = pci_get_drvdata(dev);
-	return pcmcia_socket_dev_resume(&socket->cls_d, RESUME_RESTORE_STATE);
+	return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
 }
 
-
 static struct pci_device_id cardbus_table [] __devinitdata = { {
 	.class		= PCI_CLASS_BRIDGE_CARDBUS << 8,
 	.class_mask	= ~0,
diff -ruN linux-original/drivers/pcmcia/pci_socket.h linux/drivers/pcmcia/pci_socket.h
--- linux-original/drivers/pcmcia/pci_socket.h	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/pci_socket.h	2003-05-17 21:05:08.000000000 +0200
@@ -23,7 +23,7 @@
 	struct work_struct tq_task;
 	struct timer_list poll_timer;
 
-	struct pcmcia_socket_class_data cls_d;
+	struct pcmcia_socket socket;
 	/* A few words of private data for the low-level driver.. */
 	unsigned int private[8];
 } pci_socket_t;
diff -ruN linux-original/drivers/pcmcia/tcic.c linux/drivers/pcmcia/tcic.c
--- linux-original/drivers/pcmcia/tcic.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/tcic.c	2003-05-17 21:05:08.000000000 +0200
@@ -121,6 +121,7 @@
     void	*info;
     u_char	last_sstat;
     u_char	id;
+    struct pcmcia_socket socket;
 } socket_info_t;
 
 static struct timer_list poll_timer;
@@ -372,15 +373,11 @@
 
 /*====================================================================*/
 
-static struct pcmcia_socket_class_data tcic_data = {
-	.ops = &tcic_operations,
-};
-
 static struct device_driver tcic_driver = {
 	.name = "tcic-pcmcia",
 	.bus = &platform_bus_type,
-/*	.suspend = pcmcia_socket_dev_suspend,	FIXME?	*/
-/*	.resume = pcmcia_socket_dev_resume,	FIXME?	*/
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device tcic_device = {
@@ -391,13 +388,9 @@
 	},
 };
 
-static struct class_device tcic_class_data = {
-	.class = &pcmcia_socket_class,
-};
-
 static int __init init_tcic(void)
 {
-    int i, sock;
+    int i, sock, ret = 0;
     u_int mask, scan;
     servinfo_t serv;
 
@@ -524,15 +517,18 @@
     /* jump start interrupt handler, if needed */
     tcic_interrupt(0, NULL, NULL);
 
-    tcic_data.nsock = sockets;
-    tcic_class_data.dev = &tcic_device.dev;
-    tcic_class_data.class_data = &tcic_data;
-    strncpy(tcic_class_data.class_id, "tcic-pcmcia", BUS_ID_SIZE);
-    
     platform_device_register(&tcic_device);
-    class_device_register(&tcic_class_data);
 
-    return 0;
+
+    for (i = 0; i < sockets; i++) {
+	    socket_table[i].socket.ops = &tcic_operations;
+	    socket_table[i].socket.dev.dev = &tcic_device.dev;
+	    ret = pcmcia_register_socket(&socket_table[i].socket);	    
+	    if (ret && i)
+		    pcmcia_unregister_socket(&socket_table[0].socket);
+    }
+    
+    return ret;
     
 } /* init_tcic */
 
@@ -540,13 +536,19 @@
 
 static void __exit exit_tcic(void)
 {
+    int i;
+
     del_timer_sync(&poll_timer);
     if (cs_irq != 0) {
 	tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
 	free_irq(cs_irq, tcic_interrupt);
     }
     release_region(tcic_base, 16);
-    class_device_unregister(&tcic_class_data);
+
+    for (i = 0; i < sockets; i++) {
+	    pcmcia_unregister_socket(&socket_table[i].socket);	    
+    }
+
     platform_device_unregister(&tcic_device);
     driver_unregister(&tcic_driver);
 } /* exit_tcic */
diff -ruN linux-original/include/pcmcia/ss.h linux/include/pcmcia/ss.h
--- linux-original/include/pcmcia/ss.h	2003-05-17 21:19:17.000000000 +0200
+++ linux/include/pcmcia/ss.h	2003-05-17 21:05:08.000000000 +0200
@@ -144,26 +144,26 @@
 
 struct pcmcia_socket {
 	struct list_head		socket_list;
+	struct class_device		dev;
 	struct pccard_operations	*ops;
 
+	/* data internal to the socket driver */
+	void				*driver_data;
+
 	/* deprecated */
 	unsigned int			socket_no;
 	void				*s_info; /* socket_info_t */
 };
 
-struct pcmcia_socket_class_data {
-	unsigned int nsock;			/* number of sockets */
-	unsigned int sock_offset;		/* socket # (which is
-	 * returned to driver) = sock_offset + (0, 1, .. , (nsock-1) */
-	struct pccard_operations *ops;		/* see above */
-	void *s_info;				/* socket_info_t */
-	struct class_device class_dev;		/* generic class structure */
-};
+
+extern unsigned int pcmcia_register_socket(struct pcmcia_socket *socket);
+extern void pcmcia_unregister_socket(struct pcmcia_socket *socket);
 
 extern struct class pcmcia_socket_class;
 
+
 /* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct pcmcia_socket_class_data *cls_d, u32 state, u32 level);
-extern int pcmcia_socket_dev_resume(struct pcmcia_socket_class_data *cls_d, u32 level);
+extern int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level);
+extern int pcmcia_socket_dev_resume(struct device *dev, u32 level);
 
 #endif /* _LINUX_SS_H */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030517/b5a47052/attachment.bin
From linux at brodo.de  Sun May 18 00:43:49 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sat May 17 22:56:20 2003
Subject: [PATCH] pcmcia: unify yenta.c and pci_socket.c
Message-ID: <20030517214349.GA7882@brodo.de>

As discussed a few weeks ago with Linus, merge yenta.c and
pci_socket.c as the pcmcia core now passes a "struct pcmcia_socket" as
argument. Also, allow to build it as a module, and clean yenta.c up
some (typedefs etc.)

 Kconfig      |    9 +
 Makefile     |    6 -
 pci_socket.c |  242 -------------------------------------------------
 pci_socket.h |   48 ---------
 ricoh.h      |   43 +++-----
 ti113x.h     |  130 ++++++++++----------------
 yenta.c      |  289 +++++++++++++++++++++++++++++++++++++++--------------------
 yenta.h      |   20 +++-
 8 files changed, 288 insertions(+), 499 deletions(-)

diff -ruN linux-original/drivers/pcmcia/Kconfig linux/drivers/pcmcia/Kconfig
--- linux-original/drivers/pcmcia/Kconfig	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/Kconfig	2003-05-17 23:31:27.000000000 +0200
@@ -29,8 +29,8 @@
 	  and ds.  If you want to compile it as a module, say M here and
 	  read <file:Documentation/modules.txt>.
 
-config CARDBUS
-	bool "CardBus support"
+config YENTA
+	tristate "CardBus yenta-compatible bridge support"
 	depends on PCMCIA && PCI
 	---help---
 	  CardBus is a bus mastering architecture for PC-cards, which allows
@@ -48,6 +48,11 @@
 
 	  If unsure, say Y.
 
+config CARDBUS
+	bool
+	depends on YENTA
+	default y if YENTA
+
 config I82092
 	tristate "i82092 compatible bridge support"
 	depends on PCMCIA && PCI
diff -ruN linux-original/drivers/pcmcia/Makefile linux/drivers/pcmcia/Makefile
--- linux-original/drivers/pcmcia/Makefile	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/Makefile	2003-05-17 23:22:08.000000000 +0200
@@ -3,9 +3,7 @@
 #
 
 obj-$(CONFIG_PCMCIA)				+= pcmcia_core.o ds.o
-ifeq ($(CONFIG_CARDBUS),y)
-  obj-$(CONFIG_PCMCIA) 				+= yenta_socket.o
-endif
+obj-$(CONFIG_YENTA) 				+= yenta.o
 
 obj-$(CONFIG_I82365)				+= i82365.o
 obj-$(CONFIG_I82092)				+= i82092.o
@@ -14,8 +12,6 @@
 obj-$(CONFIG_PCMCIA_SA1100)			+= sa11xx_core.o sa1100_cs.o
 obj-$(CONFIG_PCMCIA_SA1111)			+= sa11xx_core.o sa1111_cs.o
 
-yenta_socket-y					+= pci_socket.o yenta.o
-
 pcmcia_core-y					+= cistpl.o rsrc_mgr.o bulkmem.o cs.o
 pcmcia_core-$(CONFIG_CARDBUS)			+= cardbus.o
 
diff -ruN linux-original/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c
--- linux-original/drivers/pcmcia/pci_socket.c	2003-05-17 23:13:38.000000000 +0200
+++ linux/drivers/pcmcia/pci_socket.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,242 +0,0 @@
-/*
- * Generic PCI pccard driver interface.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * This implements the common parts of PCI pccard drivers,
- * notably detection and infrastructure conversion (ie change
- * from socket index to "struct pci_dev" etc)
- *
- * This does NOT implement the actual low-level driver details,
- * and this has on purpose been left generic enough that it can
- * be used to set up a PCI PCMCIA controller (ie non-cardbus),
- * or to set up a controller.
- *
- * See for example the "yenta" driver for PCI cardbus controllers
- * conforming to the yenta cardbus specifications.
- */
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-
-#include <pcmcia/ss.h>
-
-#include <asm/io.h>
-
-#include "pci_socket.h"
-
-
-/*
- * Arbitrary define. This is the array of active cardbus
- * entries.
- */
-#define MAX_SOCKETS (8)
-static pci_socket_t pci_socket_array[MAX_SOCKETS];
-
-static int pci_init_socket(struct pcmcia_socket *sock)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	if (socket->op && socket->op->init)
-		return socket->op->init(socket);
-	return -EINVAL;
-}
-
-static int pci_suspend_socket(struct pcmcia_socket *sock)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	if (socket->op && socket->op->suspend)
-		return socket->op->suspend(socket);
-	return -EINVAL;
-}
-
-static int pci_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	socket->handler = handler;
-	socket->info = info;
-	return 0;
-}
-
-static int pci_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	*cap = socket->cap;
-	return 0;
-}
-
-static int pci_get_status(struct pcmcia_socket *sock, unsigned int *value)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	if (socket->op && socket->op->get_status)
-		return socket->op->get_status(socket, value);
-	*value = 0;
-	return -EINVAL;
-}
-
-static int pci_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	if (socket->op && socket->op->get_socket)
-		return socket->op->get_socket(socket, state);
-	return -EINVAL;
-}
-
-static int pci_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	if (socket->op && socket->op->set_socket)
-		return socket->op->set_socket(socket, state);
-	return -EINVAL;
-}
-
-static int pci_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	if (socket->op && socket->op->set_io_map)
-		return socket->op->set_io_map(socket, io);
-	return -EINVAL;
-}
-
-static int pci_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	if (socket->op && socket->op->set_mem_map)
-		return socket->op->set_mem_map(socket, mem);
-	return -EINVAL;
-}
-
-static void pci_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
-{
-	pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
-
-	if (socket->op && socket->op->proc_setup)
-		socket->op->proc_setup(socket, base);
-}
-
-static struct pccard_operations pci_socket_operations = {
-	.owner			= THIS_MODULE,
-	.init			= pci_init_socket,
-	.suspend		= pci_suspend_socket,
-	.register_callback	= pci_register_callback,
-	.inquire_socket		= pci_inquire_socket,
-	.get_status		= pci_get_status,
-	.get_socket		= pci_get_socket,
-	.set_socket		= pci_set_socket,
-	.set_io_map		= pci_set_io_map,
-	.set_mem_map		= pci_set_mem_map,
-	.proc_setup		= pci_proc_setup,
-};
-
-static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
-{
-	pci_socket_t *socket = nr + pci_socket_array;
-	int err;
-	
-	memset(socket, 0, sizeof(*socket));
-
-	/* prepare pcmcia_socket */
-	socket->socket.ops = &pci_socket_operations;
-	socket->socket.dev.dev = &dev->dev;
-	socket->socket.driver_data = socket;
-
-	/* prepare pci_socket_t */
-	socket->dev = dev;
-	socket->op = ops;
-	pci_set_drvdata(dev, socket);
-	spin_lock_init(&socket->event_lock);
-	err = socket->op->open(socket);
-	if (err) {
-		socket->dev = NULL;
-		pci_set_drvdata(dev, NULL);
-	} else {
-		pcmcia_register_socket(&socket->socket);
-	}
-	return err;
-}
-
-int cardbus_register(struct pci_dev *p_dev)
-{
-	return 0;
-}
-
-static int __devinit
-cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id)
-{
-	int	s;
-
-	for (s = 0; s < MAX_SOCKETS; s++) {
-		if (pci_socket_array [s].dev == 0) {
-			return add_pci_socket (s, dev, &yenta_operations);
-		}
-	}
-	return -ENODEV;
-}
-
-static void __devexit cardbus_remove (struct pci_dev *dev)
-{
-	pci_socket_t *socket = pci_get_drvdata(dev);
-
-	/* note: we are already unregistered from the cs core */
-	if (socket->op && socket->op->close)
-		socket->op->close(socket);
-	pcmcia_unregister_socket(&socket->socket);
-	pci_set_drvdata(dev, NULL);
-}
-
-static int cardbus_suspend (struct pci_dev *dev, u32 state)
-{
-	return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
-}
-
-static int cardbus_resume (struct pci_dev *dev)
-{
-	return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
-}
-
-static struct pci_device_id cardbus_table [] __devinitdata = { {
-	.class		= PCI_CLASS_BRIDGE_CARDBUS << 8,
-	.class_mask	= ~0,
-
-	.vendor		= PCI_ANY_ID,
-	.device		= PCI_ANY_ID,
-	.subvendor	= PCI_ANY_ID,
-	.subdevice	= PCI_ANY_ID,
-}, { /* all zeroes */ }
-};
-MODULE_DEVICE_TABLE(pci, cardbus_table);
-
-static struct pci_driver pci_cardbus_driver = {
-	.name		= "cardbus",
-	.id_table	= cardbus_table,
-	.probe		= cardbus_probe,
-	.remove		= __devexit_p(cardbus_remove),
-	.suspend	= cardbus_suspend,
-	.resume		= cardbus_resume,
-};
-
-static int __init pci_socket_init(void)
-{
-	return pci_register_driver (&pci_cardbus_driver);
-}
-
-static void __exit pci_socket_exit (void)
-{
-	pci_unregister_driver (&pci_cardbus_driver);
-}
-
-module_init(pci_socket_init);
-module_exit(pci_socket_exit);
diff -ruN linux-original/drivers/pcmcia/pci_socket.h linux/drivers/pcmcia/pci_socket.h
--- linux-original/drivers/pcmcia/pci_socket.h	2003-05-17 22:03:15.000000000 +0200
+++ linux/drivers/pcmcia/pci_socket.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,48 +0,0 @@
-/*
- * drivers/pcmcia/pci_socket.h
- *
- * (C) Copyright 1999 Linus Torvalds
- */
-
-#ifndef __PCI_SOCKET_H
-#define __PCI_SOCKET_H
-
-struct pci_socket_ops;
-struct socket_info_t;
-
-typedef struct pci_socket {
-	struct pci_dev *dev;
-	int cb_irq, io_irq;
-	void *base;
-	void (*handler)(void *, unsigned int);
-	void *info;
-	struct pci_socket_ops *op;
-	socket_cap_t cap;
-	spinlock_t event_lock;
-	unsigned int events;
-	struct work_struct tq_task;
-	struct timer_list poll_timer;
-
-	struct pcmcia_socket socket;
-	/* A few words of private data for the low-level driver.. */
-	unsigned int private[8];
-} pci_socket_t;
-
-struct pci_socket_ops {
-	int (*open)(struct pci_socket *);
-	void (*close)(struct pci_socket *);
-
-	int (*init)(struct pci_socket *);
-	int (*suspend)(struct pci_socket *);
-	int (*get_status)(struct pci_socket *, unsigned int *);
-	int (*get_socket)(struct pci_socket *, socket_state_t *);
-	int (*set_socket)(struct pci_socket *, socket_state_t *);
-	int (*set_io_map)(struct pci_socket *, struct pccard_io_map *);
-	int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *);
-	void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base);
-};
-
-extern struct pci_socket_ops yenta_operations;
-extern struct pci_socket_ops ricoh_operations;
-
-#endif
diff -ruN linux-original/drivers/pcmcia/ricoh.h linux/drivers/pcmcia/ricoh.h
--- linux-original/drivers/pcmcia/ricoh.h	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/ricoh.h	2003-05-17 23:26:16.000000000 +0200
@@ -125,11 +125,26 @@
 #define rl_mem(socket)		((socket)->private[3])
 #define rl_config(socket)	((socket)->private[4])
 
+static int ricoh_init(struct pcmcia_socket *sock)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	yenta_init(sock);
+
+	config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
+	config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
+	config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
+	config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
+	config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
+	
+	return 0;
+}
+
+
 /*
  * Magic Ricoh initialization code.. Save state at
  * beginning, re-initialize it after suspend.
  */
-static int ricoh_open(pci_socket_t *socket)
+static int ricoh_override(struct yenta_socket *socket)
 {
 	rl_misc(socket) = config_readw(socket, RL5C4XX_MISC);
 	rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL);
@@ -146,35 +161,11 @@
 		rl_config(socket) |= RL5C4XX_CONFIG_PREFETCH;
 	}
 
-	return 0;
-}
-
-static int ricoh_init(pci_socket_t *socket)
-{
-	yenta_init(socket);
+	socket->socket.ops->init = ricoh_init;
 
-	config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
-	config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
-	config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
-	config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
-	config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
-	
 	return 0;
 }
 
-static struct pci_socket_ops ricoh_ops = {
-	ricoh_open,
-	yenta_close,
-	ricoh_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
-};
-
 #endif /* CONFIG_CARDBUS */
 
 #endif /* _LINUX_RICOH_H */
diff -ruN linux-original/drivers/pcmcia/ti113x.h linux/drivers/pcmcia/ti113x.h
--- linux-original/drivers/pcmcia/ti113x.h	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/ti113x.h	2003-05-17 23:26:16.000000000 +0200
@@ -136,6 +136,26 @@
 
 #ifdef CONFIG_CARDBUS
 
+static int ti_intctl(struct yenta_socket *socket)
+{
+	u8 new, reg = exca_readb(socket, I365_INTCTL);
+
+	new = reg & ~I365_INTR_ENA;
+	if (socket->cb_irq)
+		new |= I365_INTR_ENA;
+	if (new != reg)
+		exca_writeb(socket, I365_INTCTL, new);
+	return 0;
+}
+
+static int ti_init(struct pcmcia_socket *sock)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	yenta_init(sock);
+	ti_intctl(socket);
+	return 0;
+}
+
 /*
  * Generic TI init - TI has an extension for the
  * INTCTL register that sets the PCI CSC interrupt.
@@ -148,70 +168,28 @@
  *   This makes us correctly get PCI CSC interrupt
  *   events.
  */
-static int ti_open(pci_socket_t *socket)
+static int ti_override(struct yenta_socket *socket)
 {
 	u8 new, reg = exca_readb(socket, I365_INTCTL);
 
 	new = reg & ~I365_INTR_ENA;
 	if (new != reg)
 		exca_writeb(socket, I365_INTCTL, new);
+	socket->socket.ops->init = ti_init;
 	return 0;
 }
 
-static int ti_intctl(pci_socket_t *socket)
-{
-	u8 new, reg = exca_readb(socket, I365_INTCTL);
-
-	new = reg & ~I365_INTR_ENA;
-	if (socket->cb_irq)
-		new |= I365_INTR_ENA;
-	if (new != reg)
-		exca_writeb(socket, I365_INTCTL, new);
-	return 0;
-}
-
-static int ti_init(pci_socket_t *socket)
-{
-	yenta_init(socket);
-	ti_intctl(socket);
-	return 0;
-}
-
-static struct pci_socket_ops ti_ops = {
-	ti_open,
-	yenta_close,
-	ti_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
-};
-
 #define ti_sysctl(socket)	((socket)->private[0])
 #define ti_cardctl(socket)	((socket)->private[1])
 #define ti_devctl(socket)	((socket)->private[2])
 #define ti_diag(socket)		((socket)->private[3])
 #define ti_irqmux(socket)	((socket)->private[4])
 
-static int ti113x_open(pci_socket_t *socket)
-{
-	ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
-	ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
-	ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
-
-	ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
-	if (socket->cb_irq)
-		ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
-	ti_open(socket);
-	return 0;
-}
 
-static int ti113x_init(pci_socket_t *socket)
+static int ti113x_init(struct pcmcia_socket *sock)
 {
-	yenta_init(socket);
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	yenta_init(sock);
 
 	config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket));
 	config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket));
@@ -220,35 +198,26 @@
 	return 0;
 }
 
-static struct pci_socket_ops ti113x_ops = {
-	ti113x_open,
-	yenta_close,
-	ti113x_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
-};
-
-
-static int ti1250_open(pci_socket_t *socket)
+static int ti113x_override(struct yenta_socket *socket)
 {
-	ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+	ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
+	ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
+	ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
 
-	ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
+	ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
 	if (socket->cb_irq)
-		ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
-	ti113x_open(socket);
+		ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
+	ti_override(socket);
+	socket->socket.ops->init = ti113x_init;
 	return 0;
 }
 
-static int ti1250_init(pci_socket_t *socket)
+
+static int ti1250_init(struct pcmcia_socket *sock)
 {
-	yenta_init(socket);
-	ti113x_init(socket);
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	yenta_init(sock);
+	ti113x_init(sock);
 	ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX);
 	ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */
 	if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE))
@@ -260,18 +229,17 @@
 	return 0;
 }
 
-static struct pci_socket_ops ti1250_ops = {
-	ti1250_open,
-	yenta_close,
-	ti1250_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
-};
+static int ti1250_override(struct yenta_socket *socket)
+{
+	ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+
+	ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
+	if (socket->cb_irq)
+		ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
+	ti113x_override(socket);
+	socket->socket.ops->init = ti1250_init;
+	return 0;
+}
 
 #endif /* CONFIG_CARDBUS */
 
diff -ruN linux-original/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- linux-original/drivers/pcmcia/yenta.c	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/yenta.c	2003-05-17 23:26:16.000000000 +0200
@@ -1,5 +1,5 @@
 /*
- * Regular lowlevel cardbus driver ("yenta")
+ * Regular cardbus driver ("yenta")
  *
  * (C) Copyright 1999, 2000 Linus Torvalds
  *
@@ -7,6 +7,8 @@
  * Aug 2002: Manfred Spraul <manfred@colorfullife.com>
  * 	Dynamically adjust the size of the bridge resource
  * 	
+ * May 2003: Dominik Brodowski <linux@brodo.de>
+ * 	Merge pci_socket.c and yenta.c into one file
  */
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -26,6 +28,7 @@
 #include "yenta.h"
 #include "i82365.h"
 
+
 #if 0
 #define DEBUG(x,args...)	printk("%s: " x, __FUNCTION__, ##args)
 #else
@@ -41,20 +44,20 @@
  * regular memory space ("cb_xxx"), configuration space
  * ("config_xxx") and compatibility space ("exca_xxxx")
  */
-static inline u32 cb_readl(pci_socket_t *socket, unsigned reg)
+static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg)
 {
 	u32 val = readl(socket->base + reg);
 	DEBUG("%p %04x %08x\n", socket, reg, val);
 	return val;
 }
 
-static inline void cb_writel(pci_socket_t *socket, unsigned reg, u32 val)
+static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
 {
 	DEBUG("%p %04x %08x\n", socket, reg, val);
 	writel(val, socket->base + reg);
 }
 
-static inline u8 config_readb(pci_socket_t *socket, unsigned offset)
+static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
 {
 	u8 val;
 	pci_read_config_byte(socket->dev, offset, &val);
@@ -62,7 +65,7 @@
 	return val;
 }
 
-static inline u16 config_readw(pci_socket_t *socket, unsigned offset)
+static inline u16 config_readw(struct yenta_socket *socket, unsigned offset)
 {
 	u16 val;
 	pci_read_config_word(socket->dev, offset, &val);
@@ -70,7 +73,7 @@
 	return val;
 }
 
-static inline u32 config_readl(pci_socket_t *socket, unsigned offset)
+static inline u32 config_readl(struct yenta_socket *socket, unsigned offset)
 {
 	u32 val;
 	pci_read_config_dword(socket->dev, offset, &val);
@@ -78,32 +81,32 @@
 	return val;
 }
 
-static inline void config_writeb(pci_socket_t *socket, unsigned offset, u8 val)
+static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val)
 {
 	DEBUG("%p %04x %02x\n", socket, offset, val);
 	pci_write_config_byte(socket->dev, offset, val);
 }
 
-static inline void config_writew(pci_socket_t *socket, unsigned offset, u16 val)
+static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val)
 {
 	DEBUG("%p %04x %04x\n", socket, offset, val);
 	pci_write_config_word(socket->dev, offset, val);
 }
 
-static inline void config_writel(pci_socket_t *socket, unsigned offset, u32 val)
+static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val)
 {
 	DEBUG("%p %04x %08x\n", socket, offset, val);
 	pci_write_config_dword(socket->dev, offset, val);
 }
 
-static inline u8 exca_readb(pci_socket_t *socket, unsigned reg)
+static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg)
 {
 	u8 val = readb(socket->base + 0x800 + reg);
 	DEBUG("%p %04x %02x\n", socket, reg, val);
 	return val;
 }
 
-static inline u8 exca_readw(pci_socket_t *socket, unsigned reg)
+static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg)
 {
 	u16 val;
 	val = readb(socket->base + 0x800 + reg);
@@ -112,13 +115,13 @@
 	return val;
 }
 
-static inline void exca_writeb(pci_socket_t *socket, unsigned reg, u8 val)
+static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val)
 {
 	DEBUG("%p %04x %02x\n", socket, reg, val);
 	writeb(val, socket->base + 0x800 + reg);
 }
 
-static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val)
+static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
 {
 	DEBUG("%p %04x %04x\n", socket, reg, val);
 	writeb(val, socket->base + 0x800 + reg);
@@ -129,8 +132,9 @@
  * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
  * on what kind of card is inserted..
  */
-static int yenta_get_status(pci_socket_t *socket, unsigned int *value)
+static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	unsigned int val;
 	u32 state = cb_readl(socket, CB_SOCKET_STATE);
 
@@ -181,8 +185,9 @@
 	}
 }
 
-static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state)
+static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	u8 reg;
 	u32 control;
 
@@ -221,7 +226,7 @@
 	return 0;
 }
 
-static void yenta_set_power(pci_socket_t *socket, socket_state_t *state)
+static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
 {
 	u32 reg = 0;	/* CB_SC_STPCLK? */
 	switch (state->Vcc) {
@@ -238,8 +243,9 @@
 		cb_writel(socket, CB_SOCKET_CONTROL, reg);
 }
 
-static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state)
+static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	u16 bridge;
 
 	if (state->flags & SS_DEBOUNCED) {
@@ -300,8 +306,9 @@
 	return 0;
 }
 
-static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	int map;
 	unsigned char ioctl, addr, enable;
 
@@ -333,8 +340,9 @@
 	return 0;
 }
 
-static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	int map;
 	unsigned char addr, enable;
 	unsigned int start, stop, card_start;
@@ -386,12 +394,12 @@
 	return 0;
 }
 
-static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base)
+static void yenta_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
 {
 	/* Not done yet */
 }
 
-static unsigned int yenta_events(pci_socket_t *socket)
+static unsigned int yenta_events(struct yenta_socket *socket)
 {
 	u8 csc;
 	u32 cb_event;
@@ -418,7 +426,7 @@
 
 static void yenta_bh(void *data)
 {
-	pci_socket_t *socket = data;
+	struct yenta_socket *socket = data;
 	unsigned int events;
 
 	spin_lock_irq(&socket->event_lock);
@@ -432,7 +440,7 @@
 static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned int events;
-	pci_socket_t *socket = (pci_socket_t *) dev_id;
+	struct yenta_socket *socket = (struct yenta_socket *) dev_id;
 
 	events = yenta_events(socket);
 	if (events) {
@@ -447,7 +455,7 @@
 
 static void yenta_interrupt_wrapper(unsigned long data)
 {
-	pci_socket_t *socket = (pci_socket_t *) data;
+	struct yenta_socket *socket = (struct yenta_socket *) data;
 
 	yenta_interrupt(0, (void *)socket, NULL);
 	socket->poll_timer.expires = jiffies + HZ;
@@ -465,7 +473,7 @@
  */
 static u32 isa_interrupts = 0x0ef8;
 
-static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask)
+static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask)
 {
 	int i;
 	unsigned long val;
@@ -509,7 +517,7 @@
 /*
  * Set static data that doesn't need re-initializing..
  */
-static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask)
+static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask)
 {
 	socket->cap.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
 	socket->cap.map_size = 0x1000;
@@ -520,28 +528,38 @@
 	printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq);
 }
 
-static void yenta_clear_maps(pci_socket_t *socket)
+static int yenta_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+	*cap = socket->cap;
+
+	return 0;
+}
+
+
+static void yenta_clear_maps(struct yenta_socket *socket)
 {
 	int i;
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
 	pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
 
 	mem.sys_stop = 0x0fff;
-	yenta_set_socket(socket, &dead_socket);
+	yenta_set_socket(&socket->socket, &dead_socket);
 	for (i = 0; i < 2; i++) {
 		io.map = i;
-		yenta_set_io_map(socket, &io);
+		yenta_set_io_map(&socket->socket, &io);
 	}
 	for (i = 0; i < 5; i++) {
 		mem.map = i;
-		yenta_set_mem_map(socket, &mem);
+		yenta_set_mem_map(&socket->socket, &mem);
 	}
 }
 
 /*
  * Initialize the standard cardbus registers
  */
-static void yenta_config_init(pci_socket_t *socket)
+static void yenta_config_init(struct yenta_socket *socket)
 {
 	u16 bridge;
 	struct pci_dev *dev = socket->dev;
@@ -586,8 +604,9 @@
 }
 
 /* Called at resume and initialization events */
-static int yenta_init(pci_socket_t *socket)
+static int yenta_init(struct pcmcia_socket *sock)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	yenta_config_init(socket);
 	yenta_clear_maps(socket);
 
@@ -596,9 +615,11 @@
 	return 0;
 }
 
-static int yenta_suspend(pci_socket_t *socket)
+static int yenta_suspend(struct pcmcia_socket *sock)
 {
-	yenta_set_socket(socket, &dead_socket);
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+	yenta_set_socket(sock, &dead_socket);
 
 	/* Disable interrupts */
 	cb_writel(socket, CB_SOCKET_MASK, 0x0);
@@ -630,7 +651,7 @@
 #define BRIDGE_IO_MAX 256
 #define BRIDGE_IO_MIN 32
 
-static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
+static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type)
 {
 	struct pci_bus *bus;
 	struct resource *root, *res;
@@ -711,7 +732,7 @@
 /*
  * Allocate the bridge mappings for the device..
  */
-static void yenta_allocate_resources(pci_socket_t *socket)
+static void yenta_allocate_resources(struct yenta_socket *socket)
 {
 	yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH);
 	yenta_allocate_res(socket, 1, IORESOURCE_MEM);
@@ -719,10 +740,11 @@
 	yenta_allocate_res(socket, 3, IORESOURCE_IO);	/* PCI isn't clever enough to use this one yet */
 }
 
+
 /*
  * Free the bridge mappings for the device..
  */
-static void yenta_free_resources(pci_socket_t *socket)
+static void yenta_free_resources(struct yenta_socket *socket)
 {
 	int i;
 	for (i=0;i<4;i++) {
@@ -733,11 +755,15 @@
 		res->start = res->end = 0;
 	}
 }
+
+
 /*
  * Close it down - release our resources and go home..
  */
-static void yenta_close(pci_socket_t *sock)
+static void yenta_close(struct pci_dev *dev)
 {
+	struct yenta_socket *sock = pci_get_drvdata(dev);
+
 	/* Disable all events so we don't die in an IRQ storm */
 	cb_writel(sock, CB_SOCKET_MASK, 0x0);
 	exca_writeb(sock, I365_CSCINT, 0);
@@ -750,8 +776,37 @@
 	if (sock->base)
 		iounmap(sock->base);
 	yenta_free_resources(sock);
+
+	pcmcia_unregister_socket(&sock->socket);
+	pci_set_drvdata(dev, NULL);
 }
 
+
+static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+	socket->handler = handler;
+	socket->info = info;
+	return 0;
+}
+
+
+static struct pccard_operations yenta_socket_operations = {
+	.owner			= THIS_MODULE,
+	.init			= yenta_init,
+	.suspend		= yenta_suspend,
+	.register_callback	= yenta_register_callback,
+	.inquire_socket		= yenta_inquire_socket,
+	.get_status		= yenta_get_status,
+	.get_socket		= yenta_get_socket,
+	.set_socket		= yenta_set_socket,
+	.set_io_map		= yenta_set_io_map,
+	.set_mem_map		= yenta_set_mem_map,
+	.proc_setup		= yenta_proc_setup,
+};
+
+
 #include "ti113x.h"
 #include "ricoh.h"
 
@@ -760,49 +815,62 @@
  * initialization sequences etc details. List them here..
  */
 #define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y
-static struct cardbus_override_struct {
+struct cardbus_override_struct {
 	unsigned short vendor;
 	unsigned short device;
-	struct pci_socket_ops *op;
+	int (*override) (struct yenta_socket *socket);
 } cardbus_override[] = {
-	{ PD(TI,1130),	&ti113x_ops },
-	{ PD(TI,1031),	&ti_ops },
-	{ PD(TI,1131),	&ti113x_ops },
-	{ PD(TI,1250),	&ti1250_ops },
-	{ PD(TI,1220),	&ti_ops },
-	{ PD(TI,1221),	&ti_ops },
-	{ PD(TI,1210),	&ti_ops },
-	{ PD(TI,1450),	&ti_ops },
-	{ PD(TI,1225),	&ti_ops },
-	{ PD(TI,1251A),	&ti_ops },
-	{ PD(TI,1211),	&ti_ops },
-	{ PD(TI,1251B),	&ti_ops },
-	{ PD(TI,1410),	&ti1250_ops },
-	{ PD(TI,1420),	&ti_ops },
-	{ PD(TI,4410),	&ti_ops },
-	{ PD(TI,4451),	&ti_ops },
-
-	{ PD(RICOH,RL5C465), &ricoh_ops },
-	{ PD(RICOH,RL5C466), &ricoh_ops },
-	{ PD(RICOH,RL5C475), &ricoh_ops },
-	{ PD(RICOH,RL5C476), &ricoh_ops },
-	{ PD(RICOH,RL5C478), &ricoh_ops }
-};
-
-#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))
+	{ PD(TI,1130),	&ti113x_override },
+	{ PD(TI,1031),	&ti_override },
+	{ PD(TI,1131),	&ti113x_override },
+	{ PD(TI,1250),	&ti1250_override },
+	{ PD(TI,1220),	&ti_override },
+	{ PD(TI,1221),	&ti_override },
+	{ PD(TI,1210),	&ti_override },
+	{ PD(TI,1450),	&ti_override },
+	{ PD(TI,1225),	&ti_override },
+	{ PD(TI,1251A),	&ti_override },
+	{ PD(TI,1211),	&ti_override },
+	{ PD(TI,1251B),	&ti_override },
+	{ PD(TI,1410),	ti1250_override },
+	{ PD(TI,1420),	&ti_override },
+	{ PD(TI,4410),	&ti_override },
+	{ PD(TI,4451),	&ti_override },
+
+	{ PD(RICOH,RL5C465), &ricoh_override },
+	{ PD(RICOH,RL5C466), &ricoh_override },
+	{ PD(RICOH,RL5C475), &ricoh_override },
+	{ PD(RICOH,RL5C476), &ricoh_override },
+	{ PD(RICOH,RL5C478), &ricoh_override },
 
+	{ }, /* all zeroes */
+};
 
-extern int cardbus_register(struct pci_dev *p_dev);
 
 /*
  * Initialize a cardbus controller. Make sure we have a usable
  * interrupt, and that we can map the cardbus area. Fill in the
  * socket information structure..
  */
-static int yenta_open(pci_socket_t *socket)
+static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
-	int i;
-	struct pci_dev *dev = socket->dev;
+	struct yenta_socket *socket;
+	struct cardbus_override_struct *d;
+	
+	socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
+	if (!socket)
+		return -ENOMEM;
+	memset(socket, 0, sizeof(*socket));
+
+	/* prepare pcmcia_socket */
+	socket->socket.ops = &yenta_socket_operations;
+	socket->socket.dev.dev = &dev->dev;
+	socket->socket.driver_data = socket;
+
+	/* prepare struct yenta_socket */
+	socket->dev = dev;
+	pci_set_drvdata(dev, socket);
+	spin_lock_init(&socket->event_lock);
 
 	/*
 	 * Do some basic sanity checking..
@@ -833,16 +901,14 @@
 	socket->cb_irq = dev->irq;
 
 	/* Do we have special options for the device? */
-	for (i = 0; i < NR_OVERRIDES; i++) {
-		struct cardbus_override_struct *d = cardbus_override+i;
-		if (dev->vendor == d->vendor && dev->device == d->device) {
-			socket->op = d->op;
-			if (d->op->open) {
-				int retval = d->op->open(socket);
-				if (retval < 0)
-					return retval;
-			}
+	d = cardbus_override;
+	while (d->override) {
+		if ((dev->vendor == d->vendor) && (dev->device == d->device)) {
+			int retval = d->override(socket);
+			if (retval < 0)
+				return retval;
 		}
+		d++;
 	}
 
 	/* We must finish initialization here */
@@ -864,23 +930,58 @@
 	printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
 
 	/* Register it with the pcmcia layer.. */
-	return cardbus_register(dev);
+	return pcmcia_register_socket(&socket->socket);
 }
 
-/*
- * Standard plain cardbus - no frills, no extensions
- */
-struct pci_socket_ops yenta_operations = {
-	yenta_open,
-	yenta_close,
-	yenta_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
+
+static int yenta_dev_suspend (struct pci_dev *dev, u32 state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
+}
+
+
+static int yenta_dev_resume (struct pci_dev *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
+}
+
+
+static struct pci_device_id yenta_table [] __devinitdata = { {
+	.class		= PCI_CLASS_BRIDGE_CARDBUS << 8,
+	.class_mask	= ~0,
+
+	.vendor		= PCI_ANY_ID,
+	.device		= PCI_ANY_ID,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+}, { /* all zeroes */ }
 };
-EXPORT_SYMBOL(yenta_operations);
+MODULE_DEVICE_TABLE(pci, yenta_table);
+
+
+static struct pci_driver yenta_cardbus_driver = {
+	.name		= "yenta_cardbus",
+	.id_table	= yenta_table,
+	.probe		= yenta_probe,
+	.remove		= __devexit_p(yenta_close),
+	.suspend	= yenta_dev_suspend,
+	.resume		= yenta_dev_resume,
+};
+
+
+static int __init yenta_socket_init(void)
+{
+	return pci_register_driver (&yenta_cardbus_driver);
+}
+
+
+static void __exit yenta_socket_exit (void)
+{
+	pci_unregister_driver (&yenta_cardbus_driver);
+}
+
+
+module_init(yenta_socket_init);
+module_exit(yenta_socket_exit);
+
 MODULE_LICENSE("GPL");
diff -ruN linux-original/drivers/pcmcia/yenta.h linux/drivers/pcmcia/yenta.h
--- linux-original/drivers/pcmcia/yenta.h	2003-05-17 18:27:21.000000000 +0200
+++ linux/drivers/pcmcia/yenta.h	2003-05-17 23:19:50.000000000 +0200
@@ -2,7 +2,6 @@
 #define __YENTA_H
 
 #include <asm/io.h>
-#include "pci_socket.h"
 
 #define CB_SOCKET_EVENT		0x00
 #define    CB_CSTSEVENT		0x00000001	/* Card status event */
@@ -96,4 +95,23 @@
  */
 #define CB_MEM_PAGE(map)	(0x40 + (map))
 
+struct yenta_socket {
+	struct pci_dev *dev;
+	int cb_irq, io_irq;
+	void *base;
+	void (*handler)(void *, unsigned int);
+	void *info;
+	socket_cap_t cap;
+	spinlock_t event_lock;
+	unsigned int events;
+	struct work_struct tq_task;
+	struct timer_list poll_timer;
+
+	struct pcmcia_socket socket;
+
+	/* A few words of private data for special stuff of overrides... */
+	unsigned int private[8];
+};
+
+
 #endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030517/7b589b32/attachment.bin
From tim_small at yahoo.com  Sun May 18 01:16:41 2003
From: tim_small at yahoo.com (Tim Small)
Date: Sun May 18 00:16:52 2003
Subject: [PATCH] Support for TI1031 PCI -> PCMCIA bridges
In-Reply-To: <Pine.LNX.4.55.0305121241110.1420@marabou.research.att.com>
References: <3EBD2F2B.8070104@yahoo.com>
	<Pine.LNX.4.55.0305121241110.1420@marabou.research.att.com>
Message-ID: <3EC6C2D9.3010203@yahoo.com>

Hi Pavel et al,

I've got my TI1031 working under 2.4.20 now..  This is built on Pavel's 
original patch here:

http://lists.insecure.org/lists/linux-kernel/2003/Mar/0012.html

Pavel suggested this different change to pci.c (although I think that if you are presenting a CARDBUS header type then the cardbus vendor and device IDs should be present), but I don't know which is correct:

--- linux.orig/drivers/pci/pci.c
+++ linux/drivers/pci/pci.c
@@ -1405,12 +1405,17 @@ int pci_setup_device(struct pci_dev * de
 		break;
 
 	case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
-		if (class != PCI_CLASS_BRIDGE_CARDBUS)
+		switch (class) {
+		case PCI_CLASS_BRIDGE_CARDBUS:
+			pci_read_bases(dev, 1, 0);
+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
+			/* fallthrough */
+		case PCI_CLASS_BRIDGE_PCMCIA:
+			pci_read_irq(dev);
+		default:
 			goto bad;
-		pci_read_irq(dev);
-		pci_read_bases(dev, 1, 0);
-		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
-		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
+		}
 		break;
 
 	default:				    /* unknown header */


The patch below is against a stock 2.4.20 (and so includes Pavel's 
original)...  I'd be glad of any feedback - particularly if you have a 
TI PCI1031 based device (pretty rare, I think).  The sypnosis is:

. Change pci.c to allow PCMCIA bridge devices which present CARDBUS PCI 
header types (all TI PCI1031s do this, and possibly other similar devices)
. Change the yenta driver to correctly init the 1031, principally 
routing interrupts correctly, but also so that PCI <-> PCMCIA bridges 
are picked up (this is the only part of the patch that I'm not 
particularly sure about)..

Thanks!

Tim.
-------------- next part --------------
--- linux-2.4.20-old/drivers/pcmcia/yenta.c	2003-01-18 22:20:34.000000000 +0000
+++ linux-2.4.20-miniitx/drivers/pcmcia/yenta.c	2003-05-17 23:31:29.000000000 +0100
@@ -798,7 +798,7 @@
 	struct pci_socket_ops *op;
 } cardbus_override[] = {
 	{ PD(TI,1130),	&ti113x_ops },
-	{ PD(TI,1031),	&ti_ops },
+	{ PD(TI,1031),	&ti113x_ops },
 	{ PD(TI,1131),	&ti113x_ops },
 	{ PD(TI,1250),	&ti1250_ops },
 	{ PD(TI,1220),	&ti_ops },
--- linux-2.4.20-old/drivers/pcmcia/ti113x.h	2003-01-18 22:45:57.000000000 +0000
+++ linux-2.4.20-miniitx/drivers/pcmcia/ti113x.h	2003-05-17 23:30:28.000000000 +0100
@@ -32,6 +32,12 @@
 
 #include <linux/config.h>
 
+/* Register definitions for TI 103X PCI-to-PCMCIA bridges */ 
+
+#define TI103X_BRIDGE_CONTROL		0x003e  /* 16 bit */
+#define  TI103X_BRC_WRITEPOST_ENA	0x0400
+#define  TI103X_BRC_PCI_IREQ_ENA	0x0080
+
 /* Register definitions for TI 113X PCI-to-CardBus bridges */
 
 /* System Control Register */
@@ -167,6 +173,43 @@
 		new |= I365_INTR_ENA;
 	if (new != reg)
 		exca_writeb(socket, I365_INTCTL, new);
+
+/*
+ * If ISA interrupts don't work, then fall back to routing card
+ * interrupts to the PCI INTA/B interrupt lines (other methods
+ * are the PCI IRQSER pin, or direct connection to the ISA bus
+ * IRQ lines).
+ */
+	if (!socket->cap.irq_mask) {
+		printk (KERN_INFO "ti113x: Routing card interrupts to PCI\n");
+		if (socket->dev->device == PCI_DEVICE_ID_TI_1031) {
+			/* The 1030 may have this interface as well. */
+			int devctl;
+			u16 bridgectl;
+			devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
+			devctl &= ~TI113X_DCR_IMODE_SERIAL;
+
+			/* Route functional interrupts to PCI */
+			bridgectl = config_readw(socket, TI103X_BRIDGE_CONTROL);
+			bridgectl &= ~TI103X_BRC_PCI_IREQ_ENA;
+
+			config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
+			config_writew(socket, TI103X_BRIDGE_CONTROL, bridgectl);
+		} else {
+			int devctl, irqmux;
+			
+			devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
+			devctl &= ~TI113X_DCR_IMODE_MASK;
+			
+			/* Is twiddling this register safe on earlier chips? */
+			irqmux = config_readl(socket, TI122X_IRQMUX);
+			irqmux = (irqmux & ~0x0f) | 0x02; /* route INTA */
+			irqmux = (irqmux & ~0xf0) | 0x20; /* route INTB */
+			
+			config_writel(socket, TI122X_IRQMUX, irqmux);
+			config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
+		}
+	}		
 	return 0;
 }
 
--- linux-2.4.20-old/drivers/pci/pci.c	2003-01-18 22:21:11.000000000 +0000
+++ linux-2.4.20-miniitx/drivers/pci/pci.c	2003-05-09 13:12:06.000000000 +0100
@@ -1391,7 +1391,7 @@
 		break;
 
 	case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
-		if (class != PCI_CLASS_BRIDGE_CARDBUS)
+		if ((class != PCI_CLASS_BRIDGE_CARDBUS) && (class != PCI_CLASS_BRIDGE_PCMCIA))
 			goto bad;
 		pci_read_irq(dev);
 		pci_read_bases(dev, 1, 0);
--- linux-2.4.20-old/drivers/pcmcia/pci_socket.c	2001-12-21 17:41:55.000000000 +0000
+++ linux-2.4.20-miniitx/drivers/pcmcia/pci_socket.c	2003-05-17 23:49:14.000000000 +0100
@@ -235,7 +235,7 @@
 
 static struct pci_device_id cardbus_table [] __devinitdata = { {
 	class:		PCI_CLASS_BRIDGE_CARDBUS << 8,
-	class_mask:	~0,
+	class_mask:	~(0x02 << 8), /* also allow PCMCIA BRIDGES */
 
 	vendor:		PCI_ANY_ID,
 	device:		PCI_ANY_ID,
From hch at infradead.org  Sun May 18 07:58:58 2003
From: hch at infradead.org (Christoph Hellwig)
Date: Sun May 18 06:59:06 2003
Subject: [PATCH] pcmcia: unify yenta.c and pci_socket.c
In-Reply-To: <20030517214349.GA7882@brodo.de>;
	from linux@brodo.de on Sat, May 17, 2003 at 11:43:49PM +0200
References: <20030517214349.GA7882@brodo.de>
Message-ID: <20030518065858.A13857@infradead.org>

On Sat, May 17, 2003 at 11:43:49PM +0200, Dominik Brodowski wrote:
> +config CARDBUS
> +	bool
> +	depends on YENTA
> +	default y if YENTA
> +

Why should CONFIG_CARDBUS depend on one of the host bridge drivers?  (Even
if it's the only one currently..)


From linux at brodo.de  Sun May 18 10:04:29 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sun May 18 08:05:59 2003
Subject: [PATCH] pcmcia: unify yenta.c and pci_socket.c
In-Reply-To: <20030518065858.A13857@infradead.org>
References: <20030517214349.GA7882@brodo.de>
	<20030518065858.A13857@infradead.org>
Message-ID: <20030518070429.GA5257@brodo.de>

On Sun, May 18, 2003 at 06:58:58AM +0100, Christoph Hellwig wrote:
> On Sat, May 17, 2003 at 11:43:49PM +0200, Dominik Brodowski wrote:
> > +config CARDBUS
> > +	bool
> > +	depends on YENTA
> > +	default y if YENTA
> > +
> 
> Why should CONFIG_CARDBUS depend on one of the host bridge drivers?  (Even
> if it's the only one currently..)

Well, the clean way would be that CONFIG_YENTA depends on CONFIG_CARDBUS.
However, that'd mean two config options where currently one is enough. Also,
you can do

config CARDBUS
	bool
	depends on (YENTA || NEW_DRIVER)
	default y if (YENTA || NEW_DRIVER)


	Dominik-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030518/9038c38d/attachment.bin
From linux at brodo.de  Sun May 18 10:44:15 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Sun May 18 08:44:43 2003
Subject: [PATCH] pcmcia: remove socket_no from client_handle_t
Message-ID: <20030518074415.GA2067@brodo.de>

As "socket_no" is deprecated, replace it with struct pcmcia_socket in 
client_handle_t.

 bulkmem.c     |    2 +-
 cs.c          |   22 ++++++++++------------
 cs_internal.h |    5 ++---
 ds.c          |   22 +++++++++++-----------
 4 files changed, 24 insertions(+), 27 deletions(-)

diff -ruN linux-original/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c
--- linux-original/drivers/pcmcia/bulkmem.c	2003-05-17 23:13:38.000000000 +0200
+++ linux/drivers/pcmcia/bulkmem.c	2003-05-18 09:39:26.000000000 +0200
@@ -538,7 +538,7 @@
     
     if ((handle == NULL) || CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
-    s = get_s_info_by_nr((*handle)->Socket);
+    s = (socket_info_t *) (*handle)->Socket->s_info;
     if (open->Attributes & MEMORY_TYPE_AM)
 	region = s->a_region;
     else
diff -ruN linux-original/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- linux-original/drivers/pcmcia/cs.c	2003-05-17 23:13:38.000000000 +0200
+++ linux/drivers/pcmcia/cs.c	2003-05-18 09:39:26.000000000 +0200
@@ -306,7 +306,7 @@
 
 #define to_class_data(dev) dev->class_data
 
-socket_info_t * get_s_info_by_nr(unsigned int s_nr)
+static socket_info_t * get_s_info_by_nr(unsigned int s_nr)
 {
 	struct pcmcia_socket *tmp;
 	down(&pcmcia_socket_list_lock);
@@ -1053,7 +1053,7 @@
     client_t *client;
     socket_info_t *s;
 
-    s = SOCKET(req);
+    s = get_s_info_by_nr(req->Socket);
     if (!s)
 	    return CS_BAD_SOCKET;
 
@@ -1062,7 +1062,7 @@
     memset(client, '\0', sizeof(client_t));
     client->client_magic = CLIENT_MAGIC;
     strncpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
-    client->Socket = req->Socket;
+    client->Socket = s->sock;
     client->Function = req->Function;
     client->state = CLIENT_UNBOUND;
     client->erase_busy.next = &client->erase_busy;
@@ -1089,7 +1089,7 @@
     socket_info_t *s;
     memory_handle_t region;
     
-    s = SOCKET(req);
+    s = get_s_info_by_nr(req->Socket);
     if (!s)
 	return CS_BAD_SOCKET;
     
@@ -1119,7 +1119,7 @@
     socket_info_t *s;
     memory_handle_t region;
     u_long flags;
-    int i, sn;
+    int i;
     
     DEBUG(1, "cs: deregister_client(%p)\n", handle);
     if (CHECK_HANDLE(handle))
@@ -1140,8 +1140,6 @@
 	    if (region->mtd == handle) region->mtd = NULL;
     }
     
-    sn = handle->Socket; s = get_s_info_by_nr(sn);
-
     if ((handle->state & CLIENT_STALE) ||
 	(handle->Attributes & INFO_MASTER_CLIENT)) {
 	spin_lock_irqsave(&s->lock, flags);
@@ -1292,7 +1290,7 @@
     if ((*handle)->next == NULL) {
 	if (req->Attributes & CLIENT_THIS_SOCKET)
 	    return CS_NO_MORE_ITEMS;
-	s = get_s_info_by_nr((*handle)->Socket);
+	s = ((socket_info_t *) (*handle)->Socket->s_info);
 	if (s->clients == NULL)
 	    return CS_NO_MORE_ITEMS;
 	*handle = s->clients;
@@ -1310,7 +1308,7 @@
     int w;
 
     if (idx == 0)
-	s = get_s_info_by_nr(((client_handle_t)*handle)->Socket);
+	s = (socket_info_t *) (((client_handle_t)* handle)->Socket->s_info);
     else
 	s = (*handle)->sock;
     if (!(s->state & SOCKET_PRESENT))
@@ -1588,7 +1586,7 @@
 
     *handle = client;
     client->state &= ~CLIENT_UNBOUND;
-    client->Socket = socket->socket_no;
+    client->Socket = socket;
     client->Attributes = req->Attributes;
     client->EventMask = req->EventMask;
     client->event_handler = req->event_handler;
@@ -1789,7 +1787,7 @@
     
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
-    i = handle->Socket; s = get_s_info_by_nr(i);
+    s = SOCKET(handle);
     if (!(s->state & SOCKET_PRESENT))
 	return CS_NO_CARD;
     
@@ -2058,7 +2056,7 @@
     
     if (CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
-    s = get_s_info_by_nr((*handle)->Socket);
+    s = (socket_info_t *) ((*handle)->Socket->s_info);
     if (!(s->state & SOCKET_PRESENT))
 	return CS_NO_CARD;
     if (req->Attributes & (WIN_PAGED | WIN_SHARED))
diff -ruN linux-original/drivers/pcmcia/cs_internal.h linux/drivers/pcmcia/cs_internal.h
--- linux-original/drivers/pcmcia/cs_internal.h	2003-05-17 23:13:38.000000000 +0200
+++ linux/drivers/pcmcia/cs_internal.h	2003-05-18 09:39:26.000000000 +0200
@@ -39,7 +39,7 @@
 #define CLIENT_MAGIC 	0x51E6
 typedef struct client_t {
     u_short		client_magic;
-    socket_t		Socket;
+	struct pcmcia_socket 	*Socket;
     u_char		Function;
     dev_info_t		dev_info;
     u_int		Attributes;
@@ -183,8 +183,7 @@
 #define CHECK_HANDLE(h) \
     (((h) == NULL) || ((h)->client_magic != CLIENT_MAGIC))
 
-socket_info_t * get_s_info_by_nr(unsigned int socket);
-#define SOCKET(h) (get_s_info_by_nr(h->Socket))
+#define SOCKET(h) ((socket_info_t *) h->Socket->s_info)
 #define CONFIG(h) (&SOCKET(h)->config[(h)->Function])
 
 #define CHECK_REGION(r) \
diff -ruN linux-original/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux-original/drivers/pcmcia/ds.c	2003-05-17 22:03:15.000000000 +0200
+++ linux/drivers/pcmcia/ds.c	2003-05-18 09:39:38.000000000 +0200
@@ -108,7 +108,7 @@
 	socket_bind_t		*bind;
 	struct device		*socket_dev;
 	struct list_head	socket_list;
-	unsigned int		socket_no; /* deprecated */
+	struct pcmcia_socket	*socket;
 };
 
 #define SOCKET_PRESENT		0x01
@@ -363,14 +363,14 @@
 
     bind_req.dev_info = &mtd_info->dev_info;
     bind_req.Attributes = mtd_info->Attributes;
-    bind_req.Socket = bus_sock->socket_no;
+    bind_req.Socket = bus_sock->socket->socket_no;
     bind_req.CardOffset = mtd_info->CardOffset;
     ret = pcmcia_bind_mtd(&bind_req);
     if (ret != CS_SUCCESS) {
 	cs_error(NULL, BindMTD, ret);
-	printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d"
+	printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %p"
 	       " offset 0x%x\n",
-	       (char *)bind_req.dev_info, bus_sock->socket_no, bind_req.CardOffset);
+	       (char *)bind_req.dev_info, bus_sock, bind_req.CardOffset);
 	return -ENODEV;
     }
     return 0;
@@ -410,14 +410,14 @@
 	return -EBUSY;
     }
 
-    bind_req.Socket = s->socket_no;
+    bind_req.Socket = s->socket->socket_no;
     bind_req.Function = bind_info->function;
     bind_req.dev_info = (dev_info_t *) driver->drv.name;
     ret = pcmcia_bind_device(&bind_req);
     if (ret != CS_SUCCESS) {
 	cs_error(NULL, BindDevice, ret);
-	printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
-	       (char *)dev_info, s->socket_no);
+	printk(KERN_NOTICE "ds: unable to bind '%s' to socket %p\n",
+	       (char *)dev_info, s);
 	return -ENODEV;
     }
 
@@ -912,7 +912,7 @@
 	init_waitqueue_head(&s->queue);
 	init_waitqueue_head(&s->request);
 
-	s->socket_no = socket->socket_no;
+	s->socket = socket;
 
 	/* initialize data */
 	s->socket_dev = dev;
@@ -921,7 +921,7 @@
 	/* Set up hotline to Card Services */
 	client_reg.dev_info = bind.dev_info = &dev_info;
 
-	bind.Socket = s->socket_no;
+	bind.Socket = socket->socket_no;
 	bind.Function = BIND_FN_ALL;
 	ret = pcmcia_bind_device(&bind);
 	if (ret != CS_SUCCESS) {
@@ -965,7 +965,7 @@
 	down_write(&bus_socket_list_rwsem);
 	list_for_each_safe(list_loop, tmp_storage, &bus_socket_list) {
 		struct pcmcia_bus_socket *bus_sock = container_of(list_loop, struct pcmcia_bus_socket, socket_list);
-		if (bus_sock->socket_no == socket->socket_no) {
+		if (bus_sock->socket == socket) {
 			pcmcia_deregister_client(bus_sock->handle);
 			list_del(&bus_sock->socket_list);
 			kfree(bus_sock);
@@ -1041,7 +1041,7 @@
 	struct pcmcia_bus_socket * s;
 	down_read(&bus_socket_list_rwsem);
 	list_for_each_entry(s, &bus_socket_list, socket_list)
-		if (s->socket_no == nr) {
+		if (s->socket->socket_no == nr) {
 			up_read(&bus_socket_list_rwsem);
 			return s;
 		}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030518/b340684f/attachment.bin
From rmk at arm.linux.org.uk  Mon May 19 00:28:08 2003
From: rmk at arm.linux.org.uk (Russell King)
Date: Sun May 18 23:28:11 2003
Subject: [PATCH] pcmcia: socket callbacks now use "struct pcmcia_socket"
In-Reply-To: <20030517201603.GE1749@brodo.de>;
	from linux@brodo.de on Sat, May 17, 2003 at 10:16:03PM +0200
References: <20030517201603.GE1749@brodo.de>
Message-ID: <20030518232808.B4224@flint.arm.linux.org.uk>

On Sat, May 17, 2003 at 10:16:03PM +0200, Dominik Brodowski wrote:
> Passing a "socket number" between the core and the socket drivers is
> awful. Change it to "struct pcmcia_socket" (which will be filled with
> more life later).

I have an itch with this set of patches - we seem to be adding more
levels of indirection between the "cs" layer and the socket driver
itself.  I think this is becoming overly complex.

Is the idea to eventually kill socket_info_t in cs.c?  If this is
the case, can't we just rename socket_info_t to struct pcmcia_socket
(and keep the socket_info_t typedef around for a while.)

Also, imo the "thing" we pass to cs.c would be the class_device, and
the "thing" that cs.c passes back would likewise be the same pointer
- ie, the same class_device structure.  cs.c would then use
class_dev->class_data for its private data, and the socket driver
would then do a "pcmcia_class_drv_data(class_dev, parent_struct)"
which would return a pointer to the parent structure.

I think this would remove a fair amount of the triple/quadruple
indirection.

Comments?

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


From linux at brodo.de  Mon May 19 09:16:13 2003
From: linux at brodo.de (Dominik Brodowski)
Date: Mon May 19 07:16:26 2003
Subject: [PATCH] pcmcia: socket callbacks now use "struct pcmcia_socket"
In-Reply-To: <20030518232808.B4224@flint.arm.linux.org.uk>
References: <20030517201603.GE1749@brodo.de>
	<20030518232808.B4224@flint.arm.linux.org.uk>
Message-ID: <20030519061613.GA1299@brodo.de>

On Sun, May 18, 2003 at 11:28:08PM +0100, Russell King wrote:
> On Sat, May 17, 2003 at 10:16:03PM +0200, Dominik Brodowski wrote:
> > Passing a "socket number" between the core and the socket drivers is
> > awful. Change it to "struct pcmcia_socket" (which will be filled with
> > more life later).
> 
> I have an itch with this set of patches - we seem to be adding more
> levels of indirection between the "cs" layer and the socket driver
> itself.  I think this is becoming overly complex.

Only in the short term. And passing a "struct"  instead of a number is less
complex by itself.

> Is the idea to eventually kill socket_info_t in cs.c?  If this is
> the case, can't we just rename socket_info_t to struct pcmcia_socket
> (and keep the socket_info_t typedef around for a while.)

The idea is to integrate socket_info_t into struct pcmcia_socket. It can't
just be typedef'd as socket_info_t is widely used. Also, I want to keep
struct pcmcia_socket clean which means that only stuff is added to it which
is there to be kept, and available in a _sane_ format. Only exception, for
obvious reasons: void* s_info and socket_no.

> Also, imo the "thing" we pass to cs.c would be the class_device, and
> the "thing" that cs.c passes back would likewise be the same pointer
> - ie, the same class_device structure.  cs.c would then use
> class_dev->class_data for its private data, and the socket driver
> would then do a "pcmcia_class_drv_data(class_dev, parent_struct)"
> which would return a pointer to the parent structure.

IMHO this is ugly. Struct device, and also struct class_device are meant to
be embedded into a larger struct (just see
Documentation/driver-model/overview.txt, l.59ff.). Also, stuff like
socket_cap_t can and should be embedded in struct pcmcia_socket; and become
easily accessible by _both_ cs.c and the socket drivers.
 
> I think this would remove a fair amount of the triple/quadruple
> indirection.

As more and more functions within cs.c are converted from being based on
socket_info_t to being based on struct pcmcia_socket, one additional
level of indirection will go away. However, using struct class_device will
only add more levels of indirection as both cs.c and the socket drivers will
need access to struct pcmcia_socket.

I agree that the current assumption of

class_device->class_data == container_of(class_device, struct pcmcia_socket, class_device)

is not strictly necessary. But it inflicts less harm than the sorts of
indirections you propose.

> Comments?

I prefer the struct pcmcia_socket I sent in my patches, but I won't object
to any other patch as long as it works towards the same solution -- clean up
the cs.c / socket drivers interaction.

	Dominik
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030519/7be01379/attachment.bin
From proski at gnu.org  Mon May 19 13:21:30 2003
From: proski at gnu.org (Pavel Roskin)
Date: Mon May 19 17:21:27 2003
Subject: [PATCH] Support for TI1031 PCI -> PCMCIA bridges
In-Reply-To: <3EC6C2D9.3010203@yahoo.com>
References: <3EBD2F2B.8070104@yahoo.com>
	<Pine.LNX.4.55.0305121241110.1420@marabou.research.att.com>
	<3EC6C2D9.3010203@yahoo.com>
Message-ID: <Pine.LNX.4.55.0305191157460.4775@marabou.research.att.com>

On Sun, 18 May 2003, Tim Small wrote:

> I've got my TI1031 working under 2.4.20 now..  This is built on Pavel's
> original patch here:

Please, let's forget my patch for pci.c.  As I said, I don't know much
about PCI subsystem, and I don't like that you base your patch on
something I don't understand and put my name on it.  Perhaps I shouldn't
have posted that patch at all.

> The patch below is against a stock 2.4.20 (and so includes Pavel's
> original)...  I'd be glad of any feedback - particularly if you have a
> TI PCI1031 based device (pretty rare, I think).  The synopsis is:
>
> . Change pci.c to allow PCMCIA bridge devices which present CARDBUS PCI
> header types (all TI PCI1031s do this, and possibly other similar devices)

Yes, that's important to get right.

> . Change the yenta driver to correctly init the 1031, principally
> routing interrupts correctly, but also so that PCI <-> PCMCIA bridges
> are picked up (this is the only part of the patch that I'm not
> particularly sure about)..

My patch is already in 2.4.21-rc2-ac2.  Is it sufficient to make your card
work?  I'm concerned that the driver in 2.5.x kernels takes a different
approach and may not work for your card.

Linux 2.4.21-rc2-ac2 checks ISA interrupts and it none have been detected,
it reroutes interrupts to PCI.  Linux 2.5.69 routes interrupts to PCI for
specific devices, namely TI 1250 and TI 1410.  If your card also needs to
reroute the interrupts to PCI, it will be a strong case for forward
porting my patch from 2.4.21-rc2-ac2 to 2.5.x series.

-- 
Regards,
Pavel Roskin

From proski at gnu.org  Sat May 24 21:59:38 2003
From: proski at gnu.org (Pavel Roskin)
Date: Sun May 25 10:34:44 2003
Subject: [PATCH] pcmcia: socket callbacks now use "struct pcmcia_socket"
In-Reply-To: <20030519061613.GA1299@brodo.de>
References: <20030517201603.GE1749@brodo.de>
	<20030518232808.B4224@flint.arm.linux.org.uk>
	<20030519061613.GA1299@brodo.de>
Message-ID: <Pine.LNX.4.55.0305241950001.14179@marabou.research.att.com>

On Mon, 19 May 2003, Dominik Brodowski wrote:

> I prefer the struct pcmcia_socket I sent in my patches, but I won't object
> to any other patch as long as it works towards the same solution -- clean up
> the cs.c / socket drivers interaction.

Dominik, your patch doesn't apply to the latest bitkeeper snapshots.
There are significant overlaps between the changes, but as I understand
it, the socket number is still used in cs.c.

Are you interested in porting your patch to the latest snapshots or it
won't be applied?

-- 
Regards,
Pavel Roskin

From rmk at arm.linux.org.uk  Sun May 25 22:26:08 2003
From: rmk at arm.linux.org.uk (Russell King)
Date: Sun May 25 21:25:30 2003
Subject: [PATCH] pcmcia: socket callbacks now use "struct pcmcia_socket"
In-Reply-To: <Pine.LNX.4.55.0305241950001.14179@marabou.research.att.com>;
	from proski@gnu.org on Sat, May 24, 2003 at 08:59:38PM -0400
References: <20030517201603.GE1749@brodo.de>
	<20030518232808.B4224@flint.arm.linux.org.uk> <20030519061613.GA1299@brodo.de>
	<Pine.LNX.4.55.0305241950001.14179@marabou.research.att.com>
Message-ID: <20030525212608.A14236@flint.arm.linux.org.uk>

On Sat, May 24, 2003 at 08:59:38PM -0400, Pavel Roskin wrote:
> On Mon, 19 May 2003, Dominik Brodowski wrote:
> 
> > I prefer the struct pcmcia_socket I sent in my patches, but I won't object
> > to any other patch as long as it works towards the same solution -- clean up
> > the cs.c / socket drivers interaction.
> 
> Dominik, your patch doesn't apply to the latest bitkeeper snapshots.
> There are significant overlaps between the changes, but as I understand
> it, the socket number is still used in cs.c.
> 
> Are you interested in porting your patch to the latest snapshots or it
> won't be applied?

I keep my PCMCIA tree behind Linus' latest, so when I don't have time to
apply Dominiks patches, I can normally apply it to a version of the tree
which it does apply to, and then do the merges afterwards.

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


From proski at gnu.org  Sun May 25 18:02:17 2003
From: proski at gnu.org (Pavel Roskin)
Date: Sun May 25 22:01:38 2003
Subject: [PATCH] Re: Crash when unloading yenta_socket in Linux 2.5.69
In-Reply-To: <Pine.LNX.4.44.0305060132020.2546-200000@localhost.localdomain>
Message-ID: <Pine.LNX.4.44.0305251659440.2323-100000@localhost.localdomain>

Hello, Russell!

Perhaps my patch was lost because I didn't mark it as patch:
http://lists.infradead.org/pipermail/linux-pcmcia/2003-May/000060.html

It's still needed in 2.5.69-bk18.  It fixes unloading yenta_socket.

-- 
Regards,
Pavel Roskin


From rmk at arm.linux.org.uk  Mon May 26 00:14:24 2003
From: rmk at arm.linux.org.uk (Russell King)
Date: Sun May 25 23:13:43 2003
Subject: [PATCH] pcmcia: new socket initialization interface
In-Reply-To: <20030517201404.GD1749@brodo.de>;
	from linux@brodo.de on Sat, May 17, 2003 at 10:14:04PM +0200
References: <20030517201404.GD1749@brodo.de>
Message-ID: <20030525231424.B14236@flint.arm.linux.org.uk>

On Sat, May 17, 2003 at 10:14:04PM +0200, Dominik Brodowski wrote:
> @@ -409,85 +466,78 @@
>  /**
>   * pcmcia_register_socket - add a new pcmcia socket device
>   */
> -int pcmcia_register_socket(struct class_device *class_dev)
> +unsigned int pcmcia_register_socket(struct pcmcia_socket *socket)

Why this change?  We still return -ENOMEM from here, so we shouldn't
change this to unsigned.

Also, with all these patches applied, I'm seeing a deadlock in
get_s_info_by_nr() - we have taken the lock in pcmcia_socket_dev_suspend().
Would a read/write lock be more appropriate for pcmcia_socket_list_lock?

[<c0237270>] (schedule+0x0/0x45c) from [<c02256a0>] (__down+0xe0/0x170)
[<c02255c0>] (__down+0x0/0x170) from [<c02259ac>] (__down_failed+0xc/0x20)
[<c033fed0>] (get_s_info_by_nr+0x0/0xcc) from [<c034234c>] (pcmcia_release_configuration+0x6c/0x140)
[<c03422e0>] (pcmcia_release_configuration+0x0/0x140) from [<c0343804>] (CardServices+0x27c/0x398)
[<c0343588>] (CardServices+0x0/0x398) from [<c03216b4>] (pcnet_event+0x25c/0x268)
[<c0321458>] (pcnet_event+0x0/0x268) from [<c0340800>] (send_event+0x70/0x80)
[<c0340790>] (send_event+0x0/0x80) from [<c0340d20>] (socket_suspend+0x34/0x60)
[<c0340cec>] (socket_suspend+0x0/0x60) from [<c034006c>] (pcmcia_socket_dev_suspend+0xd0/0x100)
[<c033ff9c>] (pcmcia_socket_dev_suspend+0x0/0x100) from [<c02ea204>] (device_suspend+0x88/0xb8)
[<c02ea17c>] (device_suspend+0x0/0xb8) from [<c0229184>] (suspend+0x80/0xf4)
[<c0229104>] (suspend+0x0/0xf4) from [<c0229240>] (pm_sysctl_proc_handler+0x48/0x50)
[<c02291f8>] (pm_sysctl_proc_handler+0x0/0x50) from [<c024147c>] (do_rw_proc+0x9c/0xa8)
[<c02413e0>] (do_rw_proc+0x0/0xa8) from [<c02414f4>] (proc_writesys+0x34/0x38)
[<c02414c0>] (proc_writesys+0x0/0x38) from [<c0275a14>] (vfs_write+0xd8/0x124)
[<c027593c>] (vfs_write+0x0/0x124) from [<c0275ae4>] (sys_write+0x38/0x4c)
[<c0275aac>] (sys_write+0x0/0x4c) from [<c0222300>] (ret_fast_syscall+0x0/0x30)


-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


