[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