OK, I made some time to look at that. As I've mentioned already, the "spi_bitbang" code needed to morph in this direction, and that was in fact the patch I was hoping you'd be sending. So I finished that up instead, and have sent it separately ... but I've also attached the C file to this response. > +struct threaded_async_data { > + atomic_t exiting; > + struct spi_master *master; > + struct task_struct *thread; > + wait_queue_head_t wq; I just kept the workqueue, named after its device. It makes the code look a lot simpler! > + struct list_head msgs; > + spinlock_t lock; > + int (*xfer) (struct spi_master *, struct spi_message *); > +}; > + > +/** > + * spi_start_async - start the thread > + * @master: SPI controller structure which the thread is related to > + * @return: abstract pointer to the thread context > + */ > +int spi_start_async (struct spi_master *master, int (*xfer)(struct spi_master *, > struct spi_message *)) I did this differently, but liked your start/stop names. :) So: int spi_bitbang_start(struct spi_bitbang *bitbang); int spi_bitbang_stop(struct spi_bitbang *bitbang); to start and stop processing the queue associated with the bitbanged spi_master. Callbacks just get stored in the structure; simpler, and the return value is just a normal zero-or-negative-errno. > @@ -152,6 +152,7 @@ static inline void spi_unregister_driver > * device's SPI controller; protocol code may call this. > * @transfer: adds a message to the controller's transfer queue. > * @cleanup: frees controller-specific state > + * @context: controller-specific data > * > * Each SPI master controller can communicate with one or more spi_device > * children. These make a small bus, sharing MOSI, MISO and SCK signals I've not seen a need for that yet; the class_get_devdata() is doing that already. And it's now wrapped up as spi_master_get_devdata(). - Dave