Esempio n. 1
0
static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
					   struct class_interface *class_intf)
{
	struct pcmcia_socket *socket = class_get_devdata(class_dev);
	int ret;

	socket = pcmcia_get_socket(socket);
	if (!socket) {
		printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket);
		return -ENODEV;
	}

	/*
	 * Ugly. But we want to wait for the socket threads to have started up.
	 * We really should let the drivers themselves drive some of this..
	 */
	msleep(250);

#ifdef CONFIG_PCMCIA_IOCTL
	init_waitqueue_head(&socket->queue);
#endif
	INIT_LIST_HEAD(&socket->devices_list);
	INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device, socket);
	memset(&socket->pcmcia_state, 0, sizeof(u8));
	socket->device_count = 0;

	ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback);
	if (ret) {
		printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket);
		pcmcia_put_socket(socket);
		return (ret);
	}

	return 0;
}
Esempio n. 2
0
static void pcmcia_release_dev(struct device *dev)
{
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
	ds_dbg(1, "releasing dev %p\n", p_dev);
	pcmcia_put_socket(p_dev->socket);
	kfree(p_dev->devname);
	kfree(p_dev);
}
Esempio n. 3
0
static void pcmcia_bus_remove_socket(struct class_device *class_dev,
				     struct class_interface *class_intf)
{
	struct pcmcia_socket *socket = class_get_devdata(class_dev);

	if (!socket)
		return;

	socket->pcmcia_state.dead = 1;
	pccard_register_pcmcia(socket, NULL);

	pcmcia_put_socket(socket);

	return;
}
Esempio n. 4
0
static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
{
	struct pcmcia_socket *s = pcmcia_get_socket(skt);

	ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
	       event, priority, skt);

	switch (event) {
	case CS_EVENT_CARD_REMOVAL:
		s->pcmcia_state.present = 0;
		pcmcia_card_remove(skt);
		handle_event(skt, event);
		break;

	case CS_EVENT_CARD_INSERTION:
		s->pcmcia_state.present = 1;
		pcmcia_card_add(skt);
		handle_event(skt, event);
		break;

	case CS_EVENT_EJECTION_REQUEST:
		break;

	case CS_EVENT_PM_SUSPEND:
	case CS_EVENT_PM_RESUME:
	case CS_EVENT_RESET_PHYSICAL:
	case CS_EVENT_CARD_RESET:
	default:
		handle_event(skt, event);
		break;
    }

    pcmcia_put_socket(s);

    return 0;
} /* ds_event */
Esempio n. 5
0
struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function)
{
	struct pcmcia_device *p_dev;
	unsigned long flags;
	int bus_id_len;

	s = pcmcia_get_socket(s);
	if (!s)
		return NULL;

	down(&device_add_lock);

	/* max of 2 devices per card */
	if (s->device_count == 2)
		goto err_put;

	p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
	if (!p_dev)
		goto err_put;

	p_dev->socket = s;
	p_dev->device_no = (s->device_count++);
	p_dev->func   = function;

	p_dev->dev.bus = &pcmcia_bus_type;
	p_dev->dev.parent = s->dev.dev;
	p_dev->dev.release = pcmcia_release_dev;
	bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);

	p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
	if (!p_dev->devname)
		goto err_free;
	sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);

	/* compat */
	p_dev->state = CLIENT_UNBOUND;

	/* Add to the list in pcmcia_bus_socket */
	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
	list_add_tail(&p_dev->socket_device_list, &s->devices_list);
	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);

	printk(KERN_NOTICE "pcmcia: registering new device %s\n",
	       p_dev->devname);

	pcmcia_device_query(p_dev);

	if (device_register(&p_dev->dev)) {
		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
		list_del(&p_dev->socket_device_list);
		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);

		goto err_free;
       }

	up(&device_add_lock);

	return p_dev;

 err_free:
	kfree(p_dev->devname);
	kfree(p_dev);
	s->device_count--;
 err_put:
	up(&device_add_lock);
	pcmcia_put_socket(s);

	return NULL;
}
Esempio n. 6
0
static void pcmcia_release_bus_socket(struct kref *refcount)
{
	struct pcmcia_bus_socket *s = container_of(refcount, struct pcmcia_bus_socket, refcount);
	pcmcia_put_socket(s->parent);
	kfree(s);
}