static int pcmcia_device_remove(struct device * dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; int i; /* detach the "instance" */ p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); if (!p_drv) return 0; if (p_drv->remove) p_drv->remove(p_dev); /* check for proper unloading */ if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) printk(KERN_INFO "pcmcia: driver %s did not release config properly\n", p_drv->drv.name); for (i = 0; i < MAX_WIN; i++) if (p_dev->state & CLIENT_WIN_REQ(i)) printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n", p_drv->drv.name); /* references from pcmcia_probe_device */ p_dev->state = CLIENT_UNBOUND; pcmcia_put_dev(p_dev); module_put(p_drv->owner); return 0; }
int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) { struct pcmcia_socket *s = p_dev->socket; pccard_mem_map *win; wh--; if (wh >= MAX_WIN) return -EINVAL; mutex_lock(&s->ops_mutex); win = &s->win[wh]; if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) { dev_dbg(&s->dev, "not releasing unknown window\n"); mutex_unlock(&s->ops_mutex); return -EINVAL; } /* Shut down memory window */ win->flags &= ~MAP_ACTIVE; s->ops->set_mem_map(s, win); s->state &= ~SOCKET_WIN_REQ(wh); /* Release system memory */ if (win->res) { release_resource(win->res); kfree(win->res); win->res = NULL; } p_dev->_win &= ~CLIENT_WIN_REQ(wh); mutex_unlock(&s->ops_mutex); return 0; } /* pcmcia_release_window */