Real camera pipelines generate frames on a schedule. This driver does the same — and hits a wall.
The previous drivers were reactive — they responded to userspace writes. A real camera generates frames autonomously on a hardware timer. I needed a driver that produces events independently, on a schedule, and wakes up readers when data is ready.
That sounds simple. But it introduced the constraint that changes everything about synchronization in this driver.
Kernel timer callbacks run in softirq context — an interrupt context where the CPU cannot sleep. That means:
| Primitive | Can sleep? | Safe in softirq? |
|---|---|---|
mutex | Yes | ❌ Illegal |
spinlock_t | No | ✅ Required |
Everything I learned about mutexes in drivers 01–03 was suddenly wrong. I had to switch to spinlocks with irqsave/irqrestore.
unsigned long flags;
spin_lock_irqsave(&kernel_logger.lock, flags);
/* critical section */
spin_unlock_irqrestore(&kernel_logger.lock, flags);| Function | Why not |
|---|---|
copy_to_user | May page-fault (sleep) |
wake_up_interruptible | Touches scheduler |
kmalloc(GFP_KERNEL) | May sleep |
mod_timer | Has internal locks |
uint8_t tmp[MEM_SIZE];
spin_lock_irqsave(&lock, flags);
memcpy(tmp, buffer[idx], copy_len); /* safe inside lock */
count--;
spin_unlock_irqrestore(&lock, flags);
if (copy_to_user(user_buf, tmp, copy_len)) /* outside lock */
return -EFAULT;| Bug | Fix |
|---|---|
copy_to_user under spinlock → kernel warning | Moved to after unlock, using local tmp buffer |
wake_up under spinlock → deadlock risk | Moved outside critical section |
| Timer not stopping on ioctl STOP | Added timer_active flag checked in callback |
Used del_timer on exit | Replaced with del_timer_sync — waits for in-progress callback |