diff options
-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 | } |