pciehp_ctrl.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  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. static inline char *slot_name(struct slot *p_slot)
  43. {
  44. return p_slot->hotplug_slot->name;
  45. }
  46. u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
  47. {
  48. struct slot *p_slot;
  49. u8 rc = 0;
  50. u8 getstatus;
  51. struct event_info *taskInfo;
  52. /* Attention Button Change */
  53. dbg("pciehp: Attention button interrupt received.\n");
  54. /* This is the structure that tells the worker thread what to do */
  55. taskInfo = &(ctrl->event_queue[ctrl->next_event]);
  56. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  57. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  58. ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
  59. taskInfo->hp_slot = hp_slot;
  60. rc++;
  61. /*
  62. * Button pressed - See if need to TAKE ACTION!!!
  63. */
  64. info("Button pressed on Slot(%s)\n", slot_name(p_slot));
  65. taskInfo->event_type = INT_BUTTON_PRESS;
  66. if ((p_slot->state == BLINKINGON_STATE)
  67. || (p_slot->state == BLINKINGOFF_STATE)) {
  68. /* Cancel if we are still blinking; this means that we press the
  69. * attention again before the 5 sec. limit expires to cancel hot-add
  70. * or hot-remove
  71. */
  72. taskInfo->event_type = INT_BUTTON_CANCEL;
  73. info("Button cancel on Slot(%s)\n", slot_name(p_slot));
  74. } else if ((p_slot->state == POWERON_STATE)
  75. || (p_slot->state == POWEROFF_STATE)) {
  76. /* Ignore if the slot is on power-on or power-off state; this
  77. * means that the previous attention button action to hot-add or
  78. * hot-remove is undergoing
  79. */
  80. taskInfo->event_type = INT_BUTTON_IGNORE;
  81. info("Button ignore on Slot(%s)\n", slot_name(p_slot));
  82. }
  83. if (rc)
  84. up(&event_semaphore); /* signal event thread that new event is posted */
  85. return 0;
  86. }
  87. u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
  88. {
  89. struct slot *p_slot;
  90. u8 rc = 0;
  91. u8 getstatus;
  92. struct event_info *taskInfo;
  93. /* Switch Change */
  94. dbg("pciehp: Switch interrupt received.\n");
  95. /* This is the structure that tells the worker thread
  96. * what to do
  97. */
  98. taskInfo = &(ctrl->event_queue[ctrl->next_event]);
  99. ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
  100. taskInfo->hp_slot = hp_slot;
  101. rc++;
  102. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  103. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  104. if (getstatus) {
  105. /*
  106. * Switch opened
  107. */
  108. info("Latch open on Slot(%s)\n", slot_name(p_slot));
  109. taskInfo->event_type = INT_SWITCH_OPEN;
  110. } else {
  111. /*
  112. * Switch closed
  113. */
  114. info("Latch close on Slot(%s)\n", slot_name(p_slot));
  115. taskInfo->event_type = INT_SWITCH_CLOSE;
  116. }
  117. if (rc)
  118. up(&event_semaphore); /* signal event thread that new event is posted */
  119. return rc;
  120. }
  121. u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
  122. {
  123. struct slot *p_slot;
  124. u8 presence_save, rc = 0;
  125. struct event_info *taskInfo;
  126. /* Presence Change */
  127. dbg("pciehp: Presence/Notify input change.\n");
  128. /* This is the structure that tells the worker thread
  129. * what to do
  130. */
  131. taskInfo = &(ctrl->event_queue[ctrl->next_event]);
  132. ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
  133. taskInfo->hp_slot = hp_slot;
  134. rc++;
  135. p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
  136. /* Switch is open, assume a presence change
  137. * Save the presence state
  138. */
  139. p_slot->hpc_ops->get_adapter_status(p_slot, &presence_save);
  140. if (presence_save) {
  141. /*
  142. * Card Present
  143. */
  144. info("Card present on Slot(%s)\n", slot_name(p_slot));
  145. taskInfo->event_type = INT_PRESENCE_ON;
  146. } else {
  147. /*
  148. * Not Present
  149. */
  150. info("Card not present on Slot(%s)\n", slot_name(p_slot));
  151. taskInfo->event_type = INT_PRESENCE_OFF;
  152. }
  153. if (rc)
  154. up(&event_semaphore); /* signal event thread that new event is posted */
  155. return rc;
  156. }
  157. u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
  158. {
  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(%s)\n", slot_name(p_slot));
  177. taskInfo->event_type = INT_POWER_FAULT_CLEAR;
  178. } else {
  179. /*
  180. * power fault
  181. */
  182. info("Power fault on Slot(%s)\n", slot_name(p_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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  214. return;
  215. }
  216. wait_for_ctrl_irq (ctrl);
  217. }
  218. /* Done with exclusive hardware access */
  219. mutex_unlock(&ctrl->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  516. break;
  517. case BLINKINGON_STATE:
  518. /* Wait for exclusive access to hardware */
  519. mutex_lock(&ctrl->ctrl_lock);
  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->ctrl_lock);
  532. break;
  533. default:
  534. warn("Not a valid state\n");
  535. return;
  536. }
  537. info(msg_button_cancel, slot_name(p_slot));
  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, slot_name(p_slot));
  550. } else {
  551. /* slot is off */
  552. dbg("slot is off\n");
  553. p_slot->state = BLINKINGON_STATE;
  554. info(msg_button_on, slot_name(p_slot));
  555. }
  556. /* Wait for exclusive access to hardware */
  557. mutex_lock(&ctrl->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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->ctrl_lock);
  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(%s)\n", __FUNCTION__,
  627. slot_name(p_slot));
  628. mutex_unlock(&p_slot->ctrl->crit_sect);
  629. return -ENODEV;
  630. }
  631. if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
  632. rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  633. if (rc || getstatus) {
  634. info("%s: latch open on slot(%s)\n", __FUNCTION__,
  635. slot_name(p_slot));
  636. mutex_unlock(&p_slot->ctrl->crit_sect);
  637. return -ENODEV;
  638. }
  639. }
  640. if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
  641. rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  642. if (rc || getstatus) {
  643. info("%s: already enabled on slot(%s)\n", __FUNCTION__,
  644. slot_name(p_slot));
  645. mutex_unlock(&p_slot->ctrl->crit_sect);
  646. return -EINVAL;
  647. }
  648. }
  649. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  650. rc = board_added(p_slot);
  651. if (rc) {
  652. p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  653. }
  654. update_slot_info(p_slot);
  655. mutex_unlock(&p_slot->ctrl->crit_sect);
  656. return rc;
  657. }
  658. int pciehp_disable_slot(struct slot *p_slot)
  659. {
  660. u8 getstatus = 0;
  661. int ret = 0;
  662. if (!p_slot->ctrl)
  663. return 1;
  664. /* Check to see if (latch closed, card present, power on) */
  665. mutex_lock(&p_slot->ctrl->crit_sect);
  666. if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
  667. ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
  668. if (ret || !getstatus) {
  669. info("%s: no adapter on slot(%s)\n", __FUNCTION__,
  670. slot_name(p_slot));
  671. mutex_unlock(&p_slot->ctrl->crit_sect);
  672. return -ENODEV;
  673. }
  674. }
  675. if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
  676. ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
  677. if (ret || getstatus) {
  678. info("%s: latch open on slot(%s)\n", __FUNCTION__,
  679. slot_name(p_slot));
  680. mutex_unlock(&p_slot->ctrl->crit_sect);
  681. return -ENODEV;
  682. }
  683. }
  684. if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
  685. ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
  686. if (ret || !getstatus) {
  687. info("%s: already disabled slot(%s)\n", __FUNCTION__,
  688. slot_name(p_slot));
  689. mutex_unlock(&p_slot->ctrl->crit_sect);
  690. return -EINVAL;
  691. }
  692. }
  693. ret = remove_board(p_slot);
  694. update_slot_info(p_slot);
  695. mutex_unlock(&p_slot->ctrl->crit_sect);
  696. return ret;
  697. }