[PATCH] pcmcia: new socket initialization interface
Dominik Brodowski
linux at brodo.de
Sat May 17 23:14:04 BST 2003
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
More information about the linux-pcmcia
mailing list