pciehp_ctrl.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  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 "../pci.h"
  35. #include "pciehp.h"
  36. static void interrupt_event_handler(struct controller *ctrl);
  37. static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
  38. static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */
  39. static int event_finished;
  40. static unsigned long pushbutton_pending; /* = 0 */
  41. static unsigned long surprise_rm_pending; /* = 0 */
  42. u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
  43. {
  44. struct controller *ctrl = (struct controller *) inst_id;
  45. struct slot *p_slot;
  46. u8 rc = 0;
  47. u8 getstatus;
  48. struct event_info *taskInfo;
  49. /* Attention Button Change */
  50. dbg("pciehp: Attention button interrupt received.\n");
  51. /* This is the structure that tells the worker thread what to do */
  52. taskInfo = &(ctrl->event_queue[ctrl->next_event]);
  53. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  54. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  55. ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
  56. taskInfo->hp_slot = hp_slot;
  57. rc++;
  58. /*
  59. * Button pressed - See if need to TAKE ACTION!!!
  60. */
  61. info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
  62. taskInfo->event_type = INT_BUTTON_PRESS;
  63. if ((p_slot->state == BLINKINGON_STATE)
  64. || (p_slot->state == BLINKINGOFF_STATE)) {
  65. /* Cancel if we are still blinking; this means that we press the
  66. * attention again before the 5 sec. limit expires to cancel hot-add
  67. * or hot-remove
  68. */
  69. taskInfo->event_type = INT_BUTTON_CANCEL;
  70. info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot);
  71. } else if ((p_slot->state == POWERON_STATE)
  72. || (p_slot->state == POWEROFF_STATE)) {
  73. /* Ignore if the slot is on power-on or power-off state; this
  74. * means that the previous attention button action to hot-add or
  75. * hot-remove is undergoing
  76. */
  77. taskInfo->event_type = INT_BUTTON_IGNORE;
  78. info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot);
  79. }
  80. if (rc)
  81. up(&event_semaphore); /* signal event thread that new event is posted */
  82. return 0;
  83. }
  84. u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
  85. {
  86. struct controller *ctrl = (struct controller *) inst_id;
  87. struct slot *p_slot;
  88. u8 rc = 0;
  89. u8 getstatus;
  90. struct event_info *taskInfo;
  91. /* Switch Change */
  92. dbg("pciehp: Switch interrupt received.\n");
  93. /* This is the structure that tells the worker thread
  94. * what to do
  95. */
  96. taskInfo = &(ctrl->event_queue[ctrl->next_event]);
  97. ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
  98. taskInfo->hp_slot = hp_slot;
  99. rc++;
  100. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  101. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  102. if (getstatus) {
  103. /*
  104. * Switch opened
  105. */
  106. info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
  107. taskInfo->event_type = INT_SWITCH_OPEN;
  108. } else {
  109. /*
  110. * Switch closed
  111. */
  112. info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
  113. taskInfo->event_type = INT_SWITCH_CLOSE;
  114. }
  115. if (rc)
  116. up(&event_semaphore); /* signal event thread that new event is posted */
  117. return rc;
  118. }
  119. u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
  120. {
  121. struct controller *ctrl = (struct controller *) inst_id;
  122. struct slot *p_slot;
  123. u8 presence_save, rc = 0;
  124. struct event_info *taskInfo;
  125. /* Presence Change */
  126. dbg("pciehp: Presence/Notify input change.\n");
  127. /* This is the structure that tells the worker thread
  128. * what to do
  129. */
  130. taskInfo = &(ctrl->event_queue[ctrl->next_event]);
  131. ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
  132. taskInfo->hp_slot = hp_slot;
  133. rc++;
  134. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  135. /* Switch is open, assume a presence change
  136. * Save the presence state
  137. */
  138. p_slot->hpc_ops->get_adapter_status(p_slot, &presence_save);
  139. if (presence_save) {
  140. /*
  141. * Card Present
  142. */
  143. info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
  144. taskInfo->event_type = INT_PRESENCE_ON;
  145. } else {
  146. /*
  147. * Not Present
  148. */
  149. info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
  150. taskInfo->event_type = INT_PRESENCE_OFF;
  151. }
  152. if (rc)
  153. up(&event_semaphore); /* signal event thread that new event is posted */
  154. return rc;
  155. }
  156. u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
  157. {
  158. struct controller *ctrl = (struct controller *) inst_id;
  159. struct slot *p_slot;
  160. u8 rc = 0;
  161. struct event_info *taskInfo;
  162. /* power fault */
  163. dbg("pciehp: Power fault interrupt received.\n");
  164. /* this is the structure that tells the worker thread
  165. * what to do
  166. */
  167. taskInfo = &(ctrl->event_queue[ctrl->next_event]);
  168. ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
  169. taskInfo->hp_slot = hp_slot;
  170. rc++;
  171. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  172. if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
  173. /*
  174. * power fault Cleared
  175. */
  176. info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
  177. taskInfo->event_type = INT_POWER_FAULT_CLEAR;
  178. } else {
  179. /*
  180. * power fault
  181. */
  182. info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
  183. taskInfo->event_type = INT_POWER_FAULT;
  184. info("power fault bit %x set\n", hp_slot);
  185. }
  186. if (rc)
  187. up(&event_semaphore); /* signal event thread that new event is posted */
  188. return rc;
  189. }
  190. /* The following routines constitute the bulk of the
  191. hotplug controller logic
  192. */
  193. static void set_slot_off(struct controller *ctrl, struct slot * pslot)
  194. {
  195. /* Wait for exclusive access to hardware */
  196. mutex_lock(&ctrl->crit_sect);
  197. /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
  198. if (POWER_CTRL(ctrl->ctrlcap)) {
  199. if (pslot->hpc_ops->power_off_slot(pslot)) {
  200. err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
  201. mutex_unlock(&ctrl->crit_sect);
  202. return;
  203. }
  204. wait_for_ctrl_irq (ctrl);
  205. }
  206. if (PWR_LED(ctrl->ctrlcap)) {
  207. pslot->hpc_ops->green_led_off(pslot);
  208. wait_for_ctrl_irq (ctrl);
  209. }
  210. if (ATTN_LED(ctrl->ctrlcap)) {
  211. if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
  212. err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
  213. mutex_unlock(&ctrl->crit_sect);
  214. return;
  215. }
  216. wait_for_ctrl_irq (ctrl);
  217. }
  218. /* Done with exclusive hardware access */
  219. mutex_unlock(&ctrl->crit_sect);
  220. }
  221. /**
  222. * board_added - Called after a board has been added to the system.
  223. *
  224. * Turns power on for the board
  225. * Configures board
  226. *
  227. */
  228. static int board_added(struct slot *p_slot)
  229. {
  230. u8 hp_slot;
  231. int rc = 0;
  232. struct controller *ctrl = p_slot->ctrl;
  233. hp_slot = p_slot->device - ctrl->slot_device_offset;
  234. dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
  235. __FUNCTION__, p_slot->device,
  236. ctrl->slot_device_offset, hp_slot);
  237. /* Wait for exclusive access to hardware */
  238. mutex_lock(&ctrl->crit_sect);
  239. if (POWER_CTRL(ctrl->ctrlcap)) {
  240. /* Power on slot */
  241. rc = p_slot->hpc_ops->power_on_slot(p_slot);
  242. if (rc) {
  243. mutex_unlock(&ctrl->crit_sect);
  244. return -1;
  245. }
  246. /* Wait for the command to complete */
  247. wait_for_ctrl_irq (ctrl);
  248. }
  249. if (PWR_LED(ctrl->ctrlcap)) {
  250. p_slot->hpc_ops->green_led_blink(p_slot);
  251. /* Wait for the command to complete */
  252. wait_for_ctrl_irq (ctrl);
  253. }
  254. /* Done with exclusive hardware access */
  255. mutex_unlock(&ctrl->crit_sect);
  256. /* Wait for ~1 second */
  257. wait_for_ctrl_irq (ctrl);
  258. /* Check link training status */
  259. rc = p_slot->hpc_ops->check_lnk_status(ctrl);
  260. if (rc) {
  261. err("%s: Failed to check link status\n", __FUNCTION__);
  262. set_slot_off(ctrl, p_slot);
  263. return rc;
  264. }
  265. /* Check for a power fault */
  266. if (p_slot->hpc_ops->query_power_fault(p_slot)) {
  267. dbg("%s: power fault detected\n", __FUNCTION__);
  268. rc = POWER_FAILURE;
  269. goto err_exit;
  270. }
  271. rc = pciehp_configure_device(p_slot);
  272. if (rc) {
  273. err("Cannot add device 0x%x:%x\n", p_slot->bus,
  274. p_slot->device);
  275. goto err_exit;
  276. }
  277. /*
  278. * Some PCI Express root ports require fixup after hot-plug operation.
  279. */
  280. if (pcie_mch_quirk)
  281. pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
  282. if (PWR_LED(ctrl->ctrlcap)) {
  283. /* Wait for exclusive access to hardware */
  284. mutex_lock(&ctrl->crit_sect);
  285. p_slot->hpc_ops->green_led_on(p_slot);
  286. /* Wait for the command to complete */
  287. wait_for_ctrl_irq (ctrl);
  288. /* Done with exclusive hardware access */
  289. mutex_unlock(&ctrl->crit_sect);
  290. }
  291. return 0;
  292. err_exit:
  293. set_slot_off(ctrl, p_slot);
  294. return -1;
  295. }
  296. /**
  297. * remove_board - Turns off slot and LED's
  298. *
  299. */
  300. static int remove_board(struct slot *p_slot)
  301. {
  302. u8 device;
  303. u8 hp_slot;
  304. int rc;
  305. struct controller *ctrl = p_slot->ctrl;
  306. if (pciehp_unconfigure_device(p_slot))
  307. return 1;
  308. device = p_slot->device;
  309. hp_slot = p_slot->device - ctrl->slot_device_offset;
  310. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  311. dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
  312. /* Wait for exclusive access to hardware */
  313. mutex_lock(&ctrl->crit_sect);
  314. if (POWER_CTRL(ctrl->ctrlcap)) {
  315. /* power off slot */
  316. rc = p_slot->hpc_ops->power_off_slot(p_slot);
  317. if (rc) {
  318. err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
  319. mutex_unlock(&ctrl->crit_sect);
  320. return rc;
  321. }
  322. /* Wait for the command to complete */
  323. wait_for_ctrl_irq (ctrl);
  324. }
  325. if (PWR_LED(ctrl->ctrlcap)) {
  326. /* turn off Green LED */
  327. p_slot->hpc_ops->green_led_off(p_slot);
  328. /* Wait for the command to complete */
  329. wait_for_ctrl_irq (ctrl);
  330. }
  331. /* Done with exclusive hardware access */
  332. mutex_unlock(&ctrl->crit_sect);
  333. return 0;
  334. }
  335. static void pushbutton_helper_thread(unsigned long data)
  336. {
  337. pushbutton_pending = data;
  338. up(&event_semaphore);
  339. }
  340. /**
  341. * pciehp_pushbutton_thread
  342. *
  343. * Scheduled procedure to handle blocking stuff for the pushbuttons
  344. * Handles all pending events and exits.
  345. *
  346. */
  347. static void pciehp_pushbutton_thread(unsigned long slot)
  348. {
  349. struct slot *p_slot = (struct slot *) slot;
  350. u8 getstatus;
  351. pushbutton_pending = 0;
  352. if (!p_slot) {
  353. dbg("%s: Error! slot NULL\n", __FUNCTION__);
  354. return;
  355. }
  356. p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  357. if (getstatus) {
  358. p_slot->state = POWEROFF_STATE;
  359. dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__,
  360. p_slot->bus, p_slot->device);
  361. pciehp_disable_slot(p_slot);
  362. p_slot->state = STATIC_STATE;
  363. } else {
  364. p_slot->state = POWERON_STATE;
  365. dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
  366. p_slot->bus, p_slot->device);
  367. if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
  368. /* Wait for exclusive access to hardware */
  369. mutex_lock(&p_slot->ctrl->crit_sect);
  370. p_slot->hpc_ops->green_led_off(p_slot);
  371. /* Wait for the command to complete */
  372. wait_for_ctrl_irq (p_slot->ctrl);
  373. /* Done with exclusive hardware access */
  374. mutex_unlock(&p_slot->ctrl->crit_sect);
  375. }
  376. p_slot->state = STATIC_STATE;
  377. }
  378. return;
  379. }
  380. /**
  381. * pciehp_surprise_rm_thread
  382. *
  383. * Scheduled procedure to handle blocking stuff for the surprise removal
  384. * Handles all pending events and exits.
  385. *
  386. */
  387. static void pciehp_surprise_rm_thread(unsigned long slot)
  388. {
  389. struct slot *p_slot = (struct slot *) slot;
  390. u8 getstatus;
  391. surprise_rm_pending = 0;
  392. if (!p_slot) {
  393. dbg("%s: Error! slot NULL\n", __FUNCTION__);
  394. return;
  395. }
  396. p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
  397. if (!getstatus) {
  398. p_slot->state = POWEROFF_STATE;
  399. dbg("%s: removing bus:device(%x:%x)\n",
  400. __FUNCTION__, p_slot->bus, p_slot->device);
  401. pciehp_disable_slot(p_slot);
  402. p_slot->state = STATIC_STATE;
  403. } else {
  404. p_slot->state = POWERON_STATE;
  405. dbg("%s: adding bus:device(%x:%x)\n",
  406. __FUNCTION__, p_slot->bus, p_slot->device);
  407. if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
  408. /* Wait for exclusive access to hardware */
  409. mutex_lock(&p_slot->ctrl->crit_sect);
  410. p_slot->hpc_ops->green_led_off(p_slot);
  411. /* Wait for the command to complete */
  412. wait_for_ctrl_irq (p_slot->ctrl);
  413. /* Done with exclusive hardware access */
  414. mutex_unlock(&p_slot->ctrl->crit_sect);
  415. }
  416. p_slot->state = STATIC_STATE;
  417. }
  418. return;
  419. }
  420. /* this is the main worker thread */
  421. static int event_thread(void* data)
  422. {
  423. struct controller *ctrl;
  424. lock_kernel();
  425. daemonize("pciehpd_event");
  426. unlock_kernel();
  427. while (1) {
  428. dbg("!!!!event_thread sleeping\n");
  429. down_interruptible (&event_semaphore);
  430. dbg("event_thread woken finished = %d\n", event_finished);
  431. if (event_finished || signal_pending(current))
  432. break;
  433. /* Do stuff here */
  434. if (pushbutton_pending)
  435. pciehp_pushbutton_thread(pushbutton_pending);
  436. else if (surprise_rm_pending)
  437. pciehp_surprise_rm_thread(surprise_rm_pending);
  438. else
  439. for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
  440. interrupt_event_handler(ctrl);
  441. }
  442. dbg("event_thread signals exit\n");
  443. up(&event_exit);
  444. return 0;
  445. }
  446. int pciehp_event_start_thread(void)
  447. {
  448. int pid;
  449. /* initialize our semaphores */
  450. init_MUTEX_LOCKED(&event_exit);
  451. event_finished=0;
  452. init_MUTEX_LOCKED(&event_semaphore);
  453. pid = kernel_thread(event_thread, NULL, 0);
  454. if (pid < 0) {
  455. err ("Can't start up our event thread\n");
  456. return -1;
  457. }
  458. return 0;
  459. }
  460. void pciehp_event_stop_thread(void)
  461. {
  462. event_finished = 1;
  463. up(&event_semaphore);
  464. down(&event_exit);
  465. }
  466. static int update_slot_info(struct slot *slot)
  467. {
  468. struct hotplug_slot_info *info;
  469. /* char buffer[SLOT_NAME_SIZE]; */
  470. int result;
  471. info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
  472. if (!info)
  473. return -ENOMEM;
  474. /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */
  475. slot->hpc_ops->get_power_status(slot, &(info->power_status));
  476. slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
  477. slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
  478. slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
  479. /* result = pci_hp_change_slot_info(buffer, info); */
  480. result = pci_hp_change_slot_info(slot->hotplug_slot, info);
  481. kfree (info);
  482. return result;
  483. }
  484. static void interrupt_event_handler(struct controller *ctrl)
  485. {
  486. int loop = 0;
  487. int change = 1;
  488. u8 hp_slot;
  489. u8 getstatus;
  490. struct slot *p_slot;
  491. while (change) {
  492. change = 0;
  493. for (loop = 0; loop < MAX_EVENTS; loop++) {
  494. if (ctrl->event_queue[loop].event_type != 0) {
  495. hp_slot = ctrl->event_queue[loop].hp_slot;
  496. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  497. if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
  498. dbg("button cancel\n");
  499. del_timer(&p_slot->task_event);
  500. switch (p_slot->state) {
  501. case BLINKINGOFF_STATE:
  502. /* Wait for exclusive access to hardware */
  503. mutex_lock(&ctrl->crit_sect);
  504. if (PWR_LED(ctrl->ctrlcap)) {
  505. p_slot->hpc_ops->green_led_on(p_slot);
  506. /* Wait for the command to complete */
  507. wait_for_ctrl_irq (ctrl);
  508. }
  509. if (ATTN_LED(ctrl->ctrlcap)) {
  510. p_slot->hpc_ops->set_attention_status(p_slot, 0);
  511. /* Wait for the command to complete */
  512. wait_for_ctrl_irq (ctrl);
  513. }
  514. /* Done with exclusive hardware access */
  515. mutex_unlock(&ctrl->crit_sect);
  516. break;
  517. case BLINKINGON_STATE:
  518. /* Wait for exclusive access to hardware */
  519. mutex_lock(&ctrl->crit_sect);
  520. if (PWR_LED(ctrl->ctrlcap)) {
  521. p_slot->hpc_ops->green_led_off(p_slot);
  522. /* Wait for the command to complete */
  523. wait_for_ctrl_irq (ctrl);
  524. }
  525. if (ATTN_LED(ctrl->ctrlcap)){
  526. p_slot->hpc_ops->set_attention_status(p_slot, 0);
  527. /* Wait for the command to complete */
  528. wait_for_ctrl_irq (ctrl);
  529. }
  530. /* Done with exclusive hardware access */
  531. mutex_unlock(&ctrl->crit_sect);
  532. break;
  533. default:
  534. warn("Not a valid state\n");
  535. return;
  536. }
  537. info(msg_button_cancel, p_slot->number);
  538. p_slot->state = STATIC_STATE;
  539. }
  540. /* ***********Button Pressed (No action on 1st press...) */
  541. else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
  542. if (ATTN_BUTTN(ctrl->ctrlcap)) {
  543. dbg("Button pressed\n");
  544. p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  545. if (getstatus) {
  546. /* slot is on */
  547. dbg("slot is on\n");
  548. p_slot->state = BLINKINGOFF_STATE;
  549. info(msg_button_off, p_slot->number);
  550. } else {
  551. /* slot is off */
  552. dbg("slot is off\n");
  553. p_slot->state = BLINKINGON_STATE;
  554. info(msg_button_on, p_slot->number);
  555. }
  556. /* Wait for exclusive access to hardware */
  557. mutex_lock(&ctrl->crit_sect);
  558. /* blink green LED and turn off amber */
  559. if (PWR_LED(ctrl->ctrlcap)) {
  560. p_slot->hpc_ops->green_led_blink(p_slot);
  561. /* Wait for the command to complete */
  562. wait_for_ctrl_irq (ctrl);
  563. }
  564. if (ATTN_LED(ctrl->ctrlcap)) {
  565. p_slot->hpc_ops->set_attention_status(p_slot, 0);
  566. /* Wait for the command to complete */
  567. wait_for_ctrl_irq (ctrl);
  568. }
  569. /* Done with exclusive hardware access */
  570. mutex_unlock(&ctrl->crit_sect);
  571. init_timer(&p_slot->task_event);
  572. p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
  573. p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
  574. p_slot->task_event.data = (unsigned long) p_slot;
  575. add_timer(&p_slot->task_event);
  576. }
  577. }
  578. /***********POWER FAULT********************/
  579. else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
  580. if (POWER_CTRL(ctrl->ctrlcap)) {
  581. dbg("power fault\n");
  582. /* Wait for exclusive access to hardware */
  583. mutex_lock(&ctrl->crit_sect);
  584. if (ATTN_LED(ctrl->ctrlcap)) {
  585. p_slot->hpc_ops->set_attention_status(p_slot, 1);
  586. wait_for_ctrl_irq (ctrl);
  587. }
  588. if (PWR_LED(ctrl->ctrlcap)) {
  589. p_slot->hpc_ops->green_led_off(p_slot);
  590. wait_for_ctrl_irq (ctrl);
  591. }
  592. /* Done with exclusive hardware access */
  593. mutex_unlock(&ctrl->crit_sect);
  594. }
  595. }
  596. /***********SURPRISE REMOVAL********************/
  597. else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) ||
  598. (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) {
  599. if (HP_SUPR_RM(ctrl->ctrlcap)) {
  600. dbg("Surprise Removal\n");
  601. if (p_slot) {
  602. surprise_rm_pending = (unsigned long) p_slot;
  603. up(&event_semaphore);
  604. update_slot_info(p_slot);
  605. }
  606. }
  607. } else {
  608. /* refresh notification */
  609. if (p_slot)
  610. update_slot_info(p_slot);
  611. }
  612. ctrl->event_queue[loop].event_type = 0;
  613. change = 1;
  614. }
  615. } /* End of FOR loop */
  616. }
  617. }
  618. int pciehp_enable_slot(struct slot *p_slot)
  619. {
  620. u8 getstatus = 0;
  621. int rc;
  622. /* Check to see if (latch closed, card present, power off) */
  623. mutex_lock(&p_slot->ctrl->crit_sect);
  624. rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
  625. if (rc || !getstatus) {
  626. info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
  627. mutex_unlock(&p_slot->ctrl->crit_sect);
  628. return 1;
  629. }
  630. if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
  631. rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  632. if (rc || getstatus) {
  633. info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
  634. mutex_unlock(&p_slot->ctrl->crit_sect);
  635. return 1;
  636. }
  637. }
  638. if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
  639. rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  640. if (rc || getstatus) {
  641. info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
  642. mutex_unlock(&p_slot->ctrl->crit_sect);
  643. return 1;
  644. }
  645. }
  646. mutex_unlock(&p_slot->ctrl->crit_sect);
  647. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  648. rc = board_added(p_slot);
  649. if (rc) {
  650. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  651. }
  652. if (p_slot)
  653. update_slot_info(p_slot);
  654. return rc;
  655. }
  656. int pciehp_disable_slot(struct slot *p_slot)
  657. {
  658. u8 getstatus = 0;
  659. int ret = 0;
  660. if (!p_slot->ctrl)
  661. return 1;
  662. /* Check to see if (latch closed, card present, power on) */
  663. mutex_lock(&p_slot->ctrl->crit_sect);
  664. if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
  665. ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
  666. if (ret || !getstatus) {
  667. info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
  668. mutex_unlock(&p_slot->ctrl->crit_sect);
  669. return 1;
  670. }
  671. }
  672. if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
  673. ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  674. if (ret || getstatus) {
  675. info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
  676. mutex_unlock(&p_slot->ctrl->crit_sect);
  677. return 1;
  678. }
  679. }
  680. if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
  681. ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  682. if (ret || !getstatus) {
  683. info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
  684. mutex_unlock(&p_slot->ctrl->crit_sect);
  685. return 1;
  686. }
  687. }
  688. mutex_unlock(&p_slot->ctrl->crit_sect);
  689. ret = remove_board(p_slot);
  690. update_slot_info(p_slot);
  691. return ret;
  692. }