Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 501 lines 13 kB view raw
1/********************************************************************* 2 * 3 * sir_kthread.c: dedicated thread to process scheduled 4 * sir device setup requests 5 * 6 * Copyright (c) 2002 Martin Diehl 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 ********************************************************************/ 14 15#include <linux/module.h> 16#include <linux/kernel.h> 17#include <linux/version.h> 18#include <linux/init.h> 19#include <linux/smp_lock.h> 20#include <linux/completion.h> 21#include <linux/delay.h> 22 23#include <net/irda/irda.h> 24 25#include "sir-dev.h" 26 27/************************************************************************** 28 * 29 * kIrDAd kernel thread and config state machine 30 * 31 */ 32 33struct irda_request_queue { 34 struct list_head request_list; 35 spinlock_t lock; 36 task_t *thread; 37 struct completion exit; 38 wait_queue_head_t kick, done; 39 atomic_t num_pending; 40}; 41 42static struct irda_request_queue irda_rq_queue; 43 44static int irda_queue_request(struct irda_request *rq) 45{ 46 int ret = 0; 47 unsigned long flags; 48 49 if (!test_and_set_bit(0, &rq->pending)) { 50 spin_lock_irqsave(&irda_rq_queue.lock, flags); 51 list_add_tail(&rq->lh_request, &irda_rq_queue.request_list); 52 wake_up(&irda_rq_queue.kick); 53 atomic_inc(&irda_rq_queue.num_pending); 54 spin_unlock_irqrestore(&irda_rq_queue.lock, flags); 55 ret = 1; 56 } 57 return ret; 58} 59 60static void irda_request_timer(unsigned long data) 61{ 62 struct irda_request *rq = (struct irda_request *)data; 63 unsigned long flags; 64 65 spin_lock_irqsave(&irda_rq_queue.lock, flags); 66 list_add_tail(&rq->lh_request, &irda_rq_queue.request_list); 67 wake_up(&irda_rq_queue.kick); 68 spin_unlock_irqrestore(&irda_rq_queue.lock, flags); 69} 70 71static int irda_queue_delayed_request(struct irda_request *rq, unsigned long delay) 72{ 73 int ret = 0; 74 struct timer_list *timer = &rq->timer; 75 76 if (!test_and_set_bit(0, &rq->pending)) { 77 timer->expires = jiffies + delay; 78 timer->function = irda_request_timer; 79 timer->data = (unsigned long)rq; 80 atomic_inc(&irda_rq_queue.num_pending); 81 add_timer(timer); 82 ret = 1; 83 } 84 return ret; 85} 86 87static void run_irda_queue(void) 88{ 89 unsigned long flags; 90 struct list_head *entry, *tmp; 91 struct irda_request *rq; 92 93 spin_lock_irqsave(&irda_rq_queue.lock, flags); 94 list_for_each_safe(entry, tmp, &irda_rq_queue.request_list) { 95 rq = list_entry(entry, struct irda_request, lh_request); 96 list_del_init(entry); 97 spin_unlock_irqrestore(&irda_rq_queue.lock, flags); 98 99 clear_bit(0, &rq->pending); 100 rq->func(rq->data); 101 102 if (atomic_dec_and_test(&irda_rq_queue.num_pending)) 103 wake_up(&irda_rq_queue.done); 104 105 spin_lock_irqsave(&irda_rq_queue.lock, flags); 106 } 107 spin_unlock_irqrestore(&irda_rq_queue.lock, flags); 108} 109 110static int irda_thread(void *startup) 111{ 112 DECLARE_WAITQUEUE(wait, current); 113 114 daemonize("kIrDAd"); 115 116 irda_rq_queue.thread = current; 117 118 complete((struct completion *)startup); 119 120 while (irda_rq_queue.thread != NULL) { 121 122 /* We use TASK_INTERRUPTIBLE, rather than 123 * TASK_UNINTERRUPTIBLE. Andrew Morton made this 124 * change ; he told me that it is safe, because "signal 125 * blocking is now handled in daemonize()", he added 126 * that the problem is that "uninterruptible sleep 127 * contributes to load average", making user worry. 128 * Jean II */ 129 set_task_state(current, TASK_INTERRUPTIBLE); 130 add_wait_queue(&irda_rq_queue.kick, &wait); 131 if (list_empty(&irda_rq_queue.request_list)) 132 schedule(); 133 else 134 __set_task_state(current, TASK_RUNNING); 135 remove_wait_queue(&irda_rq_queue.kick, &wait); 136 137 /* make swsusp happy with our thread */ 138 try_to_freeze(); 139 140 run_irda_queue(); 141 } 142 143#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,35) 144 reparent_to_init(); 145#endif 146 complete_and_exit(&irda_rq_queue.exit, 0); 147 /* never reached */ 148 return 0; 149} 150 151 152static void flush_irda_queue(void) 153{ 154 if (atomic_read(&irda_rq_queue.num_pending)) { 155 156 DECLARE_WAITQUEUE(wait, current); 157 158 if (!list_empty(&irda_rq_queue.request_list)) 159 run_irda_queue(); 160 161 set_task_state(current, TASK_UNINTERRUPTIBLE); 162 add_wait_queue(&irda_rq_queue.done, &wait); 163 if (atomic_read(&irda_rq_queue.num_pending)) 164 schedule(); 165 else 166 __set_task_state(current, TASK_RUNNING); 167 remove_wait_queue(&irda_rq_queue.done, &wait); 168 } 169} 170 171/* substate handler of the config-fsm to handle the cases where we want 172 * to wait for transmit completion before changing the port configuration 173 */ 174 175static int irda_tx_complete_fsm(struct sir_dev *dev) 176{ 177 struct sir_fsm *fsm = &dev->fsm; 178 unsigned next_state, delay; 179 unsigned bytes_left; 180 181 do { 182 next_state = fsm->substate; /* default: stay in current substate */ 183 delay = 0; 184 185 switch(fsm->substate) { 186 187 case SIRDEV_STATE_WAIT_XMIT: 188 if (dev->drv->chars_in_buffer) 189 bytes_left = dev->drv->chars_in_buffer(dev); 190 else 191 bytes_left = 0; 192 if (!bytes_left) { 193 next_state = SIRDEV_STATE_WAIT_UNTIL_SENT; 194 break; 195 } 196 197 if (dev->speed > 115200) 198 delay = (bytes_left*8*10000) / (dev->speed/100); 199 else if (dev->speed > 0) 200 delay = (bytes_left*10*10000) / (dev->speed/100); 201 else 202 delay = 0; 203 /* expected delay (usec) until remaining bytes are sent */ 204 if (delay < 100) { 205 udelay(delay); 206 delay = 0; 207 break; 208 } 209 /* sleep some longer delay (msec) */ 210 delay = (delay+999) / 1000; 211 break; 212 213 case SIRDEV_STATE_WAIT_UNTIL_SENT: 214 /* block until underlaying hardware buffer are empty */ 215 if (dev->drv->wait_until_sent) 216 dev->drv->wait_until_sent(dev); 217 next_state = SIRDEV_STATE_TX_DONE; 218 break; 219 220 case SIRDEV_STATE_TX_DONE: 221 return 0; 222 223 default: 224 IRDA_ERROR("%s - undefined state\n", __FUNCTION__); 225 return -EINVAL; 226 } 227 fsm->substate = next_state; 228 } while (delay == 0); 229 return delay; 230} 231 232/* 233 * Function irda_config_fsm 234 * 235 * State machine to handle the configuration of the device (and attached dongle, if any). 236 * This handler is scheduled for execution in kIrDAd context, so we can sleep. 237 * however, kIrDAd is shared by all sir_dev devices so we better don't sleep there too 238 * long. Instead, for longer delays we start a timer to reschedule us later. 239 * On entry, fsm->sem is always locked and the netdev xmit queue stopped. 240 * Both must be unlocked/restarted on completion - but only on final exit. 241 */ 242 243static void irda_config_fsm(void *data) 244{ 245 struct sir_dev *dev = data; 246 struct sir_fsm *fsm = &dev->fsm; 247 int next_state; 248 int ret = -1; 249 unsigned delay; 250 251 IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies); 252 253 do { 254 IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n", 255 __FUNCTION__, fsm->state, fsm->substate); 256 257 next_state = fsm->state; 258 delay = 0; 259 260 switch(fsm->state) { 261 262 case SIRDEV_STATE_DONGLE_OPEN: 263 if (dev->dongle_drv != NULL) { 264 ret = sirdev_put_dongle(dev); 265 if (ret) { 266 fsm->result = -EINVAL; 267 next_state = SIRDEV_STATE_ERROR; 268 break; 269 } 270 } 271 272 /* Initialize dongle */ 273 ret = sirdev_get_dongle(dev, fsm->param); 274 if (ret) { 275 fsm->result = ret; 276 next_state = SIRDEV_STATE_ERROR; 277 break; 278 } 279 280 /* Dongles are powered through the modem control lines which 281 * were just set during open. Before resetting, let's wait for 282 * the power to stabilize. This is what some dongle drivers did 283 * in open before, while others didn't - should be safe anyway. 284 */ 285 286 delay = 50; 287 fsm->substate = SIRDEV_STATE_DONGLE_RESET; 288 next_state = SIRDEV_STATE_DONGLE_RESET; 289 290 fsm->param = 9600; 291 292 break; 293 294 case SIRDEV_STATE_DONGLE_CLOSE: 295 /* shouldn't we just treat this as success=? */ 296 if (dev->dongle_drv == NULL) { 297 fsm->result = -EINVAL; 298 next_state = SIRDEV_STATE_ERROR; 299 break; 300 } 301 302 ret = sirdev_put_dongle(dev); 303 if (ret) { 304 fsm->result = ret; 305 next_state = SIRDEV_STATE_ERROR; 306 break; 307 } 308 next_state = SIRDEV_STATE_DONE; 309 break; 310 311 case SIRDEV_STATE_SET_DTR_RTS: 312 ret = sirdev_set_dtr_rts(dev, 313 (fsm->param&0x02) ? TRUE : FALSE, 314 (fsm->param&0x01) ? TRUE : FALSE); 315 next_state = SIRDEV_STATE_DONE; 316 break; 317 318 case SIRDEV_STATE_SET_SPEED: 319 fsm->substate = SIRDEV_STATE_WAIT_XMIT; 320 next_state = SIRDEV_STATE_DONGLE_CHECK; 321 break; 322 323 case SIRDEV_STATE_DONGLE_CHECK: 324 ret = irda_tx_complete_fsm(dev); 325 if (ret < 0) { 326 fsm->result = ret; 327 next_state = SIRDEV_STATE_ERROR; 328 break; 329 } 330 if ((delay=ret) != 0) 331 break; 332 333 if (dev->dongle_drv) { 334 fsm->substate = SIRDEV_STATE_DONGLE_RESET; 335 next_state = SIRDEV_STATE_DONGLE_RESET; 336 } 337 else { 338 dev->speed = fsm->param; 339 next_state = SIRDEV_STATE_PORT_SPEED; 340 } 341 break; 342 343 case SIRDEV_STATE_DONGLE_RESET: 344 if (dev->dongle_drv->reset) { 345 ret = dev->dongle_drv->reset(dev); 346 if (ret < 0) { 347 fsm->result = ret; 348 next_state = SIRDEV_STATE_ERROR; 349 break; 350 } 351 } 352 else 353 ret = 0; 354 if ((delay=ret) == 0) { 355 /* set serial port according to dongle default speed */ 356 if (dev->drv->set_speed) 357 dev->drv->set_speed(dev, dev->speed); 358 fsm->substate = SIRDEV_STATE_DONGLE_SPEED; 359 next_state = SIRDEV_STATE_DONGLE_SPEED; 360 } 361 break; 362 363 case SIRDEV_STATE_DONGLE_SPEED: 364 if (dev->dongle_drv->reset) { 365 ret = dev->dongle_drv->set_speed(dev, fsm->param); 366 if (ret < 0) { 367 fsm->result = ret; 368 next_state = SIRDEV_STATE_ERROR; 369 break; 370 } 371 } 372 else 373 ret = 0; 374 if ((delay=ret) == 0) 375 next_state = SIRDEV_STATE_PORT_SPEED; 376 break; 377 378 case SIRDEV_STATE_PORT_SPEED: 379 /* Finally we are ready to change the serial port speed */ 380 if (dev->drv->set_speed) 381 dev->drv->set_speed(dev, dev->speed); 382 dev->new_speed = 0; 383 next_state = SIRDEV_STATE_DONE; 384 break; 385 386 case SIRDEV_STATE_DONE: 387 /* Signal network layer so it can send more frames */ 388 netif_wake_queue(dev->netdev); 389 next_state = SIRDEV_STATE_COMPLETE; 390 break; 391 392 default: 393 IRDA_ERROR("%s - undefined state\n", __FUNCTION__); 394 fsm->result = -EINVAL; 395 /* fall thru */ 396 397 case SIRDEV_STATE_ERROR: 398 IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result); 399 400#if 0 /* don't enable this before we have netdev->tx_timeout to recover */ 401 netif_stop_queue(dev->netdev); 402#else 403 netif_wake_queue(dev->netdev); 404#endif 405 /* fall thru */ 406 407 case SIRDEV_STATE_COMPLETE: 408 /* config change finished, so we are not busy any longer */ 409 sirdev_enable_rx(dev); 410 up(&fsm->sem); 411 return; 412 } 413 fsm->state = next_state; 414 } while(!delay); 415 416 irda_queue_delayed_request(&fsm->rq, msecs_to_jiffies(delay)); 417} 418 419/* schedule some device configuration task for execution by kIrDAd 420 * on behalf of the above state machine. 421 * can be called from process or interrupt/tasklet context. 422 */ 423 424int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param) 425{ 426 struct sir_fsm *fsm = &dev->fsm; 427 int xmit_was_down; 428 429 IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param); 430 431 if (down_trylock(&fsm->sem)) { 432 if (in_interrupt() || in_atomic() || irqs_disabled()) { 433 IRDA_DEBUG(1, "%s(), state machine busy!\n", __FUNCTION__); 434 return -EWOULDBLOCK; 435 } else 436 down(&fsm->sem); 437 } 438 439 if (fsm->state == SIRDEV_STATE_DEAD) { 440 /* race with sirdev_close should never happen */ 441 IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__); 442 up(&fsm->sem); 443 return -ESTALE; /* or better EPIPE? */ 444 } 445 446 xmit_was_down = netif_queue_stopped(dev->netdev); 447 netif_stop_queue(dev->netdev); 448 atomic_set(&dev->enable_rx, 0); 449 450 fsm->state = initial_state; 451 fsm->param = param; 452 fsm->result = 0; 453 454 INIT_LIST_HEAD(&fsm->rq.lh_request); 455 fsm->rq.pending = 0; 456 fsm->rq.func = irda_config_fsm; 457 fsm->rq.data = dev; 458 459 if (!irda_queue_request(&fsm->rq)) { /* returns 0 on error! */ 460 atomic_set(&dev->enable_rx, 1); 461 if (!xmit_was_down) 462 netif_wake_queue(dev->netdev); 463 up(&fsm->sem); 464 return -EAGAIN; 465 } 466 return 0; 467} 468 469int __init irda_thread_create(void) 470{ 471 struct completion startup; 472 int pid; 473 474 spin_lock_init(&irda_rq_queue.lock); 475 irda_rq_queue.thread = NULL; 476 INIT_LIST_HEAD(&irda_rq_queue.request_list); 477 init_waitqueue_head(&irda_rq_queue.kick); 478 init_waitqueue_head(&irda_rq_queue.done); 479 atomic_set(&irda_rq_queue.num_pending, 0); 480 481 init_completion(&startup); 482 pid = kernel_thread(irda_thread, &startup, CLONE_FS|CLONE_FILES); 483 if (pid <= 0) 484 return -EAGAIN; 485 else 486 wait_for_completion(&startup); 487 488 return 0; 489} 490 491void __exit irda_thread_join(void) 492{ 493 if (irda_rq_queue.thread) { 494 flush_irda_queue(); 495 init_completion(&irda_rq_queue.exit); 496 irda_rq_queue.thread = NULL; 497 wake_up(&irda_rq_queue.kick); 498 wait_for_completion(&irda_rq_queue.exit); 499 } 500} 501