diff options
author | Geert Uytterhoeven <geert@linux-m68k.org> | 2013-06-29 04:40:20 -0400 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2013-11-26 05:09:03 -0500 |
commit | c293738e6d8dfb9c941759855b5161fde449644d (patch) | |
tree | 3c2d4b2041af3e2fe5a8a4702cdfe49fca3e1f7f | |
parent | 1ea636eb68322198e08aebdede141244d98e8299 (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.c | 6 | ||||
-rw-r--r-- | arch/m68k/amiga/platform.c | 4 | ||||
-rw-r--r-- | drivers/zorro/zorro.c | 19 | ||||
-rw-r--r-- | include/linux/zorro.h | 18 |
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 | ||
31 | unsigned int zorro_num_autocon; | 31 | unsigned int zorro_num_autocon; |
32 | struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; | 32 | struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata; |
33 | struct zorro_dev *zorro_autocon; | ||
33 | 34 | ||
34 | 35 | ||
35 | /* | 36 | /* |
@@ -38,6 +39,7 @@ struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; | |||
38 | 39 | ||
39 | struct zorro_bus { | 40 | struct 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( | |||
125 | static int __init amiga_zorro_probe(struct platform_device *pdev) | 127 | static 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 | ||
177 | extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */ | 177 | extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */ |
178 | extern struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; | 178 | extern 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 | |||
186 | struct zorro_dev_init { | ||
187 | struct ExpansionRom rom; | ||
188 | u16 slotaddr; | ||
189 | u16 slotsize; | ||
190 | u32 boardaddr; | ||
191 | u32 boardsize; | ||
192 | }; | ||
193 | |||
194 | extern struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata; | ||
179 | 195 | ||
180 | 196 | ||
181 | /* | 197 | /* |