Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff1fa9ef authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Linus Torvalds
Browse files

[PATCH] pcmcia: CIS overrid via sysfs



The one thing which surprises me in this patch that cis->Length needs to be
set to count+1.  Without it, it doesn't work, but with it, it doesn't make
sense to me.

Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7f299bcc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ struct pcmcia_callback{
	struct module	*owner;
	int		(*event) (struct pcmcia_socket *s, event_t event, int priority);
	int		(*resources_done) (struct pcmcia_socket *s);
	void		(*replace_cis) (void);
};

int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
+6 −0
Original line number Diff line number Diff line
@@ -653,6 +653,11 @@ static inline void pcmcia_add_pseudo_device(struct pcmcia_bus_socket *s)
	return;
}

static void pcmcia_bus_rescan(void)
{
	/* must be called with skt_sem held */
        bus_rescan_devices(&pcmcia_bus_type);
}

static inline int pcmcia_devmatch(struct pcmcia_device *dev,
				  struct pcmcia_device_id *did)
@@ -1766,6 +1771,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
	s->callback.owner = THIS_MODULE;
	s->callback.event = &ds_event;
	s->callback.resources_done = &pcmcia_card_add;
	s->callback.replace_cis = &pcmcia_bus_rescan;
	socket->pcmcia = s;

	ret = pccard_register_pcmcia(socket, &s->callback);
+46 −1
Original line number Diff line number Diff line
@@ -282,6 +282,50 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size
	return (count);
}

static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
	struct pcmcia_socket *s = to_socket(container_of(kobj, struct class_device, kobj));
	cisdump_t *cis;
	ssize_t ret = count;

	if (off)
		return -EINVAL;

	if (count >= 0x200)
		return -EINVAL;

	if (!(s->state & SOCKET_PRESENT))
		return -ENODEV;

	cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL);
	if (!cis)
		return -ENOMEM;
	memset(cis, 0, sizeof(cisdump_t));

	cis->Length = count + 1;
	memcpy(cis->Data, buf, count);

	if (pcmcia_replace_cis(s, cis))
		ret  = -EIO;

	kfree(cis);

	if (!ret) {
		down(&s->skt_sem);
		if ((s->callback) && (s->state & SOCKET_PRESENT) &&
		    !(s->state & SOCKET_CARDBUS)) {
			if (try_module_get(s->callback->owner)) {
				s->callback->replace_cis();
				module_put(s->callback->owner);
			}
		}
		up(&s->skt_sem);
	}


	return (ret);
}


static struct class_device_attribute *pccard_socket_attributes[] = {
	&class_device_attr_card_type,
@@ -296,9 +340,10 @@ static struct class_device_attribute *pccard_socket_attributes[] = {
};

static struct bin_attribute pccard_cis_attr = {
	.attr = { .name = "cis", .mode = S_IRUGO, .owner = THIS_MODULE},
	.attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE},
	.size = 0x200,
	.read = pccard_show_cis,
	.write = pccard_store_cis,
};

static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev)