pciehp_ctrl.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*
  2. * PCI Express Hot Plug Controller Driver
  3. *
  4. * Copyright (C) 1995,2001 Compaq Computer Corporation
  5. * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
  6. * Copyright (C) 2001 IBM Corp.
  7. * Copyright (C) 2003-2004 Intel Corporation
  8. *
  9. * All rights reserved.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or (at
  14. * your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful, but
  17. * WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  19. * NON INFRINGEMENT. See the GNU General Public License for more
  20. * details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. *
  26. * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  27. *
  28. */
  29. #include <linux/module.h>
  30. #include <linux/kernel.h>
  31. #include <linux/types.h>
  32. #include <linux/smp_lock.h>
  33. #include <linux/pci.h>
  34. #include <linux/workqueue.h>
  35. #include "../pci.h"
  36. #include "pciehp.h"
  37. static void interrupt_event_handler(struct work_struct *work);
  38. static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
  39. {
  40. struct event_info *info;
  41. info = kmalloc(sizeof(*info), GFP_ATOMIC);
  42. if (!info)
  43. return -ENOMEM;
  44. info->event_type = event_type;
  45. info->p_slot = p_slot;
  46. INIT_WORK(&info->work, interrupt_event_handler);
  47. schedule_work(&info->work);
  48. return 0;
  49. }
  50. u8 pciehp_handle_attention_button(struct slot *p_slot)
  51. {
  52. u32 event_type;
  53. /* Attention Button Change */
  54. dbg("pciehp: Attention button interrupt received.\n");
  55. /*
  56. * Button pressed - See if need to TAKE ACTION!!!
  57. */
  58. info("Button pressed on Slot(%s)\n", p_slot->name);
  59. event_type = INT_BUTTON_PRESS;
  60. queue_interrupt_event(p_slot, event_type);
  61. return 0;
  62. }
  63. u8 pciehp_handle_switch_change(struct slot *p_slot)
  64. {
  65. u8 getstatus;
  66. u32 event_type;
  67. /* Switch Change */
  68. dbg("pciehp: Switch interrupt received.\n");
  69. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  70. if (getstatus) {
  71. /*
  72. * Switch opened
  73. */
  74. info("Latch open on Slot(%s)\n", p_slot->name);
  75. event_type = INT_SWITCH_OPEN;
  76. } else {
  77. /*
  78. * Switch closed
  79. */
  80. info("Latch close on Slot(%s)\n", p_slot->name);
  81. event_type = INT_SWITCH_CLOSE;
  82. }
  83. queue_interrupt_event(p_slot, event_type);
  84. return 1;
  85. }
  86. u8 pciehp_handle_presence_change(struct slot *p_slot)
  87. {
  88. u32 event_type;
  89. u8 presence_save;
  90. /* Presence Change */
  91. dbg("pciehp: Presence/Notify input change.\n");
  92. /* Switch is open, assume a presence change
  93. * Save the presence state
  94. */
  95. p_slot->hpc_ops->get_adapter_status(p_slot, &presence_save);
  96. if (presence_save) {
  97. /*
  98. * Card Present
  99. */
  100. info("Card present on Slot(%s)\n", p_slot->name);
  101. event_type = INT_PRESENCE_ON;
  102. } else {
  103. /*
  104. * Not Present
  105. */
  106. info("Card not present on Slot(%s)\n", p_slot->name);
  107. event_type = INT_PRESENCE_OFF;
  108. }
  109. queue_interrupt_event(p_slot, event_type);
  110. return 1;
  111. }
  112. u8 pciehp_handle_power_fault(struct slot *p_slot)
  113. {
  114. u32 event_type;
  115. /* power fault */
  116. dbg("pciehp: Power fault interrupt received.\n");
  117. if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
  118. /*
  119. * power fault Cleared
  120. */
  121. info("Power fault cleared on Slot(%s)\n", p_slot->name);
  122. event_type = INT_POWER_FAULT_CLEAR;
  123. } else {
  124. /*
  125. * power fault
  126. */
  127. info("Power fault on Slot(%s)\n", p_slot->name);
  128. event_type = INT_POWER_FAULT;
  129. info("power fault bit %x set\n", 0);
  130. }
  131. queue_interrupt_event(p_slot, event_type);
  132. return 1;
  133. }
  134. /* The following routines constitute the bulk of the
  135. hotplug controller logic
  136. */
  137. static void set_slot_off(struct controller *ctrl, struct slot * pslot)
  138. {
  139. /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
  140. if (POWER_CTRL(ctrl)) {
  141. if (pslot->hpc_ops->power_off_slot(pslot)) {
  142. err("%s: Issue of Slot Power Off command failed\n",
  143. __func__);
  144. return;
  145. }
  146. }
  147. /*
  148. * After turning power off, we must wait for at least 1 second
  149. * before taking any action that relies on power having been
  150. * removed from the slot/adapter.
  151. */
  152. msleep(1000);
  153. if (PWR_LED(ctrl))
  154. pslot->hpc_ops->green_led_off(pslot);
  155. if (ATTN_LED(ctrl)) {
  156. if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
  157. err("%s: Issue of Set Attention Led command failed\n",
  158. __func__);
  159. return;
  160. }
  161. }
  162. }
  163. /**
  164. * board_added - Called after a board has been added to the system.
  165. * @p_slot: &slot where board is added
  166. *
  167. * Turns power on for the board.
  168. * Configures board.
  169. */
  170. static int board_added(struct slot *p_slot)
  171. {
  172. int retval = 0;
  173. struct controller *ctrl = p_slot->ctrl;
  174. dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
  175. __func__, p_slot->device,
  176. ctrl->slot_device_offset, p_slot->hp_slot);
  177. if (POWER_CTRL(ctrl)) {
  178. /* Power on slot */
  179. retval = p_slot->hpc_ops->power_on_slot(p_slot);
  180. if (retval)
  181. return retval;
  182. }
  183. if (PWR_LED(ctrl))
  184. p_slot->hpc_ops->green_led_blink(p_slot);
  185. /* Wait for ~1 second */
  186. msleep(1000);
  187. /* Check link training status */
  188. retval = p_slot->hpc_ops->check_lnk_status(ctrl);
  189. if (retval) {
  190. err("%s: Failed to check link status\n", __func__);
  191. set_slot_off(ctrl, p_slot);
  192. return retval;
  193. }
  194. /* Check for a power fault */
  195. if (p_slot->hpc_ops->query_power_fault(p_slot)) {
  196. dbg("%s: power fault detected\n", __func__);
  197. retval = POWER_FAILURE;
  198. goto err_exit;
  199. }
  200. retval = pciehp_configure_device(p_slot);
  201. if (retval) {
  202. err("Cannot add device 0x%x:%x\n", p_slot->bus,
  203. p_slot->device);
  204. goto err_exit;
  205. }
  206. /*
  207. * Some PCI Express root ports require fixup after hot-plug operation.
  208. */
  209. if (pcie_mch_quirk)
  210. pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
  211. if (PWR_LED(ctrl))
  212. p_slot->hpc_ops->green_led_on(p_slot);
  213. return 0;
  214. err_exit:
  215. set_slot_off(ctrl, p_slot);
  216. return retval;
  217. }
  218. /**
  219. * remove_board - Turns off slot and LEDs
  220. * @p_slot: slot where board is being removed
  221. */
  222. static int remove_board(struct slot *p_slot)
  223. {
  224. int retval = 0;
  225. struct controller *ctrl = p_slot->ctrl;
  226. retval = pciehp_unconfigure_device(p_slot);
  227. if (retval)
  228. return retval;
  229. dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
  230. if (POWER_CTRL(ctrl)) {
  231. /* power off slot */
  232. retval = p_slot->hpc_ops->power_off_slot(p_slot);
  233. if (retval) {
  234. err("%s: Issue of Slot Disable command failed\n",
  235. __func__);
  236. return retval;
  237. }
  238. }
  239. /*
  240. * After turning power off, we must wait for at least 1 second
  241. * before taking any action that relies on power having been
  242. * removed from the slot/adapter.
  243. */
  244. msleep(1000);
  245. if (PWR_LED(ctrl))
  246. /* turn off Green LED */
  247. p_slot->hpc_ops->green_led_off(p_slot);
  248. return 0;
  249. }
  250. struct power_work_info {
  251. struct slot *p_slot;
  252. struct work_struct work;
  253. };
  254. /**
  255. * pciehp_power_thread - handle pushbutton events
  256. * @work: &struct work_struct describing work to be done
  257. *
  258. * Scheduled procedure to handle blocking stuff for the pushbuttons.
  259. * Handles all pending events and exits.
  260. */
  261. static void pciehp_power_thread(struct work_struct *work)
  262. {
  263. struct power_work_info *info =
  264. container_of(work, struct power_work_info, work);
  265. struct slot *p_slot = info->p_slot;
  266. mutex_lock(&p_slot->lock);
  267. switch (p_slot->state) {
  268. case POWEROFF_STATE:
  269. mutex_unlock(&p_slot->lock);
  270. dbg("%s: disabling bus:device(%x:%x)\n",
  271. __func__, p_slot->bus, p_slot->device);
  272. pciehp_disable_slot(p_slot);
  273. mutex_lock(&p_slot->lock);
  274. p_slot->state = STATIC_STATE;
  275. break;
  276. case POWERON_STATE:
  277. mutex_unlock(&p_slot->lock);
  278. if (pciehp_enable_slot(p_slot) &&
  279. PWR_LED(p_slot->ctrl))
  280. p_slot->hpc_ops->green_led_off(p_slot);
  281. mutex_lock(&p_slot->lock);
  282. p_slot->state = STATIC_STATE;
  283. break;
  284. default:
  285. break;
  286. }
  287. mutex_unlock(&p_slot->lock);
  288. kfree(info);
  289. }
  290. void pciehp_queue_pushbutton_work(struct work_struct *work)
  291. {
  292. struct slot *p_slot = container_of(work, struct slot, work.work);
  293. struct power_work_info *info;
  294. info = kmalloc(sizeof(*info), GFP_KERNEL);
  295. if (!info) {
  296. err("%s: Cannot allocate memory\n", __func__);
  297. return;
  298. }
  299. info->p_slot = p_slot;
  300. INIT_WORK(&info->work, pciehp_power_thread);
  301. mutex_lock(&p_slot->lock);
  302. switch (p_slot->state) {
  303. case BLINKINGOFF_STATE:
  304. p_slot->state = POWEROFF_STATE;
  305. break;
  306. case BLINKINGON_STATE:
  307. p_slot->state = POWERON_STATE;
  308. break;
  309. default:
  310. goto out;
  311. }
  312. queue_work(pciehp_wq, &info->work);
  313. out:
  314. mutex_unlock(&p_slot->lock);
  315. }
  316. static int update_slot_info(struct slot *slot)
  317. {
  318. struct hotplug_slot_info *info;
  319. int result;
  320. info = kmalloc(sizeof(*info), GFP_KERNEL);
  321. if (!info)
  322. return -ENOMEM;
  323. slot->hpc_ops->get_power_status(slot, &(info->power_status));
  324. slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
  325. slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
  326. slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
  327. result = pci_hp_change_slot_info(slot->hotplug_slot, info);
  328. kfree (info);
  329. return result;
  330. }
  331. /*
  332. * Note: This function must be called with slot->lock held
  333. */
  334. static void handle_button_press_event(struct slot *p_slot)
  335. {
  336. struct controller *ctrl = p_slot->ctrl;
  337. u8 getstatus;
  338. switch (p_slot->state) {
  339. case STATIC_STATE:
  340. p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  341. if (getstatus) {
  342. p_slot->state = BLINKINGOFF_STATE;
  343. info("PCI slot #%s - powering off due to button "
  344. "press.\n", p_slot->name);
  345. } else {
  346. p_slot->state = BLINKINGON_STATE;
  347. info("PCI slot #%s - powering on due to button "
  348. "press.\n", p_slot->name);
  349. }
  350. /* blink green LED and turn off amber */
  351. if (PWR_LED(ctrl))
  352. p_slot->hpc_ops->green_led_blink(p_slot);
  353. if (ATTN_LED(ctrl))
  354. p_slot->hpc_ops->set_attention_status(p_slot, 0);
  355. schedule_delayed_work(&p_slot->work, 5*HZ);
  356. break;
  357. case BLINKINGOFF_STATE:
  358. case BLINKINGON_STATE:
  359. /*
  360. * Cancel if we are still blinking; this means that we
  361. * press the attention again before the 5 sec. limit
  362. * expires to cancel hot-add or hot-remove
  363. */
  364. info("Button cancel on Slot(%s)\n", p_slot->name);
  365. dbg("%s: button cancel\n", __func__);
  366. cancel_delayed_work(&p_slot->work);
  367. if (p_slot->state == BLINKINGOFF_STATE) {
  368. if (PWR_LED(ctrl))
  369. p_slot->hpc_ops->green_led_on(p_slot);
  370. } else {
  371. if (PWR_LED(ctrl))
  372. p_slot->hpc_ops->green_led_off(p_slot);
  373. }
  374. if (ATTN_LED(ctrl))
  375. p_slot->hpc_ops->set_attention_status(p_slot, 0);
  376. info("PCI slot #%s - action canceled due to button press\n",
  377. p_slot->name);
  378. p_slot->state = STATIC_STATE;
  379. break;
  380. case POWEROFF_STATE:
  381. case POWERON_STATE:
  382. /*
  383. * Ignore if the slot is on power-on or power-off state;
  384. * this means that the previous attention button action
  385. * to hot-add or hot-remove is undergoing
  386. */
  387. info("Button ignore on Slot(%s)\n", p_slot->name);
  388. update_slot_info(p_slot);
  389. break;
  390. default:
  391. warn("Not a valid state\n");
  392. break;
  393. }
  394. }
  395. /*
  396. * Note: This function must be called with slot->lock held
  397. */
  398. static void handle_surprise_event(struct slot *p_slot)
  399. {
  400. u8 getstatus;
  401. struct power_work_info *info;
  402. info = kmalloc(sizeof(*info), GFP_KERNEL);
  403. if (!info) {
  404. err("%s: Cannot allocate memory\n", __func__);
  405. return;
  406. }
  407. info->p_slot = p_slot;
  408. INIT_WORK(&info->work, pciehp_power_thread);
  409. p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
  410. if (!getstatus)
  411. p_slot->state = POWEROFF_STATE;
  412. else
  413. p_slot->state = POWERON_STATE;
  414. queue_work(pciehp_wq, &info->work);
  415. }
  416. static void interrupt_event_handler(struct work_struct *work)
  417. {
  418. struct event_info *info = container_of(work, struct event_info, work);
  419. struct slot *p_slot = info->p_slot;
  420. struct controller *ctrl = p_slot->ctrl;
  421. mutex_lock(&p_slot->lock);
  422. switch (info->event_type) {
  423. case INT_BUTTON_PRESS:
  424. handle_button_press_event(p_slot);
  425. break;
  426. case INT_POWER_FAULT:
  427. if (!POWER_CTRL(ctrl))
  428. break;
  429. if (ATTN_LED(ctrl))
  430. p_slot->hpc_ops->set_attention_status(p_slot, 1);
  431. if (PWR_LED(ctrl))
  432. p_slot->hpc_ops->green_led_off(p_slot);
  433. break;
  434. case INT_PRESENCE_ON:
  435. case INT_PRESENCE_OFF:
  436. if (!HP_SUPR_RM(ctrl))
  437. break;
  438. dbg("Surprise Removal\n");
  439. update_slot_info(p_slot);
  440. handle_surprise_event(p_slot);
  441. break;
  442. default:
  443. update_slot_info(p_slot);
  444. break;
  445. }
  446. mutex_unlock(&p_slot->lock);
  447. kfree(info);
  448. }
  449. int pciehp_enable_slot(struct slot *p_slot)
  450. {
  451. u8 getstatus = 0;
  452. int rc;
  453. /* Check to see if (latch closed, card present, power off) */
  454. mutex_lock(&p_slot->ctrl->crit_sect);
  455. rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
  456. if (rc || !getstatus) {
  457. info("%s: no adapter on slot(%s)\n", __func__,
  458. p_slot->name);
  459. mutex_unlock(&p_slot->ctrl->crit_sect);
  460. return -ENODEV;
  461. }
  462. if (MRL_SENS(p_slot->ctrl)) {
  463. rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  464. if (rc || getstatus) {
  465. info("%s: latch open on slot(%s)\n", __func__,
  466. p_slot->name);
  467. mutex_unlock(&p_slot->ctrl->crit_sect);
  468. return -ENODEV;
  469. }
  470. }
  471. if (POWER_CTRL(p_slot->ctrl)) {
  472. rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  473. if (rc || getstatus) {
  474. info("%s: already enabled on slot(%s)\n", __func__,
  475. p_slot->name);
  476. mutex_unlock(&p_slot->ctrl->crit_sect);
  477. return -EINVAL;
  478. }
  479. }
  480. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  481. rc = board_added(p_slot);
  482. if (rc) {
  483. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  484. }
  485. update_slot_info(p_slot);
  486. mutex_unlock(&p_slot->ctrl->crit_sect);
  487. return rc;
  488. }
  489. int pciehp_disable_slot(struct slot *p_slot)
  490. {
  491. u8 getstatus = 0;
  492. int ret = 0;
  493. if (!p_slot->ctrl)
  494. return 1;
  495. /* Check to see if (latch closed, card present, power on) */
  496. mutex_lock(&p_slot->ctrl->crit_sect);
  497. if (!HP_SUPR_RM(p_slot->ctrl)) {
  498. ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
  499. if (ret || !getstatus) {
  500. info("%s: no adapter on slot(%s)\n", __func__,
  501. p_slot->name);
  502. mutex_unlock(&p_slot->ctrl->crit_sect);
  503. return -ENODEV;
  504. }
  505. }
  506. if (MRL_SENS(p_slot->ctrl)) {
  507. ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  508. if (ret || getstatus) {
  509. info("%s: latch open on slot(%s)\n", __func__,
  510. p_slot->name);
  511. mutex_unlock(&p_slot->ctrl->crit_sect);
  512. return -ENODEV;
  513. }
  514. }
  515. if (POWER_CTRL(p_slot->ctrl)) {
  516. ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  517. if (ret || !getstatus) {
  518. info("%s: already disabled slot(%s)\n", __func__,
  519. p_slot->name);
  520. mutex_unlock(&p_slot->ctrl->crit_sect);
  521. return -EINVAL;
  522. }
  523. }
  524. ret = remove_board(p_slot);
  525. update_slot_info(p_slot);
  526. mutex_unlock(&p_slot->ctrl->crit_sect);
  527. return ret;
  528. }
  529. int pciehp_sysfs_enable_slot(struct slot *p_slot)
  530. {
  531. int retval = -ENODEV;
  532. mutex_lock(&p_slot->lock);
  533. switch (p_slot->state) {
  534. case BLINKINGON_STATE:
  535. cancel_delayed_work(&p_slot->work);
  536. case STATIC_STATE:
  537. p_slot->state = POWERON_STATE;
  538. mutex_unlock(&p_slot->lock);
  539. retval = pciehp_enable_slot(p_slot);
  540. mutex_lock(&p_slot->lock);
  541. p_slot->state = STATIC_STATE;
  542. break;
  543. case POWERON_STATE:
  544. info("Slot %s is already in powering on state\n",
  545. p_slot->name);
  546. break;
  547. case BLINKINGOFF_STATE:
  548. case POWEROFF_STATE:
  549. info("Already enabled on slot %s\n", p_slot->name);
  550. break;
  551. default:
  552. err("Not a valid state on slot %s\n", p_slot->name);
  553. break;
  554. }
  555. mutex_unlock(&p_slot->lock);
  556. return retval;
  557. }
  558. int pciehp_sysfs_disable_slot(struct slot *p_slot)
  559. {
  560. int retval = -ENODEV;
  561. mutex_lock(&p_slot->lock);
  562. switch (p_slot->state) {
  563. case BLINKINGOFF_STATE:
  564. cancel_delayed_work(&p_slot->work);
  565. case STATIC_STATE:
  566. p_slot->state = POWEROFF_STATE;
  567. mutex_unlock(&p_slot->lock);
  568. retval = pciehp_disable_slot(p_slot);
  569. mutex_lock(&p_slot->lock);
  570. p_slot->state = STATIC_STATE;
  571. break;
  572. case POWEROFF_STATE:
  573. info("Slot %s is already in powering off state\n",
  574. p_slot->name);
  575. break;
  576. case BLINKINGON_STATE:
  577. case POWERON_STATE:
  578. info("Already disabled on slot %s\n", p_slot->name);
  579. break;
  580. default:
  581. err("Not a valid state on slot %s\n", p_slot->name);
  582. break;
  583. }
  584. mutex_unlock(&p_slot->lock);
  585. return retval;
  586. }