acpiphp_pci.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * ACPI PCI HotPlug PCI configuration space management
  3. *
  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
  10. *
  11. * All rights reserved.
  12. *
  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.
  17. *
  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.
  23. *
  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.
  27. *
  28. * Send feedback to <t-kochi@bq.jp.nec.com>
  29. *
  30. */
  31. #include <linux/init.h>
  32. #include <linux/module.h>
  33. #include <linux/kernel.h>
  34. #include <linux/pci.h>
  35. #include <linux/acpi.h>
  36. #include "../pci.h"
  37. #include "pci_hotplug.h"
  38. #include "acpiphp.h"
  39. #define MY_NAME "acpiphp_pci"
  40. /* allocate mem/pmem/io resource to a new function */
  41. static int init_config_space (struct acpiphp_func *func)
  42. {
  43. u32 bar, len;
  44. u32 address[] = {
  45. PCI_BASE_ADDRESS_0,
  46. PCI_BASE_ADDRESS_1,
  47. PCI_BASE_ADDRESS_2,
  48. PCI_BASE_ADDRESS_3,
  49. PCI_BASE_ADDRESS_4,
  50. PCI_BASE_ADDRESS_5,
  51. 0
  52. };
  53. int count;
  54. struct acpiphp_bridge *bridge;
  55. struct pci_resource *res;
  56. struct pci_bus *pbus;
  57. int bus, device, function;
  58. unsigned int devfn;
  59. u16 tmp;
  60. bridge = func->slot->bridge;
  61. pbus = bridge->pci_bus;
  62. bus = bridge->bus;
  63. device = func->slot->device;
  64. function = func->function;
  65. devfn = PCI_DEVFN(device, function);
  66. for (count = 0; address[count]; count++) { /* for 6 BARs */
  67. pci_bus_write_config_dword(pbus, devfn,
  68. address[count], 0xFFFFFFFF);
  69. pci_bus_read_config_dword(pbus, devfn, address[count], &bar);
  70. if (!bar) /* This BAR is not implemented */
  71. continue;
  72. dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
  73. if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
  74. /* This is IO */
  75. len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
  76. len = len & ~(len - 1);
  77. dbg("len in IO %x, BAR %d\n", len, count);
  78. spin_lock(&bridge->res_lock);
  79. res = acpiphp_get_io_resource(&bridge->io_head, len);
  80. spin_unlock(&bridge->res_lock);
  81. if (!res) {
  82. err("cannot allocate requested io for %02x:%02x.%d len %x\n",
  83. bus, device, function, len);
  84. return -1;
  85. }
  86. pci_bus_write_config_dword(pbus, devfn,
  87. address[count],
  88. (u32)res->base);
  89. res->next = func->io_head;
  90. func->io_head = res;
  91. } else {
  92. /* This is Memory */
  93. if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
  94. /* pfmem */
  95. len = bar & 0xFFFFFFF0;
  96. len = ~len + 1;
  97. dbg("len in PFMEM %x, BAR %d\n", len, count);
  98. spin_lock(&bridge->res_lock);
  99. res = acpiphp_get_resource(&bridge->p_mem_head, len);
  100. spin_unlock(&bridge->res_lock);
  101. if (!res) {
  102. err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
  103. bus, device, function, len);
  104. return -1;
  105. }
  106. pci_bus_write_config_dword(pbus, devfn,
  107. address[count],
  108. (u32)res->base);
  109. if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
  110. dbg("inside the pfmem 64 case, count %d\n", count);
  111. count += 1;
  112. pci_bus_write_config_dword(pbus, devfn,
  113. address[count],
  114. (u32)(res->base >> 32));
  115. }
  116. res->next = func->p_mem_head;
  117. func->p_mem_head = res;
  118. } else {
  119. /* regular memory */
  120. len = bar & 0xFFFFFFF0;
  121. len = ~len + 1;
  122. dbg("len in MEM %x, BAR %d\n", len, count);
  123. spin_lock(&bridge->res_lock);
  124. res = acpiphp_get_resource(&bridge->mem_head, len);
  125. spin_unlock(&bridge->res_lock);
  126. if (!res) {
  127. err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
  128. bus, device, function, len);
  129. return -1;
  130. }
  131. pci_bus_write_config_dword(pbus, devfn,
  132. address[count],
  133. (u32)res->base);
  134. if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
  135. /* takes up another dword */
  136. dbg("inside mem 64 case, reg. mem, count %d\n", count);
  137. count += 1;
  138. pci_bus_write_config_dword(pbus, devfn,
  139. address[count],
  140. (u32)(res->base >> 32));
  141. }
  142. res->next = func->mem_head;
  143. func->mem_head = res;
  144. }
  145. }
  146. }
  147. /* disable expansion rom */
  148. pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);
  149. /* set PCI parameters from _HPP */
  150. pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE,
  151. bridge->hpp.cache_line_size);
  152. pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER,
  153. bridge->hpp.latency_timer);
  154. pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp);
  155. if (bridge->hpp.enable_SERR)
  156. tmp |= PCI_COMMAND_SERR;
  157. if (bridge->hpp.enable_PERR)
  158. tmp |= PCI_COMMAND_PARITY;
  159. pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp);
  160. return 0;
  161. }
  162. /* detect_used_resource - subtract resource under dev from bridge */
  163. static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
  164. {
  165. int count;
  166. dbg("Device %s\n", pci_name(dev));
  167. for (count = 0; count < DEVICE_COUNT_RESOURCE; count++) {
  168. struct pci_resource *res;
  169. struct pci_resource **head;
  170. unsigned long base = dev->resource[count].start;
  171. unsigned long len = dev->resource[count].end - base + 1;
  172. unsigned long flags = dev->resource[count].flags;
  173. if (!flags)
  174. continue;
  175. dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,
  176. base + len - 1, flags);
  177. if (flags & IORESOURCE_IO) {
  178. head = &bridge->io_head;
  179. } else if (flags & IORESOURCE_PREFETCH) {
  180. head = &bridge->p_mem_head;
  181. } else {
  182. head = &bridge->mem_head;
  183. }
  184. spin_lock(&bridge->res_lock);
  185. res = acpiphp_get_resource_with_base(head, base, len);
  186. spin_unlock(&bridge->res_lock);
  187. if (res)
  188. kfree(res);
  189. }
  190. return 0;
  191. }
  192. /**
  193. * acpiphp_detect_pci_resource - detect resources under bridge
  194. * @bridge: detect all resources already used under this bridge
  195. *
  196. * collect all resources already allocated for all devices under a bridge.
  197. */
  198. int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
  199. {
  200. struct list_head *l;
  201. struct pci_dev *dev;
  202. list_for_each (l, &bridge->pci_bus->devices) {
  203. dev = pci_dev_b(l);
  204. detect_used_resource(bridge, dev);
  205. }
  206. return 0;
  207. }
  208. /**
  209. * acpiphp_init_slot_resource - gather resource usage information of a slot
  210. * @slot: ACPI slot object to be checked, should have valid pci_dev member
  211. *
  212. * TBD: PCI-to-PCI bridge case
  213. * use pci_dev->resource[]
  214. */
  215. int acpiphp_init_func_resource (struct acpiphp_func *func)
  216. {
  217. u64 base;
  218. u32 bar, len;
  219. u32 address[] = {
  220. PCI_BASE_ADDRESS_0,
  221. PCI_BASE_ADDRESS_1,
  222. PCI_BASE_ADDRESS_2,
  223. PCI_BASE_ADDRESS_3,
  224. PCI_BASE_ADDRESS_4,
  225. PCI_BASE_ADDRESS_5,
  226. 0
  227. };
  228. int count;
  229. struct pci_resource *res;
  230. struct pci_dev *dev;
  231. dev = func->pci_dev;
  232. dbg("Hot-pluggable device %s\n", pci_name(dev));
  233. for (count = 0; address[count]; count++) { /* for 6 BARs */
  234. pci_read_config_dword(dev, address[count], &bar);
  235. if (!bar) /* This BAR is not implemented */
  236. continue;
  237. pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
  238. pci_read_config_dword(dev, address[count], &len);
  239. if (len & PCI_BASE_ADDRESS_SPACE_IO) {
  240. /* This is IO */
  241. base = bar & 0xFFFFFFFC;
  242. len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
  243. len = len & ~(len - 1);
  244. dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
  245. res = acpiphp_make_resource(base, len);
  246. if (!res)
  247. goto no_memory;
  248. res->next = func->io_head;
  249. func->io_head = res;
  250. } else {
  251. /* This is Memory */
  252. base = bar & 0xFFFFFFF0;
  253. if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
  254. /* pfmem */
  255. len &= 0xFFFFFFF0;
  256. len = ~len + 1;
  257. if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
  258. dbg("prefetch mem 64\n");
  259. count += 1;
  260. }
  261. dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
  262. res = acpiphp_make_resource(base, len);
  263. if (!res)
  264. goto no_memory;
  265. res->next = func->p_mem_head;
  266. func->p_mem_head = res;
  267. } else {
  268. /* regular memory */
  269. len &= 0xFFFFFFF0;
  270. len = ~len + 1;
  271. if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
  272. /* takes up another dword */
  273. dbg("mem 64\n");
  274. count += 1;
  275. }
  276. dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
  277. res = acpiphp_make_resource(base, len);
  278. if (!res)
  279. goto no_memory;
  280. res->next = func->mem_head;
  281. func->mem_head = res;
  282. }
  283. }
  284. pci_write_config_dword(dev, address[count], bar);
  285. }
  286. #if 1
  287. acpiphp_dump_func_resource(func);
  288. #endif
  289. return 0;
  290. no_memory:
  291. err("out of memory\n");
  292. acpiphp_free_resource(&func->io_head);
  293. acpiphp_free_resource(&func->mem_head);
  294. acpiphp_free_resource(&func->p_mem_head);
  295. return -1;
  296. }
  297. /**
  298. * acpiphp_configure_slot - allocate PCI resources
  299. * @slot: slot to be configured
  300. *
  301. * initializes a PCI functions on a device inserted
  302. * into the slot
  303. *
  304. */
  305. int acpiphp_configure_slot (struct acpiphp_slot *slot)
  306. {
  307. struct acpiphp_func *func;
  308. struct list_head *l;
  309. u8 hdr;
  310. u32 dvid;
  311. int retval = 0;
  312. int is_multi = 0;
  313. pci_bus_read_config_byte(slot->bridge->pci_bus,
  314. PCI_DEVFN(slot->device, 0),
  315. PCI_HEADER_TYPE, &hdr);
  316. if (hdr & 0x80)
  317. is_multi = 1;
  318. list_for_each (l, &slot->funcs) {
  319. func = list_entry(l, struct acpiphp_func, sibling);
  320. if (is_multi || func->function == 0) {
  321. pci_bus_read_config_dword(slot->bridge->pci_bus,
  322. PCI_DEVFN(slot->device,
  323. func->function),
  324. PCI_VENDOR_ID, &dvid);
  325. if (dvid != 0xffffffff) {
  326. retval = init_config_space(func);
  327. if (retval)
  328. break;
  329. }
  330. }
  331. }
  332. return retval;
  333. }
  334. /**
  335. * acpiphp_configure_function - configure PCI function
  336. * @func: function to be configured
  337. *
  338. * initializes a PCI functions on a device inserted
  339. * into the slot
  340. *
  341. */
  342. int acpiphp_configure_function (struct acpiphp_func *func)
  343. {
  344. /* all handled by the pci core now */
  345. return 0;
  346. }
  347. /**
  348. * acpiphp_unconfigure_function - unconfigure PCI function
  349. * @func: function to be unconfigured
  350. *
  351. */
  352. void acpiphp_unconfigure_function (struct acpiphp_func *func)
  353. {
  354. struct acpiphp_bridge *bridge;
  355. /* if pci_dev is NULL, ignore it */
  356. if (!func->pci_dev)
  357. return;
  358. pci_remove_bus_device(func->pci_dev);
  359. /* free all resources */
  360. bridge = func->slot->bridge;
  361. spin_lock(&bridge->res_lock);
  362. acpiphp_move_resource(&func->io_head, &bridge->io_head);
  363. acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
  364. acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
  365. acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
  366. spin_unlock(&bridge->res_lock);
  367. }