Commit fd0dacff authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Linus Torvalds

[PATCH] pcmcia: add socket_offset for multiple pci_sockets, correct suspend&resume

 - suspend & remove for pci_socket was broken -- thanks to Paul
   Mackerras for noting this
 - to correctly initialize multiple pci_socket devices, a sock_offset is
   needed.
 - s_info doesn't need to be an array.
parent ade30b83
...@@ -337,13 +337,14 @@ int pcmcia_register_socket(struct device *dev) ...@@ -337,13 +337,14 @@ int pcmcia_register_socket(struct device *dev)
return -ENOMEM; return -ENOMEM;
memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t)); memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t));
cls_d->s_info = s_info;
/* socket initialization */ /* socket initialization */
for (i = 0; i < cls_d->nsock; i++) { for (i = 0; i < cls_d->nsock; i++) {
socket_info_t *s = &s_info[i]; socket_info_t *s = &s_info[i];
cls_d->s_info[i] = s;
s->ss_entry = cls_d->ops; s->ss_entry = cls_d->ops;
s->sock = i; s->sock = i + cls_d->sock_offset;
/* base address = 0, map = 0 */ /* base address = 0, map = 0 */
s->cis_mem.flags = 0; s->cis_mem.flags = 0;
...@@ -359,7 +360,7 @@ int pcmcia_register_socket(struct device *dev) ...@@ -359,7 +360,7 @@ int pcmcia_register_socket(struct device *dev)
if (j == sockets) sockets++; if (j == sockets) sockets++;
init_socket(s); init_socket(s);
s->ss_entry->inquire_socket(i, &s->cap); s->ss_entry->inquire_socket(s->sock, &s->cap);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
if (proc_pccard) { if (proc_pccard) {
char name[3]; char name[3];
......
...@@ -171,6 +171,16 @@ static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_sock ...@@ -171,6 +171,16 @@ static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_sock
int err; int err;
memset(socket, 0, sizeof(*socket)); 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.use_bus_pm = 1;
dev->dev.class_data = &socket->cls_d;
/* prepare pci_socket_t */
socket->dev = dev; socket->dev = dev;
socket->op = ops; socket->op = ops;
pci_set_drvdata(dev, socket); pci_set_drvdata(dev, socket);
...@@ -186,18 +196,6 @@ static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_sock ...@@ -186,18 +196,6 @@ static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_sock
int cardbus_register(struct pci_dev *p_dev) int cardbus_register(struct pci_dev *p_dev)
{ {
pci_socket_t *socket = pci_get_drvdata(p_dev);
struct pcmcia_socket_class_data *cls_d;
if (!socket)
return -EINVAL;
cls_d = &socket->cls_d;
cls_d->nsock = 1; /* yenta is 1, no other low-level driver uses
this yet */
cls_d->ops = &pci_socket_operations;
cls_d->use_bus_pm = 1;
p_dev->dev.class_data = cls_d;
return 0; return 0;
} }
...@@ -227,14 +225,16 @@ static void __devexit cardbus_remove (struct pci_dev *dev) ...@@ -227,14 +225,16 @@ static void __devexit cardbus_remove (struct pci_dev *dev)
static int cardbus_suspend (struct pci_dev *dev, u32 state) static int cardbus_suspend (struct pci_dev *dev, u32 state)
{ {
pci_socket_t *socket = pci_get_drvdata(dev); pci_socket_t *socket = pci_get_drvdata(dev);
pcmcia_suspend_socket (socket->pcmcia_socket); if (socket && socket->cls_d.s_info)
pcmcia_suspend_socket (socket->cls_d.s_info);
return 0; return 0;
} }
static int cardbus_resume (struct pci_dev *dev) static int cardbus_resume (struct pci_dev *dev)
{ {
pci_socket_t *socket = pci_get_drvdata(dev); pci_socket_t *socket = pci_get_drvdata(dev);
pcmcia_resume_socket (socket->pcmcia_socket); if (socket && socket->cls_d.s_info)
pcmcia_resume_socket (socket->cls_d.s_info);
return 0; return 0;
} }
......
...@@ -20,7 +20,6 @@ typedef struct pci_socket { ...@@ -20,7 +20,6 @@ typedef struct pci_socket {
socket_cap_t cap; socket_cap_t cap;
spinlock_t event_lock; spinlock_t event_lock;
unsigned int events; unsigned int events;
struct socket_info_t *pcmcia_socket;
struct work_struct tq_task; struct work_struct tq_task;
struct timer_list poll_timer; struct timer_list poll_timer;
......
...@@ -145,12 +145,12 @@ struct pccard_operations { ...@@ -145,12 +145,12 @@ struct pccard_operations {
* Calls to set up low-level "Socket Services" drivers * Calls to set up low-level "Socket Services" drivers
*/ */
#define MAX_SOCKETS_PER_DEV 8
struct pcmcia_socket_class_data { struct pcmcia_socket_class_data {
unsigned int nsock; /* number of sockets */ 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 */ struct pccard_operations *ops; /* see above */
void *s_info[MAX_SOCKETS_PER_DEV]; /* socket_info_t */ void *s_info; /* socket_info_t */
unsigned int use_bus_pm; unsigned int use_bus_pm;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment