/* * As each timer expires, it determines (a) whether the "transmit" * waiter needs to be woken up, and (b) whether the poller needs to * be rescheduled. */ static void dgnc_poll_handler(struct timer_list *unused) { struct dgnc_board *brd; unsigned long flags; int i; unsigned long new_time; for (i = 0; i < dgnc_num_boards; i++) { brd = dgnc_board[i]; spin_lock_irqsave(&brd->bd_lock, flags); if (brd->state == BOARD_FAILED) { spin_unlock_irqrestore(&brd->bd_lock, flags); continue; } tasklet_schedule(&brd->helper_tasklet); spin_unlock_irqrestore(&brd->bd_lock, flags); } /* Schedule ourself back at the nominal wakeup interval. */ spin_lock_irqsave(&dgnc_poll_lock, flags); dgnc_poll_time += dgnc_jiffies_from_ms(dgnc_poll_tick); new_time = dgnc_poll_time - jiffies; if ((ulong)new_time >= 2 * dgnc_poll_tick) dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick); timer_setup(&dgnc_poll_timer, dgnc_poll_handler, 0); dgnc_poll_timer.expires = dgnc_poll_time; spin_unlock_irqrestore(&dgnc_poll_lock, flags); if (!dgnc_poll_stop) add_timer(&dgnc_poll_timer); }
static int dgnc_start(void) { int rc = 0; unsigned long flags; struct device *dev; init_timer(&dgnc_poll_timer); rc = register_chrdev(0, "dgnc", &dgnc_board_fops); if (rc < 0) { pr_err(DRVSTR ": Can't register dgnc driver device (%d)\n", rc); return rc; } dgnc_major = rc; dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt"); if (IS_ERR(dgnc_class)) { rc = PTR_ERR(dgnc_class); pr_err(DRVSTR ": Can't create dgnc_mgmt class (%d)\n", rc); goto failed_class; } dev = device_create(dgnc_class, NULL, MKDEV(dgnc_major, 0), NULL, "dgnc_mgmt"); if (IS_ERR(dev)) { rc = PTR_ERR(dev); pr_err(DRVSTR ": Can't create device (%d)\n", rc); goto failed_device; } /* Start the poller */ spin_lock_irqsave(&dgnc_poll_lock, flags); setup_timer(&dgnc_poll_timer, dgnc_poll_handler, 0); dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick); dgnc_poll_timer.expires = dgnc_poll_time; spin_unlock_irqrestore(&dgnc_poll_lock, flags); add_timer(&dgnc_poll_timer); return 0; failed_device: class_destroy(dgnc_class); failed_class: unregister_chrdev(dgnc_major, "dgnc"); return rc; }