From cdb138080b78146d1cdadba9f5dadbeb97445b91 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 28 Jul 2010 10:59:06 +0200 Subject: pcmcia: do not use win_req_t when calling pcmcia_request_window() Instead of win_req_t, drivers are now requested to fill out struct pcmcia_device *p_dev->resource[2,3,4,5] for up to four iomem ranges. After a call to pcmcia_request_window(), the windows found there are reserved and may be used until pcmcia_release_window() is called. CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-mtd@lists.infradead.org CC: Jiri Kosina CC: linux-scsi@vger.kernel.org Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 60 ++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'drivers/pcmcia') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 9ba4dade69a4..bf16a1cf7399 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -204,11 +204,10 @@ int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val) EXPORT_SYMBOL(pcmcia_write_config_byte); -int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, +int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res, unsigned int offset) { struct pcmcia_socket *s = p_dev->socket; - struct resource *res = wh; unsigned int w; int ret; @@ -386,7 +385,12 @@ out: return ret; } /* pcmcia_release_io */ - +/** + * pcmcia_release_window() - release reserved iomem for PCMCIA devices + * + * pcmcia_release_window() releases struct resource *res which was + * previously reserved by calling pcmcia_request_window(). + */ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) { struct pcmcia_socket *s = p_dev->socket; @@ -420,6 +424,8 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) kfree(win->res); win->res = NULL; } + res->start = res->end = 0; + res->flags = IORESOURCE_MEM; p_dev->_win &= ~CLIENT_WIN_REQ(w); mutex_unlock(&s->ops_mutex); @@ -795,17 +801,21 @@ int pcmcia_setup_irq(struct pcmcia_device *p_dev) } -/** pcmcia_request_window +/** + * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices * - * Request_window() establishes a mapping between card memory space - * and system memory space. + * pcmcia_request_window() attepts to reserve an iomem ranges specified in + * struct resource *res pointing to one of the entries in + * struct pcmcia_device *p_dev->resource[2..5]. The "start" value is the + * requested start of the IO mem resource; "end" reflects the size + * requested. */ -int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh) +int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res, + unsigned int speed) { struct pcmcia_socket *s = p_dev->socket; pccard_mem_map *win; u_long align; - struct resource *res; int w; if (!(s->state & SOCKET_PRESENT)) { @@ -814,19 +824,19 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha } /* Window size defaults to smallest available */ - if (req->Size == 0) - req->Size = s->map_size; - align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; - if (req->Size & (s->map_size-1)) { + if (res->end == 0) + res->end = s->map_size; + align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size; + if (res->end & (s->map_size-1)) { dev_dbg(&p_dev->dev, "invalid map size\n"); return -EINVAL; } - if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || - (req->Base & (align-1))) { + if ((res->start && (s->features & SS_CAP_STATIC_MAP)) || + (res->start & (align-1))) { dev_dbg(&p_dev->dev, "invalid base address\n"); return -EINVAL; } - if (req->Base) + if (res->start) align = 0; /* Allocate system memory window */ @@ -843,7 +853,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha win = &s->win[w]; if (!(s->features & SS_CAP_STATIC_MAP)) { - win->res = pcmcia_find_mem_region(req->Base, req->Size, align, + win->res = pcmcia_find_mem_region(res->start, res->end, align, 0, s); if (!win->res) { dev_dbg(&p_dev->dev, "allocating mem region failed\n"); @@ -855,8 +865,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha /* Configure the socket controller */ win->map = w+1; - win->flags = req->Attributes; - win->speed = req->AccessSpeed; + win->flags = res->flags & WIN_FLAGS_MAP; + win->speed = speed; win->card_start = 0; if (s->ops->set_mem_map(s, win) != 0) { @@ -868,17 +878,14 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha /* Return window handle */ if (s->features & SS_CAP_STATIC_MAP) - req->Base = win->static_start; + res->start = win->static_start; else - req->Base = win->res->start; + res->start = win->res->start; /* convert to new-style resources */ - res = p_dev->resource[w + MAX_IO_WIN]; - res->start = req->Base; - res->end = req->Base + req->Size - 1; - res->flags &= ~IORESOURCE_BITS; - res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2); - res->flags |= IORESOURCE_MEM; + res->end += res->start - 1; + res->flags &= ~WIN_FLAGS_REQ; + res->flags |= (win->map << 2) | IORESOURCE_MEM; res->parent = win->res; if (win->res) request_resource(&iomem_resource, res); @@ -886,7 +893,6 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); mutex_unlock(&s->ops_mutex); - *wh = res; return 0; } /* pcmcia_request_window */ -- cgit v1.2.3