Commit 507e658a authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-pcmcia

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents de05cbbb b55cdbfa
...@@ -18,7 +18,7 @@ obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o ...@@ -18,7 +18,7 @@ obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o pxa2xx_cs.o obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o pxa2xx_cs.o
pcmcia_core-y += cistpl.o rsrc_mgr.o bulkmem.o cs.o pcmcia_core-y += cistpl.o rsrc_mgr.o bulkmem.o cs.o socket_sysfs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
sa11xx_core-y += soc_common.o sa11xx_base.o sa11xx_core-y += soc_common.o sa11xx_base.o
......
...@@ -264,7 +264,10 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) ...@@ -264,7 +264,10 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
goto err; goto err;
wait_for_completion(&socket->thread_done); wait_for_completion(&socket->thread_done);
BUG_ON(!socket->thread); if(!socket->thread) {
printk(KERN_WARNING "PCMCIA: warning: socket thread for socket %p did not start\n", socket);
return -EIO;
}
pcmcia_parse_events(socket, SS_DETECT); pcmcia_parse_events(socket, SS_DETECT);
return 0; return 0;
...@@ -678,9 +681,8 @@ static int pccardd(void *__skt) ...@@ -678,9 +681,8 @@ static int pccardd(void *__skt)
int ret; int ret;
daemonize("pccardd"); daemonize("pccardd");
skt->thread = current;
complete(&skt->thread_done);
skt->thread = current;
skt->socket = dead_socket; skt->socket = dead_socket;
skt->ops->init(skt); skt->ops->init(skt);
skt->ops->set_socket(skt, &skt->socket); skt->ops->set_socket(skt, &skt->socket);
...@@ -690,7 +692,10 @@ static int pccardd(void *__skt) ...@@ -690,7 +692,10 @@ static int pccardd(void *__skt)
if (ret) { if (ret) {
printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n", printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n",
skt); skt);
skt->thread = NULL;
complete_and_exit(&skt->thread_done, 0);
} }
complete(&skt->thread_done);
add_wait_queue(&skt->thread_wait, &wait); add_wait_queue(&skt->thread_wait, &wait);
for (;;) { for (;;) {
...@@ -2031,16 +2036,18 @@ int pcmcia_eject_card(struct pcmcia_socket *skt) ...@@ -2031,16 +2036,18 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
down(&skt->skt_sem); down(&skt->skt_sem);
do { do {
if (!(skt->state & SOCKET_PRESENT)) { if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD; ret = -ENODEV;
break; break;
} }
ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW); ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);
if (ret != 0) if (ret != 0) {
ret = -EINVAL;
break; break;
}
socket_remove(skt); socket_remove(skt);
ret = CS_SUCCESS; ret = 0;
} while (0); } while (0);
up(&skt->skt_sem); up(&skt->skt_sem);
...@@ -2056,14 +2063,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) ...@@ -2056,14 +2063,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
down(&skt->skt_sem); down(&skt->skt_sem);
do { do {
if (skt->state & SOCKET_PRESENT) { if (skt->state & SOCKET_PRESENT) {
ret = CS_IN_USE; ret = -EBUSY;
break; break;
} }
if (socket_insert(skt) == CS_NO_CARD) { if (socket_insert(skt) == CS_NO_CARD) {
ret = CS_NO_CARD; ret = -ENODEV;
break; break;
} }
ret = CS_SUCCESS; ret = 0;
} while (0); } while (0);
up(&skt->skt_sem); up(&skt->skt_sem);
...@@ -2161,16 +2168,21 @@ EXPORT_SYMBOL(pcmcia_socket_class); ...@@ -2161,16 +2168,21 @@ EXPORT_SYMBOL(pcmcia_socket_class);
static int __init init_pcmcia_cs(void) static int __init init_pcmcia_cs(void)
{ {
int ret;
printk(KERN_INFO "%s\n", release); printk(KERN_INFO "%s\n", release);
printk(KERN_INFO " %s\n", options); printk(KERN_INFO " %s\n", options);
return class_register(&pcmcia_socket_class); ret = class_register(&pcmcia_socket_class);
if (ret)
return (ret);
return class_interface_register(&pccard_sysfs_interface);
} }
static void __exit exit_pcmcia_cs(void) static void __exit exit_pcmcia_cs(void)
{ {
printk(KERN_INFO "unloading Kernel Card Services\n"); printk(KERN_INFO "unloading Kernel Card Services\n");
release_resource_db(); release_resource_db();
class_interface_unregister(&pccard_sysfs_interface);
class_unregister(&pcmcia_socket_class); class_unregister(&pcmcia_socket_class);
} }
......
...@@ -192,6 +192,10 @@ void undo_irq(u_int Attributes, int irq); ...@@ -192,6 +192,10 @@ void undo_irq(u_int Attributes, int irq);
int adjust_resource_info(client_handle_t handle, adjust_t *adj); int adjust_resource_info(client_handle_t handle, adjust_t *adj);
void release_resource_db(void); void release_resource_db(void);
/* In socket_sysfs.c */
extern struct class_interface pccard_sysfs_interface;
/* In cs.c */
extern struct rw_semaphore pcmcia_socket_list_rwsem; extern struct rw_semaphore pcmcia_socket_list_rwsem;
extern struct list_head pcmcia_socket_list; extern struct list_head pcmcia_socket_list;
......
...@@ -973,10 +973,10 @@ static int ds_ioctl(struct inode * inode, struct file * file, ...@@ -973,10 +973,10 @@ static int ds_ioctl(struct inode * inode, struct file * file,
ret = pcmcia_resume_card(s->parent); ret = pcmcia_resume_card(s->parent);
break; break;
case DS_EJECT_CARD: case DS_EJECT_CARD:
ret = pcmcia_eject_card(s->parent); err = pcmcia_eject_card(s->parent);
break; break;
case DS_INSERT_CARD: case DS_INSERT_CARD:
ret = pcmcia_insert_card(s->parent); err = pcmcia_insert_card(s->parent);
break; break;
case DS_ACCESS_CONFIGURATION_REGISTER: case DS_ACCESS_CONFIGURATION_REGISTER:
if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
......
/*
* socket_sysfs.c -- most of socket-related sysfs output
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* (C) 2003 - 2004 Dominik Brodowski
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/pci.h>
#include <linux/device.h>
#include <linux/suspend.h>
#include <asm/system.h>
#include <asm/irq.h>
#define IN_CARD_SERVICES
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/cs.h>
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
#include "cs_internal.h"
#define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev)
static ssize_t pccard_show_type(struct class_device *dev, char *buf)
{
int val;
struct pcmcia_socket *s = to_socket(dev);
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
s->ops->get_status(s, &val);
if (val & SS_CARDBUS)
return sprintf(buf, "32-bit\n");
if (val & SS_DETECT)
return sprintf(buf, "16-bit\n");
return sprintf(buf, "invalid\n");
}
static CLASS_DEVICE_ATTR(card_type, 0400, pccard_show_type, NULL);
static ssize_t pccard_show_voltage(struct class_device *dev, char *buf)
{
int val;
struct pcmcia_socket *s = to_socket(dev);
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
s->ops->get_status(s, &val);
if (val & SS_3VCARD)
return sprintf(buf, "3.3V\n");
if (val & SS_XVCARD)
return sprintf(buf, "X.XV\n");
return sprintf(buf, "5.0V\n");
}
static CLASS_DEVICE_ATTR(card_voltage, 0400, pccard_show_voltage, NULL);
static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
{
struct pcmcia_socket *s = to_socket(dev);
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10);
}
static CLASS_DEVICE_ATTR(card_vpp, 0400, pccard_show_vpp, NULL);
static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
{
struct pcmcia_socket *s = to_socket(dev);
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10);
}
static CLASS_DEVICE_ATTR(card_vcc, 0400, pccard_show_vcc, NULL);
static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, size_t count)
{
ssize_t ret;
struct pcmcia_socket *s = to_socket(dev);
if (!count)
return -EINVAL;
ret = pcmcia_insert_card(s);
return ret ? ret : count;
}
static CLASS_DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert);
static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, size_t count)
{
ssize_t ret;
struct pcmcia_socket *s = to_socket(dev);
if (!count)
return -EINVAL;
ret = pcmcia_eject_card(s);
return ret ? ret : count;
}
static CLASS_DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject);
static struct class_device_attribute *pccard_socket_attributes[] = {
&class_device_attr_card_type,
&class_device_attr_card_voltage,
&class_device_attr_card_vpp,
&class_device_attr_card_vcc,
&class_device_attr_card_insert,
&class_device_attr_card_eject,
NULL,
};
static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev)
{
struct class_device_attribute **attr;
int ret = 0;
for (attr = pccard_socket_attributes; *attr; attr++) {
ret = class_device_create_file(class_dev, *attr);
if (ret)
break;
}
return ret;
}
static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev)
{
struct class_device_attribute **attr;
for (attr = pccard_socket_attributes; *attr; attr++)
class_device_remove_file(class_dev, *attr);
}
struct class_interface pccard_sysfs_interface = {
.class = &pcmcia_socket_class,
.add = &pccard_sysfs_add_socket,
.remove = __devexit_p(&pccard_sysfs_remove_socket),
};
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