pcmcia: add socket_offset for multiple pci_sockets, correct suspend&resume
PATCH 1/1 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.
Please apply,
Dominik
drivers/pcmcia/cs.c +3 -2
@@ -337,13 +337,14 @@return -ENOMEM ;memset (s_info,0 , cls_d->nsock *sizeof (socket_info_t)); + cls_d->s_info = s_info; +/* socket initialization */ for (i =0 ; i < cls_d->nsock; i++) {socket_info_t *s = &s_info[i]; - cls_d->s_info[i] = s; s->ss_entry = cls_d->ops; - s->sock = i; + s->sock = i + cls_d->sock_offset;/* base address = 0, map = 0 */ s->cis_mem.flags =0 ;
drivers/pcmcia/pci_socket.c +14 -14
@@ -171,6 +171,16 @@int err;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->op = ops;pci_set_drvdata (dev, socket);
@@ -186,18 +196,6 @@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 ; }
@@ -227,14 +225,16 @@static int cardbus_suspend (struct pci_dev *dev,u32 state) {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 ; }static int cardbus_resume (struct pci_dev *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 ; }
drivers/pcmcia/pci_socket.h +0 -1
@@ -20,7 +20,6 @@socket_cap_t cap;spinlock_t event_lock;unsigned int events; -struct socket_info_t *pcmcia_socket;struct work_struct tq_task;struct timer_list poll_timer;
include/pcmcia/ss.h +3 -3
@@ -145,12 +145,12 @@* Calls to set up low-level "Socket Services" drivers */ -#define MAX_SOCKETS_PER_DEV 8 -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[MAX_SOCKETS_PER_DEV ];/* socket_info_t */ +void *s_info;/* socket_info_t */ unsigned int use_bus_pm; };
Quoted 10 lines · Dominik Brodowski
diff -ruN
linux-original/drivers/pcmcia/cs.clinux/drivers/pcmcia/cs.cdrivers/pcmcia/cs.c +2
-0@@ -337,13 +337,14 @@return -ENOMEM ;memset (s_info,0 , cls_d->nsock *sizeof (socket_info_t)); + cls_d->s_info = s_info; +/* socket initialization */
drivers/pcmcia/cs.c line 350
Quoted 10 lines
drivers/pcmcia/cs.c +1
-2for (i =0 ; i < cls_d->nsock; i++) {socket_info_t *s = &s_info[i]; - cls_d->s_info[i] = s; s->ss_entry = cls_d->ops; - s->sock = i; + s->sock = i + cls_d->sock_offset;/* base address = 0, map = 0 */ s->cis_mem.flags =0 ;
I think you missed changing:
s->ss_entry->inquire_socket(i, &s->cap);
to:
s->ss_entry->inquire_socket(s->sock, &s->cap);
otherwise both sockets end up pointing at the same cb_dev.
Signature · 2 lines
Russell King ([email protected]) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html
PATCH 1/1 pcmcia: add socket_offset for multiple pci_sockets, correct suspend&resume
Thanks for the hint, Russell -- here comes an updated patch:
- 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.
Please apply,
Dominik
drivers/pcmcia/cs.c +4 -3
@@ -337,13 +337,14 @@return -ENOMEM ;memset (s_info,0 , cls_d->nsock *sizeof (socket_info_t)); + cls_d->s_info = s_info; +/* socket initialization */ for (i =0 ; i < cls_d->nsock; i++) {socket_info_t *s = &s_info[i]; - cls_d->s_info[i] = s; s->ss_entry = cls_d->ops; - s->sock = i; + s->sock = i + cls_d->sock_offset;/* base address = 0, map = 0 */ s->cis_mem.flags =0 ;
@@ -359,7 +360,7 @@if (j == sockets) sockets++;init_socket (s); - s->ss_entry->inquire_socket (i, &s->cap); + s->ss_entry->inquire_socket (s->sock, &s->cap);#ifdef CONFIG_PROC_FS if (proc_pccard) {char name[3 ];
drivers/pcmcia/pci_socket.c +14 -14
@@ -171,6 +171,16 @@int err;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->op = ops;pci_set_drvdata (dev, socket);
@@ -186,18 +196,6 @@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 ; }
@@ -227,14 +225,16 @@static int cardbus_suspend (struct pci_dev *dev,u32 state) {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 ; }static int cardbus_resume (struct pci_dev *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 ; }
drivers/pcmcia/pci_socket.h +0 -1
@@ -20,7 +20,6 @@socket_cap_t cap;spinlock_t event_lock;unsigned int events; -struct socket_info_t *pcmcia_socket;struct work_struct tq_task;struct timer_list poll_timer;
include/pcmcia/ss.h +3 -3
@@ -145,12 +145,12 @@* Calls to set up low-level "Socket Services" drivers */ -#define MAX_SOCKETS_PER_DEV 8 -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[MAX_SOCKETS_PER_DEV ];/* socket_info_t */ +void *s_info;/* socket_info_t */ unsigned int use_bus_pm; };