pciehp_core.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * PCI Express Hot Plug Controller Driver
  4. *
  5. * Copyright (C) 1995,2001 Compaq Computer Corporation
  6. * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
  7. * Copyright (C) 2001 IBM Corp.
  8. * Copyright (C) 2003-2004 Intel Corporation
  9. *
  10. * All rights reserved.
  11. *
  12. * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  13. *
  14. * Authors:
  15. * Dan Zink <dan.zink@compaq.com>
  16. * Greg Kroah-Hartman <greg@kroah.com>
  17. * Dely Sy <dely.l.sy@intel.com>"
  18. */
  19. #include <linux/moduleparam.h>
  20. #include <linux/kernel.h>
  21. #include <linux/slab.h>
  22. #include <linux/types.h>
  23. #include <linux/pci.h>
  24. #include "pciehp.h"
  25. #include <linux/interrupt.h>
  26. #include <linux/time.h>
  27. /* Global variables */
  28. bool pciehp_debug;
  29. bool pciehp_poll_mode;
  30. int pciehp_poll_time;
  31. static bool pciehp_force;
  32. /*
  33. * not really modular, but the easiest way to keep compat with existing
  34. * bootargs behaviour is to continue using module_param here.
  35. */
  36. module_param(pciehp_debug, bool, 0644);
  37. module_param(pciehp_poll_mode, bool, 0644);
  38. module_param(pciehp_poll_time, int, 0644);
  39. module_param(pciehp_force, bool, 0644);
  40. MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
  41. MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
  42. MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
  43. MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if OSHP is missing");
  44. #define PCIE_MODULE_NAME "pciehp"
  45. static int set_attention_status(struct hotplug_slot *slot, u8 value);
  46. static int enable_slot(struct hotplug_slot *slot);
  47. static int disable_slot(struct hotplug_slot *slot);
  48. static int get_power_status(struct hotplug_slot *slot, u8 *value);
  49. static int get_attention_status(struct hotplug_slot *slot, u8 *value);
  50. static int get_latch_status(struct hotplug_slot *slot, u8 *value);
  51. static int get_adapter_status(struct hotplug_slot *slot, u8 *value);
  52. static int reset_slot(struct hotplug_slot *slot, int probe);
  53. /**
  54. * release_slot - free up the memory used by a slot
  55. * @hotplug_slot: slot to free
  56. */
  57. static void release_slot(struct hotplug_slot *hotplug_slot)
  58. {
  59. kfree(hotplug_slot->ops);
  60. kfree(hotplug_slot->info);
  61. kfree(hotplug_slot);
  62. }
  63. static int init_slot(struct controller *ctrl)
  64. {
  65. struct slot *slot = ctrl->slot;
  66. struct hotplug_slot *hotplug = NULL;
  67. struct hotplug_slot_info *info = NULL;
  68. struct hotplug_slot_ops *ops = NULL;
  69. char name[SLOT_NAME_SIZE];
  70. int retval = -ENOMEM;
  71. hotplug = kzalloc(sizeof(*hotplug), GFP_KERNEL);
  72. if (!hotplug)
  73. goto out;
  74. info = kzalloc(sizeof(*info), GFP_KERNEL);
  75. if (!info)
  76. goto out;
  77. /* Setup hotplug slot ops */
  78. ops = kzalloc(sizeof(*ops), GFP_KERNEL);
  79. if (!ops)
  80. goto out;
  81. ops->enable_slot = enable_slot;
  82. ops->disable_slot = disable_slot;
  83. ops->get_power_status = get_power_status;
  84. ops->get_adapter_status = get_adapter_status;
  85. ops->reset_slot = reset_slot;
  86. if (MRL_SENS(ctrl))
  87. ops->get_latch_status = get_latch_status;
  88. if (ATTN_LED(ctrl)) {
  89. ops->get_attention_status = get_attention_status;
  90. ops->set_attention_status = set_attention_status;
  91. } else if (ctrl->pcie->port->hotplug_user_indicators) {
  92. ops->get_attention_status = pciehp_get_raw_indicator_status;
  93. ops->set_attention_status = pciehp_set_raw_indicator_status;
  94. }
  95. /* register this slot with the hotplug pci core */
  96. hotplug->info = info;
  97. hotplug->private = slot;
  98. hotplug->release = &release_slot;
  99. hotplug->ops = ops;
  100. slot->hotplug_slot = hotplug;
  101. snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl));
  102. retval = pci_hp_register(hotplug,
  103. ctrl->pcie->port->subordinate, 0, name);
  104. if (retval)
  105. ctrl_err(ctrl, "pci_hp_register failed: error %d\n", retval);
  106. out:
  107. if (retval) {
  108. kfree(ops);
  109. kfree(info);
  110. kfree(hotplug);
  111. }
  112. return retval;
  113. }
  114. static void cleanup_slot(struct controller *ctrl)
  115. {
  116. pci_hp_deregister(ctrl->slot->hotplug_slot);
  117. }
  118. /*
  119. * set_attention_status - Turns the Amber LED for a slot on, off or blink
  120. */
  121. static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
  122. {
  123. struct slot *slot = hotplug_slot->private;
  124. pciehp_set_attention_status(slot, status);
  125. return 0;
  126. }
  127. static int enable_slot(struct hotplug_slot *hotplug_slot)
  128. {
  129. struct slot *slot = hotplug_slot->private;
  130. return pciehp_sysfs_enable_slot(slot);
  131. }
  132. static int disable_slot(struct hotplug_slot *hotplug_slot)
  133. {
  134. struct slot *slot = hotplug_slot->private;
  135. return pciehp_sysfs_disable_slot(slot);
  136. }
  137. static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
  138. {
  139. struct slot *slot = hotplug_slot->private;
  140. pciehp_get_power_status(slot, value);
  141. return 0;
  142. }
  143. static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
  144. {
  145. struct slot *slot = hotplug_slot->private;
  146. pciehp_get_attention_status(slot, value);
  147. return 0;
  148. }
  149. static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
  150. {
  151. struct slot *slot = hotplug_slot->private;
  152. pciehp_get_latch_status(slot, value);
  153. return 0;
  154. }
  155. static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
  156. {
  157. struct slot *slot = hotplug_slot->private;
  158. pciehp_get_adapter_status(slot, value);
  159. return 0;
  160. }
  161. static int reset_slot(struct hotplug_slot *hotplug_slot, int probe)
  162. {
  163. struct slot *slot = hotplug_slot->private;
  164. return pciehp_reset_slot(slot, probe);
  165. }
  166. static int pciehp_probe(struct pcie_device *dev)
  167. {
  168. int rc;
  169. struct controller *ctrl;
  170. struct slot *slot;
  171. u8 occupied, poweron;
  172. /* If this is not a "hotplug" service, we have no business here. */
  173. if (dev->service != PCIE_PORT_SERVICE_HP)
  174. return -ENODEV;
  175. if (!dev->port->subordinate) {
  176. /* Can happen if we run out of bus numbers during probe */
  177. dev_err(&dev->device,
  178. "Hotplug bridge without secondary bus, ignoring\n");
  179. return -ENODEV;
  180. }
  181. ctrl = pcie_init(dev);
  182. if (!ctrl) {
  183. dev_err(&dev->device, "Controller initialization failed\n");
  184. return -ENODEV;
  185. }
  186. set_service_data(dev, ctrl);
  187. /* Setup the slot information structures */
  188. rc = init_slot(ctrl);
  189. if (rc) {
  190. if (rc == -EBUSY)
  191. ctrl_warn(ctrl, "Slot already registered by another hotplug driver\n");
  192. else
  193. ctrl_err(ctrl, "Slot initialization failed (%d)\n", rc);
  194. goto err_out_release_ctlr;
  195. }
  196. /* Enable events after we have setup the data structures */
  197. rc = pcie_init_notification(ctrl);
  198. if (rc) {
  199. ctrl_err(ctrl, "Notification initialization failed (%d)\n", rc);
  200. goto err_out_free_ctrl_slot;
  201. }
  202. /* Check if slot is occupied */
  203. slot = ctrl->slot;
  204. pciehp_get_adapter_status(slot, &occupied);
  205. pciehp_get_power_status(slot, &poweron);
  206. if (occupied && pciehp_force) {
  207. mutex_lock(&slot->hotplug_lock);
  208. pciehp_enable_slot(slot);
  209. mutex_unlock(&slot->hotplug_lock);
  210. }
  211. /* If empty slot's power status is on, turn power off */
  212. if (!occupied && poweron && POWER_CTRL(ctrl))
  213. pciehp_power_off_slot(slot);
  214. return 0;
  215. err_out_free_ctrl_slot:
  216. cleanup_slot(ctrl);
  217. err_out_release_ctlr:
  218. pciehp_release_ctrl(ctrl);
  219. return -ENODEV;
  220. }
  221. static void pciehp_remove(struct pcie_device *dev)
  222. {
  223. struct controller *ctrl = get_service_data(dev);
  224. cleanup_slot(ctrl);
  225. pciehp_release_ctrl(ctrl);
  226. }
  227. #ifdef CONFIG_PM
  228. static int pciehp_suspend(struct pcie_device *dev)
  229. {
  230. return 0;
  231. }
  232. static int pciehp_resume(struct pcie_device *dev)
  233. {
  234. struct controller *ctrl;
  235. struct slot *slot;
  236. u8 status;
  237. ctrl = get_service_data(dev);
  238. /* reinitialize the chipset's event detection logic */
  239. pcie_enable_notification(ctrl);
  240. slot = ctrl->slot;
  241. /* Check if slot is occupied */
  242. pciehp_get_adapter_status(slot, &status);
  243. mutex_lock(&slot->hotplug_lock);
  244. if (status)
  245. pciehp_enable_slot(slot);
  246. else
  247. pciehp_disable_slot(slot);
  248. mutex_unlock(&slot->hotplug_lock);
  249. return 0;
  250. }
  251. #endif /* PM */
  252. static struct pcie_port_service_driver hpdriver_portdrv = {
  253. .name = PCIE_MODULE_NAME,
  254. .port_type = PCIE_ANY_PORT,
  255. .service = PCIE_PORT_SERVICE_HP,
  256. .probe = pciehp_probe,
  257. .remove = pciehp_remove,
  258. #ifdef CONFIG_PM
  259. .suspend = pciehp_suspend,
  260. .resume = pciehp_resume,
  261. #endif /* PM */
  262. };
  263. static int __init pcied_init(void)
  264. {
  265. int retval = 0;
  266. retval = pcie_port_service_register(&hpdriver_portdrv);
  267. dbg("pcie_port_service_register = %d\n", retval);
  268. if (retval)
  269. dbg("Failure to register service\n");
  270. return retval;
  271. }
  272. device_initcall(pcied_init);