Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
devres.c
Go to the documentation of this file.
1 #include <linux/pci.h>
2 #include <linux/io.h>
3 #include <linux/gfp.h>
4 #include <linux/export.h>
5 
6 void devm_ioremap_release(struct device *dev, void *res)
7 {
8  iounmap(*(void __iomem **)res);
9 }
10 
11 static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
12 {
13  return *(void **)res == match_data;
14 }
15 
25  unsigned long size)
26 {
27  void __iomem **ptr, *addr;
28 
29  ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
30  if (!ptr)
31  return NULL;
32 
33  addr = ioremap(offset, size);
34  if (addr) {
35  *ptr = addr;
36  devres_add(dev, ptr);
37  } else
38  devres_free(ptr);
39 
40  return addr;
41 }
43 
54  unsigned long size)
55 {
56  void __iomem **ptr, *addr;
57 
58  ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
59  if (!ptr)
60  return NULL;
61 
62  addr = ioremap_nocache(offset, size);
63  if (addr) {
64  *ptr = addr;
65  devres_add(dev, ptr);
66  } else
67  devres_free(ptr);
68 
69  return addr;
70 }
72 
80 void devm_iounmap(struct device *dev, void __iomem *addr)
81 {
82  WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match,
83  (void *)addr));
84  iounmap(addr);
85 }
87 
104  struct resource *res)
105 {
107  const char *name;
108  void __iomem *dest_ptr;
109 
110  BUG_ON(!dev);
111 
112  if (!res || resource_type(res) != IORESOURCE_MEM) {
113  dev_err(dev, "invalid resource\n");
114  return NULL;
115  }
116 
117  size = resource_size(res);
118  name = res->name ?: dev_name(dev);
119 
120  if (!devm_request_mem_region(dev, res->start, size, name)) {
121  dev_err(dev, "can't request region for resource %pR\n", res);
122  return NULL;
123  }
124 
125  if (res->flags & IORESOURCE_CACHEABLE)
126  dest_ptr = devm_ioremap(dev, res->start, size);
127  else
128  dest_ptr = devm_ioremap_nocache(dev, res->start, size);
129 
130  if (!dest_ptr) {
131  dev_err(dev, "ioremap failed for resource %pR\n", res);
132  devm_release_mem_region(dev, res->start, size);
133  }
134 
135  return dest_ptr;
136 }
138 
139 #ifdef CONFIG_HAS_IOPORT
140 /*
141  * Generic iomap devres
142  */
143 static void devm_ioport_map_release(struct device *dev, void *res)
144 {
145  ioport_unmap(*(void __iomem **)res);
146 }
147 
148 static int devm_ioport_map_match(struct device *dev, void *res,
149  void *match_data)
150 {
151  return *(void **)res == match_data;
152 }
153 
163 void __iomem * devm_ioport_map(struct device *dev, unsigned long port,
164  unsigned int nr)
165 {
166  void __iomem **ptr, *addr;
167 
168  ptr = devres_alloc(devm_ioport_map_release, sizeof(*ptr), GFP_KERNEL);
169  if (!ptr)
170  return NULL;
171 
172  addr = ioport_map(port, nr);
173  if (addr) {
174  *ptr = addr;
175  devres_add(dev, ptr);
176  } else
177  devres_free(ptr);
178 
179  return addr;
180 }
181 EXPORT_SYMBOL(devm_ioport_map);
182 
191 void devm_ioport_unmap(struct device *dev, void __iomem *addr)
192 {
193  ioport_unmap(addr);
194  WARN_ON(devres_destroy(dev, devm_ioport_map_release,
195  devm_ioport_map_match, (void *)addr));
196 }
197 EXPORT_SYMBOL(devm_ioport_unmap);
198 
199 #ifdef CONFIG_PCI
200 /*
201  * PCI iomap devres
202  */
203 #define PCIM_IOMAP_MAX PCI_ROM_RESOURCE
204 
205 struct pcim_iomap_devres {
206  void __iomem *table[PCIM_IOMAP_MAX];
207 };
208 
209 static void pcim_iomap_release(struct device *gendev, void *res)
210 {
211  struct pci_dev *dev = container_of(gendev, struct pci_dev, dev);
212  struct pcim_iomap_devres *this = res;
213  int i;
214 
215  for (i = 0; i < PCIM_IOMAP_MAX; i++)
216  if (this->table[i])
217  pci_iounmap(dev, this->table[i]);
218 }
219 
233 void __iomem * const * pcim_iomap_table(struct pci_dev *pdev)
234 {
235  struct pcim_iomap_devres *dr, *new_dr;
236 
237  dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
238  if (dr)
239  return dr->table;
240 
241  new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL);
242  if (!new_dr)
243  return NULL;
244  dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
245  return dr->table;
246 }
248 
258 void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
259 {
260  void __iomem **tbl;
261 
262  BUG_ON(bar >= PCIM_IOMAP_MAX);
263 
264  tbl = (void __iomem **)pcim_iomap_table(pdev);
265  if (!tbl || tbl[bar]) /* duplicate mappings not allowed */
266  return NULL;
267 
268  tbl[bar] = pci_iomap(pdev, bar, maxlen);
269  return tbl[bar];
270 }
272 
280 void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
281 {
282  void __iomem **tbl;
283  int i;
284 
285  pci_iounmap(pdev, addr);
286 
287  tbl = (void __iomem **)pcim_iomap_table(pdev);
288  BUG_ON(!tbl);
289 
290  for (i = 0; i < PCIM_IOMAP_MAX; i++)
291  if (tbl[i] == addr) {
292  tbl[i] = NULL;
293  return;
294  }
295  WARN_ON(1);
296 }
298 
307 int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
308 {
309  void __iomem * const *iomap;
310  int i, rc;
311 
312  iomap = pcim_iomap_table(pdev);
313  if (!iomap)
314  return -ENOMEM;
315 
316  for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
317  unsigned long len;
318 
319  if (!(mask & (1 << i)))
320  continue;
321 
322  rc = -EINVAL;
323  len = pci_resource_len(pdev, i);
324  if (!len)
325  goto err_inval;
326 
327  rc = pci_request_region(pdev, i, name);
328  if (rc)
329  goto err_inval;
330 
331  rc = -ENOMEM;
332  if (!pcim_iomap(pdev, i, 0))
333  goto err_region;
334  }
335 
336  return 0;
337 
338  err_region:
339  pci_release_region(pdev, i);
340  err_inval:
341  while (--i >= 0) {
342  if (!(mask & (1 << i)))
343  continue;
344  pcim_iounmap(pdev, iomap[i]);
345  pci_release_region(pdev, i);
346  }
347 
348  return rc;
349 }
351 
360 int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
361  const char *name)
362 {
363  int request_mask = ((1 << 6) - 1) & ~mask;
364  int rc;
365 
366  rc = pci_request_selected_regions(pdev, request_mask, name);
367  if (rc)
368  return rc;
369 
370  rc = pcim_iomap_regions(pdev, mask, name);
371  if (rc)
372  pci_release_selected_regions(pdev, request_mask);
373  return rc;
374 }
376 
384 void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
385 {
386  void __iomem * const *iomap;
387  int i;
388 
389  iomap = pcim_iomap_table(pdev);
390  if (!iomap)
391  return;
392 
393  for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
394  if (!(mask & (1 << i)))
395  continue;
396 
397  pcim_iounmap(pdev, iomap[i]);
398  pci_release_region(pdev, i);
399  }
400 }
402 #endif /* CONFIG_PCI */
403 #endif /* CONFIG_HAS_IOPORT */