aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert@linux-m68k.org>2013-06-29 04:40:20 -0400
committerGeert Uytterhoeven <geert@linux-m68k.org>2013-11-26 05:09:03 -0500
commitc293738e6d8dfb9c941759855b5161fde449644d (patch)
tree3c2d4b2041af3e2fe5a8a4702cdfe49fca3e1f7f
parent1ea636eb68322198e08aebdede141244d98e8299 (diff)
zorro: Do not allocate zorro_autocon[] statically
Currently the array of Zorro devices is allocated statically, wasting up to 4.5 KiB when running an Amiga or multi-platform kernel on a machine with no or a handful of Zorro expansion cards. Convert it to conditional dynamic memory allocation to fix this. amiga_parse_bootinfo() still needs to store some information about the detected Zorro devices, at a time even the bootmem allocator is not yet available. This is now handled using a much smaller array (typically less than 0.5 KiB), which is __initdata and thus freed later. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-rw-r--r--arch/m68k/amiga/config.c6
-rw-r--r--arch/m68k/amiga/platform.c4
-rw-r--r--drivers/zorro/zorro.c19
-rw-r--r--include/linux/zorro.h18
4 files changed, 38 insertions, 9 deletions
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 93ab423758da..d956ddbfebe1 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -174,12 +174,12 @@ int __init amiga_parse_bootinfo(const struct bi_record *record)
174#ifdef CONFIG_ZORRO 174#ifdef CONFIG_ZORRO
175 if (zorro_num_autocon < ZORRO_NUM_AUTO) { 175 if (zorro_num_autocon < ZORRO_NUM_AUTO) {
176 const struct ConfigDev *cd = (struct ConfigDev *)data; 176 const struct ConfigDev *cd = (struct ConfigDev *)data;
177 struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++]; 177 struct zorro_dev_init *dev = &zorro_autocon_init[zorro_num_autocon++];
178 dev->rom = cd->cd_Rom; 178 dev->rom = cd->cd_Rom;
179 dev->slotaddr = cd->cd_SlotAddr; 179 dev->slotaddr = cd->cd_SlotAddr;
180 dev->slotsize = cd->cd_SlotSize; 180 dev->slotsize = cd->cd_SlotSize;
181 dev->resource.start = (unsigned long)cd->cd_BoardAddr; 181 dev->boardaddr = (u32)cd->cd_BoardAddr;
182 dev->resource.end = dev->resource.start + cd->cd_BoardSize - 1; 182 dev->boardsize = cd->cd_BoardSize;
183 } else 183 } else
184 printk("amiga_parse_bootinfo: too many AutoConfig devices\n"); 184 printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
185#endif /* CONFIG_ZORRO */ 185#endif /* CONFIG_ZORRO */
diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c
index dacd9f911f71..7847b2b1b5b6 100644
--- a/arch/m68k/amiga/platform.c
+++ b/arch/m68k/amiga/platform.c
@@ -67,8 +67,8 @@ static int __init z_dev_present(zorro_id id)
67 unsigned int i; 67 unsigned int i;
68 68
69 for (i = 0; i < zorro_num_autocon; i++) 69 for (i = 0; i < zorro_num_autocon; i++)
70 if (zorro_autocon[i].rom.er_Manufacturer == ZORRO_MANUF(id) && 70 if (zorro_autocon_init[i].rom.er_Manufacturer == ZORRO_MANUF(id) &&
71 zorro_autocon[i].rom.er_Product == ZORRO_PROD(id)) 71 zorro_autocon_init[i].rom.er_Product == ZORRO_PROD(id))
72 return 1; 72 return 1;
73 73
74 return 0; 74 return 0;
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index 858c9714b2f3..10c7f77aec08 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -29,7 +29,8 @@
29 */ 29 */
30 30
31unsigned int zorro_num_autocon; 31unsigned int zorro_num_autocon;
32struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; 32struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata;
33struct zorro_dev *zorro_autocon;
33 34
34 35
35 /* 36 /*
@@ -38,6 +39,7 @@ struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];
38 39
39struct zorro_bus { 40struct zorro_bus {
40 struct device dev; 41 struct device dev;
42 struct zorro_dev devices[0];
41}; 43};
42 44
43 45
@@ -125,16 +127,20 @@ static struct resource __init *zorro_find_parent_resource(
125static int __init amiga_zorro_probe(struct platform_device *pdev) 127static int __init amiga_zorro_probe(struct platform_device *pdev)
126{ 128{
127 struct zorro_bus *bus; 129 struct zorro_bus *bus;
130 struct zorro_dev_init *zi;
128 struct zorro_dev *z; 131 struct zorro_dev *z;
129 struct resource *r; 132 struct resource *r;
130 unsigned int i; 133 unsigned int i;
131 int error; 134 int error;
132 135
133 /* Initialize the Zorro bus */ 136 /* Initialize the Zorro bus */
134 bus = kzalloc(sizeof(*bus), GFP_KERNEL); 137 bus = kzalloc(sizeof(*bus) +
138 zorro_num_autocon * sizeof(bus->devices[0]),
139 GFP_KERNEL);
135 if (!bus) 140 if (!bus)
136 return -ENOMEM; 141 return -ENOMEM;
137 142
143 zorro_autocon = bus->devices;
138 bus->dev.parent = &pdev->dev; 144 bus->dev.parent = &pdev->dev;
139 dev_set_name(&bus->dev, "zorro"); 145 dev_set_name(&bus->dev, "zorro");
140 error = device_register(&bus->dev); 146 error = device_register(&bus->dev);
@@ -151,15 +157,22 @@ static int __init amiga_zorro_probe(struct platform_device *pdev)
151 157
152 /* First identify all devices ... */ 158 /* First identify all devices ... */
153 for (i = 0; i < zorro_num_autocon; i++) { 159 for (i = 0; i < zorro_num_autocon; i++) {
160 zi = &zorro_autocon_init[i];
154 z = &zorro_autocon[i]; 161 z = &zorro_autocon[i];
162
163 z->rom = zi->rom;
155 z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); 164 z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8);
156 if (z->id == ZORRO_PROD_GVP_EPC_BASE) { 165 if (z->id == ZORRO_PROD_GVP_EPC_BASE) {
157 /* GVP quirk */ 166 /* GVP quirk */
158 unsigned long magic = zorro_resource_start(z)+0x8000; 167 unsigned long magic = zi->boardaddr + 0x8000;
159 z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; 168 z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK;
160 } 169 }
170 z->slotaddr = zi->slotaddr;
171 z->slotsize = zi->slotsize;
161 sprintf(z->name, "Zorro device %08x", z->id); 172 sprintf(z->name, "Zorro device %08x", z->id);
162 zorro_name_device(z); 173 zorro_name_device(z);
174 z->resource.start = zi->boardaddr;
175 z->resource.end = zi->boardaddr + zi->boardsize - 1;
163 z->resource.name = z->name; 176 z->resource.name = z->name;
164 r = zorro_find_parent_resource(pdev, z); 177 r = zorro_find_parent_resource(pdev, z);
165 error = request_resource(r, &z->resource); 178 error = request_resource(r, &z->resource);
diff --git a/include/linux/zorro.h b/include/linux/zorro.h
index dff42025649b..661cbd2a86ee 100644
--- a/include/linux/zorro.h
+++ b/include/linux/zorro.h
@@ -175,7 +175,23 @@ static inline struct zorro_driver *zorro_dev_driver(const struct zorro_dev *z)
175 175
176 176
177extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */ 177extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */
178extern struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; 178extern struct zorro_dev *zorro_autocon;
179
180
181 /*
182 * Minimal information about a Zorro device, passed from bootinfo
183 * Only available temporarily, i.e. until initmem has been freed!
184 */
185
186struct zorro_dev_init {
187 struct ExpansionRom rom;
188 u16 slotaddr;
189 u16 slotsize;
190 u32 boardaddr;
191 u32 boardsize;
192};
193
194extern struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata;
179 195
180 196
181 /* 197 /*