aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-01-20 02:00:26 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-09 17:39:36 -0500
commit9ac7849e35f705830f7b016ff272b0ff1f7ff759 (patch)
tree7f17cdff87e154937a15cc2ec8da9b4e6018ce8e /include
parent77a527eadb425b60db3f5f0aae6a4c51c38e35e5 (diff)
devres: device resource management
Implement device resource management, in short, devres. A device driver can allocate arbirary size of devres data which is associated with a release function. On driver detach, release function is invoked on the devres data, then, devres data is freed. devreses are typed by associated release functions. Some devreses are better represented by single instance of the type while others need multiple instances sharing the same release function. Both usages are supported. devreses can be grouped using devres group such that a device driver can easily release acquired resources halfway through initialization or selectively release resources (e.g. resources for port 1 out of 4 ports). This patch adds devres core including documentation and the following managed interfaces. * alloc/free : devm_kzalloc(), devm_kzfree() * IO region : devm_request_region(), devm_release_region() * IRQ : devm_request_irq(), devm_free_irq() * DMA : dmam_alloc_coherent(), dmam_free_coherent(), dmam_declare_coherent_memory(), dmam_pool_create(), dmam_pool_destroy() * PCI : pcim_enable_device(), pcim_pin_device(), pci_is_managed() * iomap : devm_ioport_map(), devm_ioport_unmap(), devm_ioremap(), devm_ioremap_nocache(), devm_iounmap(), pcim_iomap_table(), pcim_iomap(), pcim_iounmap() Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/device.h38
-rw-r--r--include/linux/dma-mapping.h29
-rw-r--r--include/linux/dmapool.h7
-rw-r--r--include/linux/interrupt.h6
-rw-r--r--include/linux/io.h17
-rw-r--r--include/linux/ioport.h20
-rw-r--r--include/linux/pci.h9
7 files changed, 125 insertions, 1 deletions
diff --git a/include/linux/device.h b/include/linux/device.h
index 5ca1cdba563a..26e4692f2d1a 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -354,6 +354,41 @@ extern int __must_check device_create_bin_file(struct device *dev,
354 struct bin_attribute *attr); 354 struct bin_attribute *attr);
355extern void device_remove_bin_file(struct device *dev, 355extern void device_remove_bin_file(struct device *dev,
356 struct bin_attribute *attr); 356 struct bin_attribute *attr);
357
358/* device resource management */
359typedef void (*dr_release_t)(struct device *dev, void *res);
360typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
361
362#ifdef CONFIG_DEBUG_DEVRES
363extern void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
364 const char *name);
365#define devres_alloc(release, size, gfp) \
366 __devres_alloc(release, size, gfp, #release)
367#else
368extern void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
369#endif
370extern void devres_free(void *res);
371extern void devres_add(struct device *dev, void *res);
372extern void * devres_find(struct device *dev, dr_release_t release,
373 dr_match_t match, void *match_data);
374extern void * devres_get(struct device *dev, void *new_res,
375 dr_match_t match, void *match_data);
376extern void * devres_remove(struct device *dev, dr_release_t release,
377 dr_match_t match, void *match_data);
378extern int devres_destroy(struct device *dev, dr_release_t release,
379 dr_match_t match, void *match_data);
380
381/* devres group */
382extern void * __must_check devres_open_group(struct device *dev, void *id,
383 gfp_t gfp);
384extern void devres_close_group(struct device *dev, void *id);
385extern void devres_remove_group(struct device *dev, void *id);
386extern int devres_release_group(struct device *dev, void *id);
387
388/* managed kzalloc/kfree for device drivers, no kmalloc, always use kzalloc */
389extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
390extern void devm_kfree(struct device *dev, void *p);
391
357struct device { 392struct device {
358 struct klist klist_children; 393 struct klist klist_children;
359 struct klist_node knode_parent; /* node in sibling list */ 394 struct klist_node knode_parent; /* node in sibling list */
@@ -397,6 +432,9 @@ struct device {
397 /* arch specific additions */ 432 /* arch specific additions */
398 struct dev_archdata archdata; 433 struct dev_archdata archdata;
399 434
435 spinlock_t devres_lock;
436 struct list_head devres_head;
437
400 /* class_device migration path */ 438 /* class_device migration path */
401 struct list_head node; 439 struct list_head node;
402 struct class *class; 440 struct class *class;
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index ff203c465fed..9a663c6db16a 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -66,6 +66,33 @@ dma_mark_declared_memory_occupied(struct device *dev,
66} 66}
67#endif 67#endif
68 68
69#endif 69/*
70 * Managed DMA API
71 */
72extern void *dmam_alloc_coherent(struct device *dev, size_t size,
73 dma_addr_t *dma_handle, gfp_t gfp);
74extern void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
75 dma_addr_t dma_handle);
76extern void *dmam_alloc_noncoherent(struct device *dev, size_t size,
77 dma_addr_t *dma_handle, gfp_t gfp);
78extern void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
79 dma_addr_t dma_handle);
80#ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
81extern int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
82 dma_addr_t device_addr, size_t size,
83 int flags);
84extern void dmam_release_declared_memory(struct device *dev);
85#else /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
86static inline int dmam_declare_coherent_memory(struct device *dev,
87 dma_addr_t bus_addr, dma_addr_t device_addr,
88 size_t size, gfp_t gfp)
89{
90 return 0;
91}
70 92
93static inline void dmam_release_declared_memory(struct device *dev)
94{
95}
96#endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
71 97
98#endif
diff --git a/include/linux/dmapool.h b/include/linux/dmapool.h
index 76f12f46db7f..022e34fcbd1b 100644
--- a/include/linux/dmapool.h
+++ b/include/linux/dmapool.h
@@ -24,5 +24,12 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
24 24
25void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr); 25void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr);
26 26
27/*
28 * Managed DMA pool
29 */
30struct dma_pool *dmam_pool_create(const char *name, struct device *dev,
31 size_t size, size_t align, size_t allocation);
32void dmam_pool_destroy(struct dma_pool *pool);
33
27#endif 34#endif
28 35
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index e36e86c869fb..5a8ba0b8ccba 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -12,6 +12,7 @@
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/irqflags.h> 13#include <linux/irqflags.h>
14#include <linux/bottom_half.h> 14#include <linux/bottom_half.h>
15#include <linux/device.h>
15#include <asm/atomic.h> 16#include <asm/atomic.h>
16#include <asm/ptrace.h> 17#include <asm/ptrace.h>
17#include <asm/system.h> 18#include <asm/system.h>
@@ -83,6 +84,11 @@ extern int request_irq(unsigned int, irq_handler_t handler,
83 unsigned long, const char *, void *); 84 unsigned long, const char *, void *);
84extern void free_irq(unsigned int, void *); 85extern void free_irq(unsigned int, void *);
85 86
87extern int devm_request_irq(struct device *dev, unsigned int irq,
88 irq_handler_t handler, unsigned long irqflags,
89 const char *devname, void *dev_id);
90extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
91
86/* 92/*
87 * On lockdep we dont want to enable hardirqs in hardirq 93 * On lockdep we dont want to enable hardirqs in hardirq
88 * context. Use local_irq_enable_in_hardirq() to annotate 94 * context. Use local_irq_enable_in_hardirq() to annotate
diff --git a/include/linux/io.h b/include/linux/io.h
index 81877ea39309..f5edf9c5de0a 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -28,6 +28,23 @@ void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
28int ioremap_page_range(unsigned long addr, unsigned long end, 28int ioremap_page_range(unsigned long addr, unsigned long end,
29 unsigned long phys_addr, pgprot_t prot); 29 unsigned long phys_addr, pgprot_t prot);
30 30
31/*
32 * Managed iomap interface
33 */
34void __iomem * devm_ioport_map(struct device *dev, unsigned long port,
35 unsigned int nr);
36void devm_ioport_unmap(struct device *dev, void __iomem *addr);
37
38void __iomem * devm_ioremap(struct device *dev, unsigned long offset,
39 unsigned long size);
40void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
41 unsigned long size);
42void devm_iounmap(struct device *dev, void __iomem *addr);
43
44void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
45void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
46void __iomem * const * pcim_iomap_table(struct pci_dev *pdev);
47
31/** 48/**
32 * check_signature - find BIOS signatures 49 * check_signature - find BIOS signatures
33 * @io_addr: mmio address to check 50 * @io_addr: mmio address to check
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 15228d79c5bc..6859a3b14088 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -137,4 +137,24 @@ static inline int __deprecated check_region(resource_size_t s,
137{ 137{
138 return __check_region(&ioport_resource, s, n); 138 return __check_region(&ioport_resource, s, n);
139} 139}
140
141/* Wrappers for managed devices */
142struct device;
143#define devm_request_region(dev,start,n,name) \
144 __devm_request_region(dev, &ioport_resource, (start), (n), (name))
145#define devm_request_mem_region(dev,start,n,name) \
146 __devm_request_region(dev, &iomem_resource, (start), (n), (name))
147
148extern struct resource * __devm_request_region(struct device *dev,
149 struct resource *parent, resource_size_t start,
150 resource_size_t n, const char *name);
151
152#define devm_release_region(start,n) \
153 __devm_release_region(dev, &ioport_resource, (start), (n))
154#define devm_release_mem_region(start,n) \
155 __devm_release_region(dev, &iomem_resource, (start), (n))
156
157extern void __devm_release_region(struct device *dev, struct resource *parent,
158 resource_size_t start, resource_size_t n);
159
140#endif /* _LINUX_IOPORT_H */ 160#endif /* _LINUX_IOPORT_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 805412cc6875..9e3042e7e1cc 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -167,6 +167,7 @@ struct pci_dev {
167 unsigned int broken_parity_status:1; /* Device generates false positive parity */ 167 unsigned int broken_parity_status:1; /* Device generates false positive parity */
168 unsigned int msi_enabled:1; 168 unsigned int msi_enabled:1;
169 unsigned int msix_enabled:1; 169 unsigned int msix_enabled:1;
170 unsigned int is_managed:1;
170 atomic_t enable_cnt; /* pci_enable_device has been called */ 171 atomic_t enable_cnt; /* pci_enable_device has been called */
171 172
172 u32 saved_config_space[16]; /* config space saved at suspend time */ 173 u32 saved_config_space[16]; /* config space saved at suspend time */
@@ -528,6 +529,14 @@ static inline int pci_write_config_dword(struct pci_dev *dev, int where, u32 val
528 529
529int __must_check pci_enable_device(struct pci_dev *dev); 530int __must_check pci_enable_device(struct pci_dev *dev);
530int __must_check pci_enable_device_bars(struct pci_dev *dev, int mask); 531int __must_check pci_enable_device_bars(struct pci_dev *dev, int mask);
532int __must_check pcim_enable_device(struct pci_dev *pdev);
533void pcim_pin_device(struct pci_dev *pdev);
534
535static inline int pci_is_managed(struct pci_dev *pdev)
536{
537 return pdev->is_managed;
538}
539
531void pci_disable_device(struct pci_dev *dev); 540void pci_disable_device(struct pci_dev *dev);
532void pci_set_master(struct pci_dev *dev); 541void pci_set_master(struct pci_dev *dev);
533#define HAVE_PCI_SET_MWI 542#define HAVE_PCI_SET_MWI