[TG3]: Set minimal hw interrupt mitigation.
[linux-2.6/verdex.git] / drivers / pci / hotplug / acpiphp_pci.c
blob54d97c9d1dffb5656713a70bcd8e9d3d8fdc8b11
1 /*
2 * ACPI PCI HotPlug PCI configuration space management
4 * Copyright (C) 1995,2001 Compaq Computer Corporation
5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6 * Copyright (C) 2001,2002 IBM Corp.
7 * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
8 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
9 * Copyright (C) 2002 NEC Corporation
11 * All rights reserved.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or (at
16 * your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
21 * NON INFRINGEMENT. See the GNU General Public License for more
22 * details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * Send feedback to <t-kochi@bq.jp.nec.com>
32 #include <linux/init.h>
33 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/pci.h>
37 #include <linux/acpi.h>
38 #include "../pci.h"
39 #include "pci_hotplug.h"
40 #include "acpiphp.h"
42 #define MY_NAME "acpiphp_pci"
45 /* allocate mem/pmem/io resource to a new function */
46 static int init_config_space (struct acpiphp_func *func)
48 u32 bar, len;
49 u32 address[] = {
50 PCI_BASE_ADDRESS_0,
51 PCI_BASE_ADDRESS_1,
52 PCI_BASE_ADDRESS_2,
53 PCI_BASE_ADDRESS_3,
54 PCI_BASE_ADDRESS_4,
55 PCI_BASE_ADDRESS_5,
58 int count;
59 struct acpiphp_bridge *bridge;
60 struct pci_resource *res;
61 struct pci_bus *pbus;
62 int bus, device, function;
63 unsigned int devfn;
64 u16 tmp;
66 bridge = func->slot->bridge;
67 pbus = bridge->pci_bus;
68 bus = bridge->bus;
69 device = func->slot->device;
70 function = func->function;
71 devfn = PCI_DEVFN(device, function);
73 for (count = 0; address[count]; count++) { /* for 6 BARs */
74 pci_bus_write_config_dword(pbus, devfn,
75 address[count], 0xFFFFFFFF);
76 pci_bus_read_config_dword(pbus, devfn, address[count], &bar);
78 if (!bar) /* This BAR is not implemented */
79 continue;
81 dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
83 if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
84 /* This is IO */
86 len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
87 len = len & ~(len - 1);
89 dbg("len in IO %x, BAR %d\n", len, count);
91 spin_lock(&bridge->res_lock);
92 res = acpiphp_get_io_resource(&bridge->io_head, len);
93 spin_unlock(&bridge->res_lock);
95 if (!res) {
96 err("cannot allocate requested io for %02x:%02x.%d len %x\n",
97 bus, device, function, len);
98 return -1;
100 pci_bus_write_config_dword(pbus, devfn,
101 address[count],
102 (u32)res->base);
103 res->next = func->io_head;
104 func->io_head = res;
106 } else {
107 /* This is Memory */
108 if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
109 /* pfmem */
111 len = bar & 0xFFFFFFF0;
112 len = ~len + 1;
114 dbg("len in PFMEM %x, BAR %d\n", len, count);
116 spin_lock(&bridge->res_lock);
117 res = acpiphp_get_resource(&bridge->p_mem_head, len);
118 spin_unlock(&bridge->res_lock);
120 if (!res) {
121 err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
122 bus, device, function, len);
123 return -1;
126 pci_bus_write_config_dword(pbus, devfn,
127 address[count],
128 (u32)res->base);
130 if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
131 dbg("inside the pfmem 64 case, count %d\n", count);
132 count += 1;
133 pci_bus_write_config_dword(pbus, devfn,
134 address[count],
135 (u32)(res->base >> 32));
138 res->next = func->p_mem_head;
139 func->p_mem_head = res;
141 } else {
142 /* regular memory */
144 len = bar & 0xFFFFFFF0;
145 len = ~len + 1;
147 dbg("len in MEM %x, BAR %d\n", len, count);
149 spin_lock(&bridge->res_lock);
150 res = acpiphp_get_resource(&bridge->mem_head, len);
151 spin_unlock(&bridge->res_lock);
153 if (!res) {
154 err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
155 bus, device, function, len);
156 return -1;
159 pci_bus_write_config_dword(pbus, devfn,
160 address[count],
161 (u32)res->base);
163 if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
164 /* takes up another dword */
165 dbg("inside mem 64 case, reg. mem, count %d\n", count);
166 count += 1;
167 pci_bus_write_config_dword(pbus, devfn,
168 address[count],
169 (u32)(res->base >> 32));
172 res->next = func->mem_head;
173 func->mem_head = res;
179 /* disable expansion rom */
180 pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);
182 /* set PCI parameters from _HPP */
183 pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE,
184 bridge->hpp.cache_line_size);
185 pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER,
186 bridge->hpp.latency_timer);
188 pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp);
189 if (bridge->hpp.enable_SERR)
190 tmp |= PCI_COMMAND_SERR;
191 if (bridge->hpp.enable_PERR)
192 tmp |= PCI_COMMAND_PARITY;
193 pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp);
195 return 0;
198 /* detect_used_resource - subtract resource under dev from bridge */
199 static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
201 int count;
203 dbg("Device %s\n", pci_name(dev));
205 for (count = 0; count < DEVICE_COUNT_RESOURCE; count++) {
206 struct pci_resource *res;
207 struct pci_resource **head;
208 unsigned long base = dev->resource[count].start;
209 unsigned long len = dev->resource[count].end - base + 1;
210 unsigned long flags = dev->resource[count].flags;
212 if (!flags)
213 continue;
215 dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,
216 base + len - 1, flags);
218 if (flags & IORESOURCE_IO) {
219 head = &bridge->io_head;
220 } else if (flags & IORESOURCE_PREFETCH) {
221 head = &bridge->p_mem_head;
222 } else {
223 head = &bridge->mem_head;
226 spin_lock(&bridge->res_lock);
227 res = acpiphp_get_resource_with_base(head, base, len);
228 spin_unlock(&bridge->res_lock);
229 if (res)
230 kfree(res);
233 return 0;
238 * acpiphp_detect_pci_resource - detect resources under bridge
239 * @bridge: detect all resources already used under this bridge
241 * collect all resources already allocated for all devices under a bridge.
243 int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
245 struct list_head *l;
246 struct pci_dev *dev;
248 list_for_each (l, &bridge->pci_bus->devices) {
249 dev = pci_dev_b(l);
250 detect_used_resource(bridge, dev);
253 return 0;
258 * acpiphp_init_slot_resource - gather resource usage information of a slot
259 * @slot: ACPI slot object to be checked, should have valid pci_dev member
261 * TBD: PCI-to-PCI bridge case
262 * use pci_dev->resource[]
264 int acpiphp_init_func_resource (struct acpiphp_func *func)
266 u64 base;
267 u32 bar, len;
268 u32 address[] = {
269 PCI_BASE_ADDRESS_0,
270 PCI_BASE_ADDRESS_1,
271 PCI_BASE_ADDRESS_2,
272 PCI_BASE_ADDRESS_3,
273 PCI_BASE_ADDRESS_4,
274 PCI_BASE_ADDRESS_5,
277 int count;
278 struct pci_resource *res;
279 struct pci_dev *dev;
281 dev = func->pci_dev;
282 dbg("Hot-pluggable device %s\n", pci_name(dev));
284 for (count = 0; address[count]; count++) { /* for 6 BARs */
285 pci_read_config_dword(dev, address[count], &bar);
287 if (!bar) /* This BAR is not implemented */
288 continue;
290 pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
291 pci_read_config_dword(dev, address[count], &len);
293 if (len & PCI_BASE_ADDRESS_SPACE_IO) {
294 /* This is IO */
295 base = bar & 0xFFFFFFFC;
296 len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
297 len = len & ~(len - 1);
299 dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
301 res = acpiphp_make_resource(base, len);
302 if (!res)
303 goto no_memory;
305 res->next = func->io_head;
306 func->io_head = res;
308 } else {
309 /* This is Memory */
310 base = bar & 0xFFFFFFF0;
311 if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
312 /* pfmem */
314 len &= 0xFFFFFFF0;
315 len = ~len + 1;
317 if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
318 dbg("prefetch mem 64\n");
319 count += 1;
321 dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
322 res = acpiphp_make_resource(base, len);
323 if (!res)
324 goto no_memory;
326 res->next = func->p_mem_head;
327 func->p_mem_head = res;
329 } else {
330 /* regular memory */
332 len &= 0xFFFFFFF0;
333 len = ~len + 1;
335 if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
336 /* takes up another dword */
337 dbg("mem 64\n");
338 count += 1;
340 dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
341 res = acpiphp_make_resource(base, len);
342 if (!res)
343 goto no_memory;
345 res->next = func->mem_head;
346 func->mem_head = res;
351 pci_write_config_dword(dev, address[count], bar);
353 #if 1
354 acpiphp_dump_func_resource(func);
355 #endif
357 return 0;
359 no_memory:
360 err("out of memory\n");
361 acpiphp_free_resource(&func->io_head);
362 acpiphp_free_resource(&func->mem_head);
363 acpiphp_free_resource(&func->p_mem_head);
365 return -1;
370 * acpiphp_configure_slot - allocate PCI resources
371 * @slot: slot to be configured
373 * initializes a PCI functions on a device inserted
374 * into the slot
377 int acpiphp_configure_slot (struct acpiphp_slot *slot)
379 struct acpiphp_func *func;
380 struct list_head *l;
381 u8 hdr;
382 u32 dvid;
383 int retval = 0;
384 int is_multi = 0;
386 pci_bus_read_config_byte(slot->bridge->pci_bus,
387 PCI_DEVFN(slot->device, 0),
388 PCI_HEADER_TYPE, &hdr);
390 if (hdr & 0x80)
391 is_multi = 1;
393 list_for_each (l, &slot->funcs) {
394 func = list_entry(l, struct acpiphp_func, sibling);
395 if (is_multi || func->function == 0) {
396 pci_bus_read_config_dword(slot->bridge->pci_bus,
397 PCI_DEVFN(slot->device,
398 func->function),
399 PCI_VENDOR_ID, &dvid);
400 if (dvid != 0xffffffff) {
401 retval = init_config_space(func);
402 if (retval)
403 break;
408 return retval;
412 * acpiphp_configure_function - configure PCI function
413 * @func: function to be configured
415 * initializes a PCI functions on a device inserted
416 * into the slot
419 int acpiphp_configure_function (struct acpiphp_func *func)
421 /* all handled by the pci core now */
422 return 0;
426 * acpiphp_unconfigure_function - unconfigure PCI function
427 * @func: function to be unconfigured
430 void acpiphp_unconfigure_function (struct acpiphp_func *func)
432 struct acpiphp_bridge *bridge;
434 /* if pci_dev is NULL, ignore it */
435 if (!func->pci_dev)
436 return;
438 pci_remove_bus_device(func->pci_dev);
440 /* free all resources */
441 bridge = func->slot->bridge;
443 spin_lock(&bridge->res_lock);
444 acpiphp_move_resource(&func->io_head, &bridge->io_head);
445 acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
446 acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
447 acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
448 spin_unlock(&bridge->res_lock);