static int ds_release(struct inode *inode, struct file *file) { struct pcmcia_bus_socket *s; user_info_t *user, **link; ds_dbg(0, "ds_release(socket %d)\n", iminor(inode)); user = file->private_data; if (CHECK_USER(user)) goto out; s = user->socket; /* Unlink user data structure */ if ((file->f_flags & O_ACCMODE) != O_RDONLY) { s->state &= ~DS_SOCKET_BUSY; s->req_pending = 0; wake_up_interruptible(&s->request); } file->private_data = NULL; for (link = &s->user; *link; link = &(*link)->next) if (*link == user) break; if (link == NULL) goto out; *link = user->next; user->user_magic = 0; kfree(user); pcmcia_put_bus_socket(s); out: return 0; } /* ds_release */
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_bus_socket(p_dev->socket->pcmcia); kfree(p_dev); }
static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned int function) { struct pcmcia_device *p_dev; unsigned long flags; s = pcmcia_get_bus_socket(s); if (!s) return NULL; down(&device_add_lock); p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); if (!p_dev) goto err_put; memset(p_dev, 0, sizeof(struct pcmcia_device)); p_dev->socket = s->parent; p_dev->device_no = (s->device_count++); p_dev->func = function; p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.parent = s->parent->dev.dev; p_dev->dev.release = pcmcia_release_dev; sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); /* compat */ p_dev->client.client_magic = CLIENT_MAGIC; p_dev->client.Socket = s->parent; p_dev->client.Function = function; p_dev->client.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); 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); s->device_count--; err_put: up(&device_add_lock); pcmcia_put_bus_socket(s); return NULL; }
static void pcmcia_bus_remove_socket(struct class_device *class_dev) { struct pcmcia_socket *socket = class_dev->class_data; if (!socket || !socket->pcmcia) return; flush_scheduled_work(); pcmcia_deregister_client(socket->pcmcia->handle); socket->pcmcia->state |= DS_SOCKET_DEAD; pcmcia_put_bus_socket(socket->pcmcia); socket->pcmcia = NULL; return; }