Work queues are mechanism for bottom halves that are handled by kernel threads.
Consequently the code executes in a process context.
This means that bottom halves that are implemented in work queues can "sleep", since there is a process that is scheduled and can continue after the sleep is over.
Of the three mechanisms only work queues run an a process context.