diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-07-25 07:10:22 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-08-03 03:04:19 -0400 |
commit | ad0c7be28bc7593da43f494f6d074767ea96ca59 (patch) | |
tree | 31db0dd8238bfb075e5d7b3adade482e24e5e352 /drivers/pcmcia | |
parent | 8f677ea07a2a934ac74ffa57db0f5617aec15ddf (diff) |
pcmcia: insert PCMCIA device resources into resource tree
Insert PCMCIA device resources into the resource tree. However, this is
currently only implemented for sockets which do not statically map the
resources.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 3 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 4 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 74 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_iodyn.c | 5 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_mgr.c | 3 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 5 |
6 files changed, 60 insertions, 34 deletions
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 37d38b5a1972..da055dc14d98 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -62,7 +62,8 @@ struct pccard_resource_ops { | |||
62 | unsigned int attr, | 62 | unsigned int attr, |
63 | unsigned int *base, | 63 | unsigned int *base, |
64 | unsigned int num, | 64 | unsigned int num, |
65 | unsigned int align); | 65 | unsigned int align, |
66 | struct resource **parent); | ||
66 | struct resource* (*find_mem) (unsigned long base, unsigned long num, | 67 | struct resource* (*find_mem) (unsigned long base, unsigned long num, |
67 | unsigned long align, int low, | 68 | unsigned long align, int low, |
68 | struct pcmcia_socket *s); | 69 | struct pcmcia_socket *s); |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 028c97353b92..55570d9e1e4c 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -553,11 +553,11 @@ static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, | |||
553 | p_dev->function_config = c; | 553 | p_dev->function_config = c; |
554 | kref_init(&c->ref); | 554 | kref_init(&c->ref); |
555 | for (i = 0; i < MAX_IO_WIN; i++) { | 555 | for (i = 0; i < MAX_IO_WIN; i++) { |
556 | c->io[i].name = dev_name(&p_dev->dev); | 556 | c->io[i].name = p_dev->devname; |
557 | c->io[i].flags = IORESOURCE_IO; | 557 | c->io[i].flags = IORESOURCE_IO; |
558 | } | 558 | } |
559 | for (i = 0; i< MAX_WIN; i++) { | 559 | for (i = 0; i< MAX_WIN; i++) { |
560 | c->mem[i].name = dev_name(&p_dev->dev); | 560 | c->mem[i].name = p_dev->devname; |
561 | c->mem[i].flags = IORESOURCE_MEM; | 561 | c->mem[i].flags = IORESOURCE_MEM; |
562 | } | 562 | } |
563 | } | 563 | } |
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 01f8e56c8d2f..d48437f83acf 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -56,6 +56,33 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, | |||
56 | } | 56 | } |
57 | 57 | ||
58 | 58 | ||
59 | static void release_io_space(struct pcmcia_socket *s, struct resource *res) | ||
60 | { | ||
61 | resource_size_t num = resource_size(res); | ||
62 | int i; | ||
63 | |||
64 | dev_dbg(&s->dev, "release_io_space for %pR\n", res); | ||
65 | |||
66 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
67 | if (!s->io[i].res) | ||
68 | continue; | ||
69 | if ((s->io[i].res->start <= res->start) && | ||
70 | (s->io[i].res->end >= res->end)) { | ||
71 | s->io[i].InUse -= num; | ||
72 | if (res->parent) | ||
73 | release_resource(res); | ||
74 | res->start = res->end = 0; | ||
75 | res->flags = IORESOURCE_IO; | ||
76 | /* Free the window if no one else is using it */ | ||
77 | if (s->io[i].InUse == 0) { | ||
78 | release_resource(s->io[i].res); | ||
79 | kfree(s->io[i].res); | ||
80 | s->io[i].res = NULL; | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | } /* release_io_space */ | ||
85 | |||
59 | /** alloc_io_space | 86 | /** alloc_io_space |
60 | * | 87 | * |
61 | * Special stuff for managing IO windows, because they are scarce | 88 | * Special stuff for managing IO windows, because they are scarce |
@@ -87,43 +114,28 @@ static int alloc_io_space(struct pcmcia_socket *s, struct resource *res, | |||
87 | align = 0; | 114 | align = 0; |
88 | } | 115 | } |
89 | 116 | ||
90 | ret = s->resource_ops->find_io(s, res->flags, &base, num, align); | 117 | ret = s->resource_ops->find_io(s, res->flags, &base, num, align, |
118 | &res->parent); | ||
91 | if (ret) { | 119 | if (ret) { |
92 | dev_dbg(&s->dev, "alloc_io_space request returned %d", ret); | 120 | dev_dbg(&s->dev, "alloc_io_space request failed (%d)\n", ret); |
93 | return -EINVAL; | 121 | return -EINVAL; |
94 | } | 122 | } |
95 | 123 | ||
96 | res->start = base; | 124 | res->start = base; |
97 | res->end = res->start + num - 1; | 125 | res->end = res->start + num - 1; |
98 | dev_dbg(&s->dev, "alloc_io_space request returned %pR, %d\n", res, ret); | ||
99 | return 0; | ||
100 | } /* alloc_io_space */ | ||
101 | 126 | ||
102 | 127 | if (res->parent) { | |
103 | static void release_io_space(struct pcmcia_socket *s, struct resource *res) | 128 | ret = request_resource(res->parent, res); |
104 | { | 129 | if (ret) { |
105 | resource_size_t num = resource_size(res); | 130 | dev_warn(&s->dev, |
106 | int i; | 131 | "request_resource %pR failed: %d\n", res, ret); |
107 | 132 | res->parent = NULL; | |
108 | dev_dbg(&s->dev, "release_io_space for %pR\n", res); | 133 | release_io_space(s, res); |
109 | |||
110 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
111 | if (!s->io[i].res) | ||
112 | continue; | ||
113 | if ((s->io[i].res->start <= res->start) && | ||
114 | (s->io[i].res->end >= res->end)) { | ||
115 | s->io[i].InUse -= num; | ||
116 | res->start = res->end = 0; | ||
117 | res->flags = IORESOURCE_IO; | ||
118 | /* Free the window if no one else is using it */ | ||
119 | if (s->io[i].InUse == 0) { | ||
120 | release_resource(s->io[i].res); | ||
121 | kfree(s->io[i].res); | ||
122 | s->io[i].res = NULL; | ||
123 | } | ||
124 | } | 134 | } |
125 | } | 135 | } |
126 | } /* release_io_space */ | 136 | dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res); |
137 | return ret; | ||
138 | } /* alloc_io_space */ | ||
127 | 139 | ||
128 | 140 | ||
129 | /** | 141 | /** |
@@ -401,6 +413,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | |||
401 | 413 | ||
402 | /* Release system memory */ | 414 | /* Release system memory */ |
403 | if (win->res) { | 415 | if (win->res) { |
416 | release_resource(res); | ||
404 | release_resource(win->res); | 417 | release_resource(win->res); |
405 | kfree(win->res); | 418 | kfree(win->res); |
406 | win->res = NULL; | 419 | win->res = NULL; |
@@ -853,6 +866,11 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
853 | res->end = req->Base + req->Size - 1; | 866 | res->end = req->Base + req->Size - 1; |
854 | res->flags &= ~IORESOURCE_BITS; | 867 | res->flags &= ~IORESOURCE_BITS; |
855 | res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2); | 868 | res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2); |
869 | res->flags |= IORESOURCE_MEM; | ||
870 | res->parent = win->res; | ||
871 | if (win->res) | ||
872 | request_resource(&iomem_resource, res); | ||
873 | |||
856 | dev_dbg(&s->dev, "request_window results in %pR\n", res); | 874 | dev_dbg(&s->dev, "request_window results in %pR\n", res); |
857 | 875 | ||
858 | mutex_unlock(&s->ops_mutex); | 876 | mutex_unlock(&s->ops_mutex); |
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c index 3b1dce2df26a..8510c35d2952 100644 --- a/drivers/pcmcia/rsrc_iodyn.c +++ b/drivers/pcmcia/rsrc_iodyn.c | |||
@@ -87,7 +87,7 @@ static struct resource *__iodyn_find_io_region(struct pcmcia_socket *s, | |||
87 | 87 | ||
88 | static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | 88 | static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, |
89 | unsigned int *base, unsigned int num, | 89 | unsigned int *base, unsigned int num, |
90 | unsigned int align) | 90 | unsigned int align, struct resource **parent) |
91 | { | 91 | { |
92 | int i, ret = 0; | 92 | int i, ret = 0; |
93 | 93 | ||
@@ -128,6 +128,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
128 | ((res->flags & ~IORESOURCE_BITS) | | 128 | ((res->flags & ~IORESOURCE_BITS) | |
129 | (attr & IORESOURCE_BITS)); | 129 | (attr & IORESOURCE_BITS)); |
130 | s->io[i].InUse = num; | 130 | s->io[i].InUse = num; |
131 | *parent = res; | ||
131 | return 0; | 132 | return 0; |
132 | } | 133 | } |
133 | 134 | ||
@@ -139,6 +140,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
139 | continue; | 140 | continue; |
140 | *base = try; | 141 | *base = try; |
141 | s->io[i].InUse += num; | 142 | s->io[i].InUse += num; |
143 | *parent = res; | ||
142 | return 0; | 144 | return 0; |
143 | } | 145 | } |
144 | 146 | ||
@@ -151,6 +153,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
151 | continue; | 153 | continue; |
152 | *base = try; | 154 | *base = try; |
153 | s->io[i].InUse += num; | 155 | s->io[i].InUse += num; |
156 | *parent = res; | ||
154 | return 0; | 157 | return 0; |
155 | } | 158 | } |
156 | } | 159 | } |
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index b433a7995651..4e80421fd908 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -47,11 +47,12 @@ struct resource *pcmcia_make_resource(unsigned long start, unsigned long end, | |||
47 | 47 | ||
48 | static int static_find_io(struct pcmcia_socket *s, unsigned int attr, | 48 | static int static_find_io(struct pcmcia_socket *s, unsigned int attr, |
49 | unsigned int *base, unsigned int num, | 49 | unsigned int *base, unsigned int num, |
50 | unsigned int align) | 50 | unsigned int align, struct resource **parent) |
51 | { | 51 | { |
52 | if (!s->io_offset) | 52 | if (!s->io_offset) |
53 | return -EINVAL; | 53 | return -EINVAL; |
54 | *base = s->io_offset | (*base & 0x0fff); | 54 | *base = s->io_offset | (*base & 0x0fff); |
55 | *parent = NULL; | ||
55 | 56 | ||
56 | return 0; | 57 | return 0; |
57 | } | 58 | } |
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index c17a17d9f9b5..96f348b35fde 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
@@ -718,7 +718,7 @@ static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s, | |||
718 | 718 | ||
719 | static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | 719 | static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, |
720 | unsigned int *base, unsigned int num, | 720 | unsigned int *base, unsigned int num, |
721 | unsigned int align) | 721 | unsigned int align, struct resource **parent) |
722 | { | 722 | { |
723 | int i, ret = 0; | 723 | int i, ret = 0; |
724 | 724 | ||
@@ -760,6 +760,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
760 | ((res->flags & ~IORESOURCE_BITS) | | 760 | ((res->flags & ~IORESOURCE_BITS) | |
761 | (attr & IORESOURCE_BITS)); | 761 | (attr & IORESOURCE_BITS)); |
762 | s->io[i].InUse = num; | 762 | s->io[i].InUse = num; |
763 | *parent = res; | ||
763 | return 0; | 764 | return 0; |
764 | } | 765 | } |
765 | 766 | ||
@@ -775,6 +776,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
775 | continue; | 776 | continue; |
776 | *base = try; | 777 | *base = try; |
777 | s->io[i].InUse += num; | 778 | s->io[i].InUse += num; |
779 | *parent = res; | ||
778 | return 0; | 780 | return 0; |
779 | } | 781 | } |
780 | } | 782 | } |
@@ -793,6 +795,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
793 | continue; | 795 | continue; |
794 | *base = try; | 796 | *base = try; |
795 | s->io[i].InUse += num; | 797 | s->io[i].InUse += num; |
798 | *parent = res; | ||
796 | return 0; | 799 | return 0; |
797 | } | 800 | } |
798 | } | 801 | } |