[PATCH 5/5] card insert / eject
Dominik Brodowski
linux at dominikbrodowski.de
Thu May 20 05:47:51 EDT 2004
On Tue, May 18, 2004 at 07:53:57PM +0100, Russell King wrote:
> > +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 (s->state & SOCKET_PRESENT)
> > + return -EINVAL;
>
> This introduces a nice race condition - pcmcia_insert_card already checks
> this in a race-free manner so I suggest deleting this test.
Well, it was meant as a "fast error code path", but I have no strong
feelings about it, so I'll remove it.
>
> > + if (!count)
> > + return -EINVAL;
> > +
> > + ret = pcmcia_insert_card(s);
>
> Also, pcmcia_insert_card() returns 0 for success, non-zero positive for
> failure, which means that:
>
> > +
> > + return ret ? ret : count;
> > +}
>
> returns a strange value on error. Maybe we need to translate the "pcmcia
> error code" to something more appropriate, or (preferably) make it return
> a usual unix errno in the first place and translate _that_ to the "pcmcia
> error code" in ds.c ?
Oh, yes, the non-standard CS_ return values...
Add two further attributes, "card_insert" and "card_eject". Reading these
files will fail; but writing _anything_ non-empty to these files will execute
an user insert/ejection request -- equivalent to "cardctl insert",
"cardctl eject".
To ensure proper error values to userspace, transform the return values
from CS_ error codes to -E error codes.
drivers/pcmcia/cs.c | 14 ++++++++------
drivers/pcmcia/ds.c | 4 ++--
drivers/pcmcia/socket_sysfs.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+), 8 deletions(-)
diff -ruN linux-original/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- linux-original/drivers/pcmcia/cs.c 2004-05-20 09:30:51.807435464 +0200
+++ linux/drivers/pcmcia/cs.c 2004-05-20 09:40:30.341484920 +0200
@@ -2024,16 +2024,18 @@
down(&skt->skt_sem);
do {
if (!(skt->state & SOCKET_PRESENT)) {
- ret = CS_NO_CARD;
+ ret = -ENODEV;
break;
}
ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);
- if (ret != 0)
+ if (ret != 0) {
+ ret = -EINVAL;
break;
+ }
socket_remove(skt);
- ret = CS_SUCCESS;
+ ret = 0;
} while (0);
up(&skt->skt_sem);
@@ -2049,14 +2051,14 @@
down(&skt->skt_sem);
do {
if (skt->state & SOCKET_PRESENT) {
- ret = CS_IN_USE;
+ ret = -EBUSY;
break;
}
if (socket_insert(skt) == CS_NO_CARD) {
- ret = CS_NO_CARD;
+ ret = -ENODEV;
break;
}
- ret = CS_SUCCESS;
+ ret = 0;
} while (0);
up(&skt->skt_sem);
diff -ruN linux-original/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux-original/drivers/pcmcia/ds.c 2004-05-20 09:30:43.497698736 +0200
+++ linux/drivers/pcmcia/ds.c 2004-05-20 09:38:37.289671408 +0200
@@ -970,10 +970,10 @@
ret = pcmcia_resume_card(s->parent);
break;
case DS_EJECT_CARD:
- ret = pcmcia_eject_card(s->parent);
+ err = pcmcia_eject_card(s->parent);
break;
case DS_INSERT_CARD:
- ret = pcmcia_insert_card(s->parent);
+ err = pcmcia_insert_card(s->parent);
break;
case DS_ACCESS_CONFIGURATION_REGISTER:
if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
diff -ruN linux-original/drivers/pcmcia/socket_sysfs.c linux/drivers/pcmcia/socket_sysfs.c
--- linux-original/drivers/pcmcia/socket_sysfs.c 2004-05-20 09:31:02.695780184 +0200
+++ linux/drivers/pcmcia/socket_sysfs.c 2004-05-20 09:38:49.979742224 +0200
@@ -92,11 +92,43 @@
}
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,
};
More information about the linux-pcmcia
mailing list