Hello Colin,
I am glad you managed to get your USB wifi dongle working.
Thanks! It was a fun project.
I only briefly skimmed your commit series but I think it would be
worthwhile to integrate your additions. As we want to use the driver
component also on other platforms besides the PC the code should be
restructured (i.e. move the common parts from the 'pc' into the
'dde_linux' repo) anyway.
This would be fantastic. The reason I got stuck in the 'pc' repo is because I was working from the example of wifi_drv. In order to run dde_linux I assumed it was necessary to have the directory repos/pc/src/lib/pc/lx_emul or some analogous version. I completely agree 'dde_linux' is more appropriate. Indeed, the driver should also work on ARM systems with USB provided the lx_emul/kit framework can be used the same way.
At this point splitting the PCI and adding the
USB backend appears to be reasonable.
Yes. Regarding splitting up the components, a thought I had was to make the 'wifi_supplicant' a separate Genode component. Since it already runs as a separate thread using a shared buffer and semaphores, it shouldn't be too difficult to split it as its own component. The advantages would be that all interfacing of sculpt_manager with the supplicant would be common across drivers, making it easier to port more drivers, and each driver would inherit the same feature set of the supplicant (e.g. if ad-hoc mode were enabled it would not require much, if any, change to the drivers).
As you probably have noticed we have some ported USB device drivers, albeit
using the legacy lx_kit/lx_emul implementation, that share the glue-code.
Eventually we want to update them as well - so by all means, if you have
some ideas formed by your current experience feel free to share them.
Yes, I did see these drivers. My experience with the legacy lx_kit/lx_emul implementation has been much less positive than with the current version, sorry to say. My thoughts on porting USB drivers:
1) My 'wlan_usb' and 'lx_usb_wrapper' don't conform to the lx_emul/lx_kit distinction so would need to be refactored as you said, but the basic idea is the same, to have a layer of separation written in c between c++ code and linux-kernel code. Roughly 'wlab_usb' is intended to be something like lx_kit, and lx_usb_wrapper to be something like lx_emul. Ideally the author of a port should be required only to instantiate something like a 'Lx_kit::Usb' and make sure that the initcall is configured to call 'usb_register_driver'.
2) lx_kit requests a 'Platform' session to enumerate the devices. This is completely unnecessary in the case of a USB driver, since no devices will be used (Genode provides a separate USB interface). However, the lx_kit will loop forever if the device list is empty. As a workaround my driver asks for platform information about the USB host controller itself, just to get out of this loop by having a non-empty list. Ideally there would be a way to start a lx_kit session with the understanding that no devices are needed.
3) The ath9k driver on Linux opens a lot of simultaneous inbound interrupt URBs (something like 64, I'd have to check). I suppose this is to handle cases of heavy host workload so that the device-side queue doesn't fill. Unfortunately, Genode's USB interface doesn't seem capable of having so many URBs queued at once. Hence I had to implement a secondary queue, which is done a bit ad-hoc at the moment. Potentially Genode's limit could be relaxed and this would become unnecessary, or else it could be done more generically (i.e. applied to all endpoints).
4) Not relevant to making things work, but to performance, the model for preparing URBs is different between Linux and Genode. In Linux the memory needs to be allocated generically as a "socket buffer" (aka skbuff aka skb) and then attached to a URB, whereas in Genode one needs to allocate the space with the intention ahead of time that it's destined for USB (Usb::Interface::alloc). Hence any emulation of Linux kernel behavior by Genode is forced to bounce-buffer out of the Linux-allocated skb into a Genode-allocated packet. Perhaps this is an architectural distinction that cannot be overcome? My understanding of Genode IPC is not complete, but as I understand it the Genode 'packet_stream' interface is somewhat similar to Linux skbuff, except that each packet belongs to an assigned stream (e.g. network or USB). Is it possible to set up a common pool of stream packets and send them to network or USB as a later decision? In this case alloc_skb could allocate from the stream packet pool and save a bounce buffer transaction which occurs on 100% of wifi data in the current model (and probably happens on the network side too).
Regards,
Colin