irq_user.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
  3. * Licensed under the GPL
  4. */
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <signal.h>
  9. #include <string.h>
  10. #include <sys/poll.h>
  11. #include <sys/types.h>
  12. #include <sys/time.h>
  13. #include "user_util.h"
  14. #include "kern_util.h"
  15. #include "user.h"
  16. #include "process.h"
  17. #include "sigio.h"
  18. #include "irq_user.h"
  19. #include "os.h"
  20. struct irq_fd {
  21. struct irq_fd *next;
  22. void *id;
  23. int fd;
  24. int type;
  25. int irq;
  26. int pid;
  27. int events;
  28. int current_events;
  29. };
  30. static struct irq_fd *active_fds = NULL;
  31. static struct irq_fd **last_irq_ptr = &active_fds;
  32. static struct pollfd *pollfds = NULL;
  33. static int pollfds_num = 0;
  34. static int pollfds_size = 0;
  35. extern int io_count, intr_count;
  36. extern void free_irqs(void);
  37. void sigio_handler(int sig, union uml_pt_regs *regs)
  38. {
  39. struct irq_fd *irq_fd;
  40. int i, n;
  41. if(smp_sigio_handler()) return;
  42. while(1){
  43. n = poll(pollfds, pollfds_num, 0);
  44. if(n < 0){
  45. if(errno == EINTR) continue;
  46. printk("sigio_handler : poll returned %d, "
  47. "errno = %d\n", n, errno);
  48. break;
  49. }
  50. if(n == 0) break;
  51. irq_fd = active_fds;
  52. for(i = 0; i < pollfds_num; i++){
  53. if(pollfds[i].revents != 0){
  54. irq_fd->current_events = pollfds[i].revents;
  55. pollfds[i].fd = -1;
  56. }
  57. irq_fd = irq_fd->next;
  58. }
  59. for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
  60. if(irq_fd->current_events != 0){
  61. irq_fd->current_events = 0;
  62. do_IRQ(irq_fd->irq, regs);
  63. }
  64. }
  65. }
  66. free_irqs();
  67. }
  68. int activate_ipi(int fd, int pid)
  69. {
  70. return(os_set_fd_async(fd, pid));
  71. }
  72. static void maybe_sigio_broken(int fd, int type)
  73. {
  74. if(isatty(fd)){
  75. if((type == IRQ_WRITE) && !pty_output_sigio){
  76. write_sigio_workaround();
  77. add_sigio_fd(fd, 0);
  78. }
  79. else if((type == IRQ_READ) && !pty_close_sigio){
  80. write_sigio_workaround();
  81. add_sigio_fd(fd, 1);
  82. }
  83. }
  84. }
  85. int activate_fd(int irq, int fd, int type, void *dev_id)
  86. {
  87. struct pollfd *tmp_pfd;
  88. struct irq_fd *new_fd, *irq_fd;
  89. unsigned long flags;
  90. int pid, events, err, n, size;
  91. pid = os_getpid();
  92. err = os_set_fd_async(fd, pid);
  93. if(err < 0)
  94. goto out;
  95. new_fd = um_kmalloc(sizeof(*new_fd));
  96. err = -ENOMEM;
  97. if(new_fd == NULL)
  98. goto out;
  99. if(type == IRQ_READ) events = POLLIN | POLLPRI;
  100. else events = POLLOUT;
  101. *new_fd = ((struct irq_fd) { .next = NULL,
  102. .id = dev_id,
  103. .fd = fd,
  104. .type = type,
  105. .irq = irq,
  106. .pid = pid,
  107. .events = events,
  108. .current_events = 0 } );
  109. /* Critical section - locked by a spinlock because this stuff can
  110. * be changed from interrupt handlers. The stuff above is done
  111. * outside the lock because it allocates memory.
  112. */
  113. /* Actually, it only looks like it can be called from interrupt
  114. * context. The culprit is reactivate_fd, which calls
  115. * maybe_sigio_broken, which calls write_sigio_workaround,
  116. * which calls activate_fd. However, write_sigio_workaround should
  117. * only be called once, at boot time. That would make it clear that
  118. * this is called only from process context, and can be locked with
  119. * a semaphore.
  120. */
  121. flags = irq_lock();
  122. for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
  123. if((irq_fd->fd == fd) && (irq_fd->type == type)){
  124. printk("Registering fd %d twice\n", fd);
  125. printk("Irqs : %d, %d\n", irq_fd->irq, irq);
  126. printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id);
  127. goto out_unlock;
  128. }
  129. }
  130. n = pollfds_num;
  131. if(n == pollfds_size){
  132. while(1){
  133. /* Here we have to drop the lock in order to call
  134. * kmalloc, which might sleep. If something else
  135. * came in and changed the pollfds array, we free
  136. * the buffer and try again.
  137. */
  138. irq_unlock(flags);
  139. size = (pollfds_num + 1) * sizeof(pollfds[0]);
  140. tmp_pfd = um_kmalloc(size);
  141. flags = irq_lock();
  142. if(tmp_pfd == NULL)
  143. goto out_unlock;
  144. if(n == pollfds_size)
  145. break;
  146. kfree(tmp_pfd);
  147. }
  148. if(pollfds != NULL){
  149. memcpy(tmp_pfd, pollfds,
  150. sizeof(pollfds[0]) * pollfds_size);
  151. kfree(pollfds);
  152. }
  153. pollfds = tmp_pfd;
  154. pollfds_size++;
  155. }
  156. if(type == IRQ_WRITE)
  157. fd = -1;
  158. pollfds[pollfds_num] = ((struct pollfd) { .fd = fd,
  159. .events = events,
  160. .revents = 0 });
  161. pollfds_num++;
  162. *last_irq_ptr = new_fd;
  163. last_irq_ptr = &new_fd->next;
  164. irq_unlock(flags);
  165. /* This calls activate_fd, so it has to be outside the critical
  166. * section.
  167. */
  168. maybe_sigio_broken(fd, type);
  169. return(0);
  170. out_unlock:
  171. irq_unlock(flags);
  172. kfree(new_fd);
  173. out:
  174. return(err);
  175. }
  176. static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
  177. {
  178. struct irq_fd **prev;
  179. unsigned long flags;
  180. int i = 0;
  181. flags = irq_lock();
  182. prev = &active_fds;
  183. while(*prev != NULL){
  184. if((*test)(*prev, arg)){
  185. struct irq_fd *old_fd = *prev;
  186. if((pollfds[i].fd != -1) &&
  187. (pollfds[i].fd != (*prev)->fd)){
  188. printk("free_irq_by_cb - mismatch between "
  189. "active_fds and pollfds, fd %d vs %d\n",
  190. (*prev)->fd, pollfds[i].fd);
  191. goto out;
  192. }
  193. pollfds_num--;
  194. /* This moves the *whole* array after pollfds[i] (though
  195. * it doesn't spot as such)! */
  196. memmove(&pollfds[i], &pollfds[i + 1],
  197. (pollfds_num - i) * sizeof(pollfds[0]));
  198. if(last_irq_ptr == &old_fd->next)
  199. last_irq_ptr = prev;
  200. *prev = (*prev)->next;
  201. if(old_fd->type == IRQ_WRITE)
  202. ignore_sigio_fd(old_fd->fd);
  203. kfree(old_fd);
  204. continue;
  205. }
  206. prev = &(*prev)->next;
  207. i++;
  208. }
  209. out:
  210. irq_unlock(flags);
  211. }
  212. struct irq_and_dev {
  213. int irq;
  214. void *dev;
  215. };
  216. static int same_irq_and_dev(struct irq_fd *irq, void *d)
  217. {
  218. struct irq_and_dev *data = d;
  219. return((irq->irq == data->irq) && (irq->id == data->dev));
  220. }
  221. void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
  222. {
  223. struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
  224. .dev = dev });
  225. free_irq_by_cb(same_irq_and_dev, &data);
  226. }
  227. static int same_fd(struct irq_fd *irq, void *fd)
  228. {
  229. return(irq->fd == *((int *) fd));
  230. }
  231. void free_irq_by_fd(int fd)
  232. {
  233. free_irq_by_cb(same_fd, &fd);
  234. }
  235. static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
  236. {
  237. struct irq_fd *irq;
  238. int i = 0;
  239. for(irq=active_fds; irq != NULL; irq = irq->next){
  240. if((irq->fd == fd) && (irq->irq == irqnum)) break;
  241. i++;
  242. }
  243. if(irq == NULL){
  244. printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
  245. goto out;
  246. }
  247. if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){
  248. printk("find_irq_by_fd - mismatch between active_fds and "
  249. "pollfds, fd %d vs %d, need %d\n", irq->fd,
  250. pollfds[i].fd, fd);
  251. irq = NULL;
  252. goto out;
  253. }
  254. *index_out = i;
  255. out:
  256. return(irq);
  257. }
  258. void reactivate_fd(int fd, int irqnum)
  259. {
  260. struct irq_fd *irq;
  261. unsigned long flags;
  262. int i;
  263. flags = irq_lock();
  264. irq = find_irq_by_fd(fd, irqnum, &i);
  265. if(irq == NULL){
  266. irq_unlock(flags);
  267. return;
  268. }
  269. pollfds[i].fd = irq->fd;
  270. irq_unlock(flags);
  271. /* This calls activate_fd, so it has to be outside the critical
  272. * section.
  273. */
  274. maybe_sigio_broken(fd, irq->type);
  275. }
  276. void deactivate_fd(int fd, int irqnum)
  277. {
  278. struct irq_fd *irq;
  279. unsigned long flags;
  280. int i;
  281. flags = irq_lock();
  282. irq = find_irq_by_fd(fd, irqnum, &i);
  283. if(irq == NULL)
  284. goto out;
  285. pollfds[i].fd = -1;
  286. out:
  287. irq_unlock(flags);
  288. }
  289. int deactivate_all_fds(void)
  290. {
  291. struct irq_fd *irq;
  292. int err;
  293. for(irq=active_fds;irq != NULL;irq = irq->next){
  294. err = os_clear_fd_async(irq->fd);
  295. if(err)
  296. return(err);
  297. }
  298. /* If there is a signal already queued, after unblocking ignore it */
  299. set_handler(SIGIO, SIG_IGN, 0, -1);
  300. return(0);
  301. }
  302. void forward_ipi(int fd, int pid)
  303. {
  304. int err;
  305. err = os_set_owner(fd, pid);
  306. if(err < 0)
  307. printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
  308. "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
  309. }
  310. void forward_interrupts(int pid)
  311. {
  312. struct irq_fd *irq;
  313. unsigned long flags;
  314. int err;
  315. flags = irq_lock();
  316. for(irq=active_fds;irq != NULL;irq = irq->next){
  317. err = os_set_owner(irq->fd, pid);
  318. if(err < 0){
  319. /* XXX Just remove the irq rather than
  320. * print out an infinite stream of these
  321. */
  322. printk("Failed to forward %d to pid %d, err = %d\n",
  323. irq->fd, pid, -err);
  324. }
  325. irq->pid = pid;
  326. }
  327. irq_unlock(flags);
  328. }
  329. void init_irq_signals(int on_sigstack)
  330. {
  331. __sighandler_t h;
  332. int flags;
  333. flags = on_sigstack ? SA_ONSTACK : 0;
  334. if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
  335. else h = boot_timer_handler;
  336. set_handler(SIGVTALRM, h, flags | SA_RESTART,
  337. SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
  338. set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
  339. SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
  340. signal(SIGWINCH, SIG_IGN);
  341. }
  342. /*
  343. * Overrides for Emacs so that we follow Linus's tabbing style.
  344. * Emacs will notice this stuff at the end of the file and automatically
  345. * adjust the settings for this buffer only. This must remain at the end
  346. * of the file.
  347. * ---------------------------------------------------------------------------
  348. * Local variables:
  349. * c-file-style: "linux"
  350. * End:
  351. */