ibinit.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /***************************************************************************
  2. sys/ibinit.c
  3. -------------------
  4. copyright : (C) 2001, 2002 by Frank Mori Hess
  5. email : fmhess@users.sourceforge.net
  6. ***************************************************************************/
  7. /***************************************************************************
  8. * *
  9. * This program is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. * *
  14. ***************************************************************************/
  15. #include "ibsys.h"
  16. #include "autopoll.h"
  17. #include <linux/kthread.h>
  18. #include <linux/vmalloc.h>
  19. #include <linux/smp_lock.h>
  20. static int autospoll_thread(void *board_void)
  21. {
  22. gpib_board_t *board = board_void;
  23. int retval = 0;
  24. lock_kernel();
  25. /* This thread doesn't need any user-level access,
  26. * so get rid of all our resources..
  27. */
  28. allow_signal(SIGKILL);
  29. GPIB_DPRINTK("entering autospoll thread\n" );
  30. while(1)
  31. {
  32. if(wait_event_interruptible(board->wait,
  33. kthread_should_stop() ||
  34. (board->master && board->autospollers > 0 &&
  35. board->stuck_srq == 0 &&
  36. test_and_clear_bit(SRQI_NUM, &board->status))))
  37. {
  38. retval = -ERESTARTSYS;
  39. break;
  40. }
  41. GPIB_DPRINTK("autospoll wait satisfied\n" );
  42. if(kthread_should_stop()) break;
  43. /* make sure we are still good after we have
  44. * lock */
  45. if(board->autospollers <= 0 || board->master == 0)
  46. {
  47. continue;
  48. }
  49. if(try_module_get(board->provider_module))
  50. {
  51. retval = autopoll_all_devices(board);
  52. module_put(board->provider_module);
  53. }else
  54. printk("gpib%i: %s: try_module_get() failed!\n", board->minor, __FUNCTION__);
  55. if(retval <= 0)
  56. {
  57. printk("gpib%i: %s: struck SRQ\n", board->minor, __FUNCTION__);
  58. board->stuck_srq = 1; // XXX could be better
  59. set_bit(SRQI_NUM, &board->status);
  60. }
  61. }
  62. printk("gpib%i: exiting autospoll thread\n", board->minor);
  63. board->autospoll_task = NULL;
  64. unlock_kernel();
  65. return retval;
  66. }
  67. int ibonline(gpib_board_t *board, gpib_board_config_t config)
  68. {
  69. int retval;
  70. if( board->online ) return -EBUSY;
  71. if(board->interface == NULL) return -ENODEV;
  72. retval = gpib_allocate_board( board );
  73. if( retval < 0 ) return retval;
  74. retval = board->interface->attach(board, config);
  75. if(retval < 0)
  76. {
  77. board->interface->detach(board);
  78. printk("gpib: interface attach failed\n");
  79. return retval;
  80. }
  81. /* nios2nommu on 2.6.11 uclinux kernel has weird problems
  82. with autospoll thread causing huge slowdowns */
  83. #ifndef CONFIG_NIOS2
  84. board->autospoll_task = kthread_run(&autospoll_thread, board, "gpib%d_autospoll_kthread", board->minor);
  85. if(IS_ERR(board->autospoll_task))
  86. {
  87. printk("gpib: failed to create autospoll thread\n");
  88. board->interface->detach(board);
  89. return PTR_ERR(board->autospoll_task);
  90. }
  91. #endif
  92. board->online = 1;
  93. GPIB_DPRINTK( "gpib: board online\n" );
  94. return 0;
  95. }
  96. /* XXX need to make sure board is generally not in use (grab board lock?) */
  97. int iboffline( gpib_board_t *board )
  98. {
  99. int retval;
  100. if( board->online == 0 )
  101. {
  102. return 0;
  103. }
  104. if(board->interface == NULL) return -ENODEV;
  105. if(board->autospoll_task != NULL && !IS_ERR(board->autospoll_task))
  106. {
  107. retval = kthread_stop(board->autospoll_task);
  108. if(retval)
  109. printk("gpib: kthread_stop returned %i\n", retval);
  110. }
  111. board->interface->detach( board );
  112. gpib_deallocate_board( board );
  113. board->online = 0;
  114. GPIB_DPRINTK( "gpib: board offline\n" );
  115. return 0;
  116. }