sgi_hotplug.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved.
  7. *
  8. * This work was based on the 2.4/2.6 kernel development by Dick Reigner.
  9. * Work to add BIOS PROM support was completed by Mike Habeck.
  10. */
  11. #include <linux/init.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/pci.h>
  15. #include <linux/proc_fs.h>
  16. #include <linux/types.h>
  17. #include <asm/sn/addrs.h>
  18. #include <asm/sn/l1.h>
  19. #include <asm/sn/module.h>
  20. #include <asm/sn/pcibr_provider.h>
  21. #include <asm/sn/pcibus_provider_defs.h>
  22. #include <asm/sn/pcidev.h>
  23. #include <asm/sn/sn_sal.h>
  24. #include <asm/sn/types.h>
  25. #include "../pci.h"
  26. #include "pci_hotplug.h"
  27. MODULE_LICENSE("GPL");
  28. MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
  29. MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
  30. #define PCIIO_ASIC_TYPE_TIOCA 4
  31. #define PCI_SLOT_ALREADY_UP 2 /* slot already up */
  32. #define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
  33. #define PCI_L1_ERR 7 /* L1 console command error */
  34. #define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
  35. #define PCI_L1_QSIZE 128 /* our L1 message buffer size */
  36. #define SN_MAX_HP_SLOTS 32 /* max number of hotplug slots */
  37. #define SGI_HOTPLUG_PROM_REV 0x0420 /* Min. required PROM version */
  38. /* internal list head */
  39. static struct list_head sn_hp_list;
  40. /* hotplug_slot struct's private pointer */
  41. struct slot {
  42. int device_num;
  43. struct pci_bus *pci_bus;
  44. /* this struct for glue internal only */
  45. struct hotplug_slot *hotplug_slot;
  46. struct list_head hp_list;
  47. };
  48. struct pcibr_slot_enable_resp {
  49. int resp_sub_errno;
  50. char resp_l1_msg[PCI_L1_QSIZE + 1];
  51. };
  52. struct pcibr_slot_disable_resp {
  53. int resp_sub_errno;
  54. char resp_l1_msg[PCI_L1_QSIZE + 1];
  55. };
  56. enum sn_pci_req_e {
  57. PCI_REQ_SLOT_ELIGIBLE,
  58. PCI_REQ_SLOT_DISABLE
  59. };
  60. static int enable_slot(struct hotplug_slot *slot);
  61. static int disable_slot(struct hotplug_slot *slot);
  62. static int get_power_status(struct hotplug_slot *slot, u8 *value);
  63. static struct hotplug_slot_ops sn_hotplug_slot_ops = {
  64. .owner = THIS_MODULE,
  65. .enable_slot = enable_slot,
  66. .disable_slot = disable_slot,
  67. .get_power_status = get_power_status,
  68. };
  69. static DECLARE_MUTEX(sn_hotplug_sem);
  70. static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
  71. {
  72. struct pcibus_info *pcibus_info;
  73. int bricktype;
  74. int bus_num;
  75. pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
  76. /* Check to see if this is a valid slot on 'pci_bus' */
  77. if (!(pcibus_info->pbi_valid_devices & (1 << device)))
  78. return -EPERM;
  79. bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
  80. bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf;
  81. /* Do not allow hotplug operations on base I/O cards */
  82. if ((bricktype == L1_BRICKTYPE_IX || bricktype == L1_BRICKTYPE_IA) &&
  83. (bus_num == 1 && device != 1))
  84. return -EPERM;
  85. return 1;
  86. }
  87. static int sn_pci_bus_valid(struct pci_bus *pci_bus)
  88. {
  89. struct pcibus_info *pcibus_info;
  90. int asic_type;
  91. int bricktype;
  92. pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
  93. /* Don't register slots hanging off the TIOCA bus */
  94. asic_type = pcibus_info->pbi_buscommon.bs_asic_type;
  95. if (asic_type == PCIIO_ASIC_TYPE_TIOCA)
  96. return -EPERM;
  97. /* Only register slots in I/O Bricks that support hotplug */
  98. bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
  99. switch (bricktype) {
  100. case L1_BRICKTYPE_IX:
  101. case L1_BRICKTYPE_PX:
  102. case L1_BRICKTYPE_IA:
  103. case L1_BRICKTYPE_PA:
  104. return 1;
  105. break;
  106. default:
  107. return -EPERM;
  108. break;
  109. }
  110. return -EIO;
  111. }
  112. static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
  113. struct pci_bus *pci_bus, int device)
  114. {
  115. struct pcibus_info *pcibus_info;
  116. struct slot *slot;
  117. pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
  118. bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot),
  119. GFP_KERNEL);
  120. if (!bss_hotplug_slot->private)
  121. return -ENOMEM;
  122. slot = (struct slot *)bss_hotplug_slot->private;
  123. bss_hotplug_slot->name = kmalloc(33, GFP_KERNEL);
  124. if (!bss_hotplug_slot->name) {
  125. kfree(bss_hotplug_slot->private);
  126. return -ENOMEM;
  127. }
  128. slot->device_num = device;
  129. slot->pci_bus = pci_bus;
  130. sprintf(bss_hotplug_slot->name, "module_%c%c%c%c%.2d_b_%d_s_%d",
  131. '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
  132. '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
  133. '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
  134. MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
  135. MODULE_GET_BPOS(pcibus_info->pbi_moduleid),
  136. ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
  137. device + 1);
  138. slot->hotplug_slot = bss_hotplug_slot;
  139. list_add(&slot->hp_list, &sn_hp_list);
  140. return 0;
  141. }
  142. static struct hotplug_slot * sn_hp_destroy(void)
  143. {
  144. struct slot *slot;
  145. struct list_head *list;
  146. struct hotplug_slot *bss_hotplug_slot = NULL;
  147. list_for_each(list, &sn_hp_list) {
  148. slot = list_entry(list, struct slot, hp_list);
  149. bss_hotplug_slot = slot->hotplug_slot;
  150. list_del(&((struct slot *)bss_hotplug_slot->private)->
  151. hp_list);
  152. break;
  153. }
  154. return bss_hotplug_slot;
  155. }
  156. static void sn_bus_alloc_data(struct pci_dev *dev)
  157. {
  158. struct list_head *node;
  159. struct pci_bus *subordinate_bus;
  160. struct pci_dev *child;
  161. sn_pci_fixup_slot(dev);
  162. /* Recursively sets up the sn_irq_info structs */
  163. if (dev->subordinate) {
  164. subordinate_bus = dev->subordinate;
  165. list_for_each(node, &subordinate_bus->devices) {
  166. child = list_entry(node, struct pci_dev, bus_list);
  167. sn_bus_alloc_data(child);
  168. }
  169. }
  170. }
  171. static void sn_bus_free_data(struct pci_dev *dev)
  172. {
  173. struct list_head *node;
  174. struct pci_bus *subordinate_bus;
  175. struct pci_dev *child;
  176. /* Recursively clean up sn_irq_info structs */
  177. if (dev->subordinate) {
  178. subordinate_bus = dev->subordinate;
  179. list_for_each(node, &subordinate_bus->devices) {
  180. child = list_entry(node, struct pci_dev, bus_list);
  181. sn_bus_free_data(child);
  182. }
  183. }
  184. sn_pci_unfixup_slot(dev);
  185. }
  186. static u8 sn_power_status_get(struct hotplug_slot *bss_hotplug_slot)
  187. {
  188. struct slot *slot = (struct slot *)bss_hotplug_slot->private;
  189. struct pcibus_info *pcibus_info;
  190. u8 retval;
  191. pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
  192. retval = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
  193. return retval ? 1 : 0;
  194. }
  195. static void sn_slot_mark_enable(struct hotplug_slot *bss_hotplug_slot,
  196. int device_num)
  197. {
  198. struct slot *slot = (struct slot *)bss_hotplug_slot->private;
  199. struct pcibus_info *pcibus_info;
  200. pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
  201. pcibus_info->pbi_enabled_devices |= (1 << device_num);
  202. }
  203. static void sn_slot_mark_disable(struct hotplug_slot *bss_hotplug_slot,
  204. int device_num)
  205. {
  206. struct slot *slot = (struct slot *)bss_hotplug_slot->private;
  207. struct pcibus_info *pcibus_info;
  208. pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
  209. pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
  210. }
  211. static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
  212. int device_num)
  213. {
  214. struct slot *slot = (struct slot *)bss_hotplug_slot->private;
  215. struct pcibus_info *pcibus_info;
  216. struct pcibr_slot_enable_resp resp;
  217. int rc;
  218. pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
  219. /*
  220. * Power-on and initialize the slot in the SN
  221. * PCI infrastructure.
  222. */
  223. rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp);
  224. if (rc == PCI_SLOT_ALREADY_UP) {
  225. dev_dbg(slot->pci_bus->self, "is already active\n");
  226. return -EPERM;
  227. }
  228. if (rc == PCI_L1_ERR) {
  229. dev_dbg(slot->pci_bus->self,
  230. "L1 failure %d with message: %s",
  231. resp.resp_sub_errno, resp.resp_l1_msg);
  232. return -EPERM;
  233. }
  234. if (rc) {
  235. dev_dbg(slot->pci_bus->self,
  236. "insert failed with error %d sub-error %d\n",
  237. rc, resp.resp_sub_errno);
  238. return -EIO;
  239. }
  240. sn_slot_mark_enable(bss_hotplug_slot, device_num);
  241. return 0;
  242. }
  243. static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
  244. int device_num, int action)
  245. {
  246. struct slot *slot = (struct slot *)bss_hotplug_slot->private;
  247. struct pcibus_info *pcibus_info;
  248. struct pcibr_slot_disable_resp resp;
  249. int rc;
  250. pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
  251. rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp);
  252. if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_SLOT_ALREADY_DOWN) {
  253. dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n");
  254. return -ENODEV;
  255. }
  256. if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_EMPTY_33MHZ) {
  257. dev_dbg(slot->pci_bus->self,
  258. "Cannot remove last 33MHz card\n");
  259. return -EPERM;
  260. }
  261. if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_L1_ERR) {
  262. dev_dbg(slot->pci_bus->self,
  263. "L1 failure %d with message \n%s\n",
  264. resp.resp_sub_errno, resp.resp_l1_msg);
  265. return -EPERM;
  266. }
  267. if (action == PCI_REQ_SLOT_ELIGIBLE && rc) {
  268. dev_dbg(slot->pci_bus->self,
  269. "remove failed with error %d sub-error %d\n",
  270. rc, resp.resp_sub_errno);
  271. return -EIO;
  272. }
  273. if (action == PCI_REQ_SLOT_ELIGIBLE && !rc)
  274. return 0;
  275. if (action == PCI_REQ_SLOT_DISABLE && !rc) {
  276. sn_slot_mark_disable(bss_hotplug_slot, device_num);
  277. dev_dbg(slot->pci_bus->self, "remove successful\n");
  278. return 0;
  279. }
  280. if (action == PCI_REQ_SLOT_DISABLE && rc) {
  281. dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc);
  282. return rc;
  283. }
  284. return rc;
  285. }
  286. static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
  287. {
  288. struct slot *slot = (struct slot *)bss_hotplug_slot->private;
  289. struct pci_bus *new_bus = NULL;
  290. struct pci_dev *dev;
  291. int func, num_funcs;
  292. int new_ppb = 0;
  293. int rc;
  294. /* Serialize the Linux PCI infrastructure */
  295. down(&sn_hotplug_sem);
  296. /*
  297. * Power-on and initialize the slot in the SN
  298. * PCI infrastructure.
  299. */
  300. rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
  301. if (rc) {
  302. up(&sn_hotplug_sem);
  303. return rc;
  304. }
  305. num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1,
  306. PCI_FUNC(0)));
  307. if (!num_funcs) {
  308. dev_dbg(slot->pci_bus->self, "no device in slot\n");
  309. up(&sn_hotplug_sem);
  310. return -ENODEV;
  311. }
  312. sn_pci_controller_fixup(pci_domain_nr(slot->pci_bus),
  313. slot->pci_bus->number,
  314. slot->pci_bus);
  315. /*
  316. * Map SN resources for all functions on the card
  317. * to the Linux PCI interface and tell the drivers
  318. * about them.
  319. */
  320. for (func = 0; func < num_funcs; func++) {
  321. dev = pci_get_slot(slot->pci_bus,
  322. PCI_DEVFN(slot->device_num + 1,
  323. PCI_FUNC(func)));
  324. if (dev) {
  325. if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
  326. unsigned char sec_bus;
  327. pci_read_config_byte(dev, PCI_SECONDARY_BUS,
  328. &sec_bus);
  329. new_bus = pci_add_new_bus(dev->bus, dev,
  330. sec_bus);
  331. pci_scan_child_bus(new_bus);
  332. sn_pci_controller_fixup(pci_domain_nr(new_bus),
  333. new_bus->number,
  334. new_bus);
  335. new_ppb = 1;
  336. }
  337. sn_bus_alloc_data(dev);
  338. pci_dev_put(dev);
  339. }
  340. }
  341. /* Call the driver for the new device */
  342. pci_bus_add_devices(slot->pci_bus);
  343. /* Call the drivers for the new devices subordinate to PPB */
  344. if (new_ppb)
  345. pci_bus_add_devices(new_bus);
  346. up(&sn_hotplug_sem);
  347. if (rc == 0)
  348. dev_dbg(slot->pci_bus->self,
  349. "insert operation successful\n");
  350. else
  351. dev_dbg(slot->pci_bus->self,
  352. "insert operation failed rc = %d\n", rc);
  353. return rc;
  354. }
  355. static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
  356. {
  357. struct slot *slot = (struct slot *)bss_hotplug_slot->private;
  358. struct pci_dev *dev;
  359. int func;
  360. int rc;
  361. /* Acquire update access to the bus */
  362. down(&sn_hotplug_sem);
  363. /* is it okay to bring this slot down? */
  364. rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
  365. PCI_REQ_SLOT_ELIGIBLE);
  366. if (rc)
  367. goto leaving;
  368. /* Free the SN resources assigned to the Linux device.*/
  369. for (func = 0; func < 8; func++) {
  370. dev = pci_get_slot(slot->pci_bus,
  371. PCI_DEVFN(slot->device_num+1,
  372. PCI_FUNC(func)));
  373. if (dev) {
  374. /*
  375. * Some drivers may use dma accesses during the
  376. * driver remove function. We release the sysdata
  377. * areas after the driver remove functions have
  378. * been called.
  379. */
  380. sn_bus_store_sysdata(dev);
  381. sn_bus_free_data(dev);
  382. pci_remove_bus_device(dev);
  383. pci_dev_put(dev);
  384. }
  385. }
  386. /* free the collected sysdata pointers */
  387. sn_bus_free_sysdata();
  388. /* Deactivate slot */
  389. rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
  390. PCI_REQ_SLOT_DISABLE);
  391. leaving:
  392. /* Release the bus lock */
  393. up(&sn_hotplug_sem);
  394. return rc;
  395. }
  396. static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value)
  397. {
  398. down(&sn_hotplug_sem);
  399. *value = sn_power_status_get(bss_hotplug_slot);
  400. up(&sn_hotplug_sem);
  401. return 0;
  402. }
  403. static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
  404. {
  405. kfree(bss_hotplug_slot->info);
  406. kfree(bss_hotplug_slot->name);
  407. kfree(bss_hotplug_slot->private);
  408. kfree(bss_hotplug_slot);
  409. }
  410. static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
  411. {
  412. int device;
  413. struct hotplug_slot *bss_hotplug_slot;
  414. int rc = 0;
  415. /*
  416. * Currently only four devices are supported,
  417. * in the future there maybe more -- up to 32.
  418. */
  419. for (device = 0; device < SN_MAX_HP_SLOTS ; device++) {
  420. if (sn_pci_slot_valid(pci_bus, device) != 1)
  421. continue;
  422. bss_hotplug_slot = kcalloc(1,sizeof(struct hotplug_slot),
  423. GFP_KERNEL);
  424. if (!bss_hotplug_slot) {
  425. rc = -ENOMEM;
  426. goto alloc_err;
  427. }
  428. bss_hotplug_slot->info =
  429. kcalloc(1,sizeof(struct hotplug_slot_info),
  430. GFP_KERNEL);
  431. if (!bss_hotplug_slot->info) {
  432. rc = -ENOMEM;
  433. goto alloc_err;
  434. }
  435. if (sn_hp_slot_private_alloc(bss_hotplug_slot,
  436. pci_bus, device)) {
  437. rc = -ENOMEM;
  438. goto alloc_err;
  439. }
  440. bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
  441. bss_hotplug_slot->release = &sn_release_slot;
  442. rc = pci_hp_register(bss_hotplug_slot);
  443. if (rc)
  444. goto register_err;
  445. }
  446. dev_dbg(pci_bus->self, "Registered bus with hotplug\n");
  447. return rc;
  448. register_err:
  449. dev_dbg(pci_bus->self, "bus failed to register with err = %d\n",
  450. rc);
  451. alloc_err:
  452. if (rc == -ENOMEM)
  453. dev_dbg(pci_bus->self, "Memory allocation error\n");
  454. /* destroy THIS element */
  455. if (bss_hotplug_slot)
  456. sn_release_slot(bss_hotplug_slot);
  457. /* destroy anything else on the list */
  458. while ((bss_hotplug_slot = sn_hp_destroy()))
  459. pci_hp_deregister(bss_hotplug_slot);
  460. return rc;
  461. }
  462. static int sn_pci_hotplug_init(void)
  463. {
  464. struct pci_bus *pci_bus = NULL;
  465. int rc;
  466. int registered = 0;
  467. INIT_LIST_HEAD(&sn_hp_list);
  468. if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
  469. printk(KERN_ERR "%s: PROM version must be greater than 4.05\n",
  470. __FUNCTION__);
  471. return -EPERM;
  472. }
  473. while ((pci_bus = pci_find_next_bus(pci_bus))) {
  474. if (!pci_bus->sysdata)
  475. continue;
  476. rc = sn_pci_bus_valid(pci_bus);
  477. if (rc != 1) {
  478. dev_dbg(pci_bus->self, "not a valid hotplug bus\n");
  479. continue;
  480. }
  481. dev_dbg(pci_bus->self, "valid hotplug bus\n");
  482. rc = sn_hotplug_slot_register(pci_bus);
  483. if (!rc)
  484. registered = 1;
  485. else {
  486. registered = 0;
  487. break;
  488. }
  489. }
  490. return registered == 1 ? 0 : -ENODEV;
  491. }
  492. static void sn_pci_hotplug_exit(void)
  493. {
  494. struct hotplug_slot *bss_hotplug_slot;
  495. while ((bss_hotplug_slot = sn_hp_destroy())) {
  496. pci_hp_deregister(bss_hotplug_slot);
  497. }
  498. if (!list_empty(&sn_hp_list))
  499. printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
  500. }
  501. module_init(sn_pci_hotplug_init);
  502. module_exit(sn_pci_hotplug_exit);