Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
soc:2010:peper:journal:week11 [2010/08/06 15:46] peper created |
soc:2010:peper:journal:week11 [2010/08/08 07:04] (current) peper |
||
---|---|---|---|
Line 3: | Line 3: | ||
==== drivers in userspace ==== | ==== drivers in userspace ==== | ||
- | === addressing spaces === | + | |
+ | === Addressing spaces === | ||
First a bit of background. There are four different kind of addresses in gPXE: | First a bit of background. There are four different kind of addresses in gPXE: | ||
Line 27: | Line 29: | ||
This was tried and backed off because malloc() aligns allocations by their phys address. That could be worked around but doesn't really seem worth it. | This was tried and backed off because malloc() aligns allocations by their phys address. That could be worked around but doesn't really seem worth it. | ||
- | === some more improvements/cleanup === | + | === Unused functions === |
+ | |||
+ | I was a bit overoptimistic about linker stripping unused functions. | ||
+ | It turns out that functions are linked with object granularity so adding ''strtoull()'' to ''core/misc.c'' which is used only on linux was in fact growing other builds as well. | ||
+ | Moved it to a separate object ''core/strtoull.c'' to eliminate that problem. | ||
+ | |||
+ | That makes me wonder whether we have any dead functions that can be nuked to reduce size. Also on a similar note [[http://gcc.gnu.org/gcc-4.5/changes.html|gcc 4.5.0]] introduced whole program optimizations, which might be worth looking into. | ||
+ | Although I'm waiting for ''4.5.1'' as it also introduced some nasty regressions that are quite noticable on a source-based distro like [[http://www.exherbo.org|exherbo]] that I'm using. | ||
+ | |||
+ | === Nicer UIO-DMA support === | ||
+ | |||
+ | Up till recently the UIO-DMA initialization was a bit hacky. UIO-DMA requires a kernel module to register the device it is supposed to be handling DMA mappings for (and rightly so as the kernel DMA API needs the device). | ||
+ | As part of the registration it returns a unique ''device_id'' that is supposed to be passed by the userspace code to the UIO-DMA module later to tell different devices apart. | ||
+ | To handle the device registration I have introduced a very simple ''uio-dma-pci'' module, | ||
+ | but I didn't have a good idea how to pass the ''device_id'' returned by UIO-DMA to userspace (e.g. creating an extra char device with an ioctl just for that seemed ilke an overkill). | ||
+ | Not wanting to spend too much time on this then I just hacked UIO-DMA to recognize a special ''id'' value meaning the ''id'' of the last device registered with it. | ||
+ | |||
+ | This worked just fine, but this kind of hacks just don't let me sleep comfortably at night ;) | ||
+ | Since that time I have had the chance to inspect some of the code behind the ''/sys/'' PCI interface (see [[http://www.mjmwired.net/kernel/Documentation/filesystems/sysfs-pci.txt|sysfs-pci.txt]]) | ||
+ | and it looked quite simple as far as creating new sysfs attributes goes and the obvious solution occurred to me. Just add a sysfs device attribute with the ''UIO-DMA'' ''device_id''. And so I did: | ||
+ | <code c> | ||
+ | ssize_t uio_dma_id_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
+ | { | ||
+ | struct dev_data *dd = dev_get_drvdata(dev); | ||
+ | |||
+ | return snprintf(buf, PAGE_SIZE, "0x%08x\n", dd->uio_dma_id); | ||
+ | } | ||
+ | |||
+ | /** Device attribute with the UIO-DMA device id */ | ||
+ | static DEVICE_ATTR(uio_dma_id, S_IRUGO, uio_dma_id_show, NULL); | ||
+ | |||
+ | static int __devinit probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
+ | { | ||
+ | ... | ||
+ | device_create_file(&pdev->dev, &dev_attr_uio_dma_id); | ||
+ | ... | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | And done. It also has the the nice side-effect of ensuring the device we are using is handled by our simple driver and not anything else. | ||
+ | |||
+ | <code> | ||
+ | $ ls -al /sys/bus/pci/devices/0000:09:00.0/ | ||
+ | total 0 | ||
+ | drwxr-xr-x 3 root root 0 2010-08-08 15:13 . | ||
+ | drwxr-xr-x 5 root root 0 2010-08-08 15:13 .. | ||
+ | -rw-r--r-- 1 root root 4096 2010-08-08 16:00 broken_parity_status | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 15:47 class | ||
+ | -rw-r--r-- 1 root root 256 2010-08-08 15:47 config | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 16:00 consistent_dma_mask_bits | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 15:47 device | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 16:00 dma_mask_bits | ||
+ | lrwxrwxrwx 1 root root 0 2010-08-08 15:47 driver -> ../../../../../bus/pci/drivers/uio-dma-pci | ||
+ | -rw------- 1 root root 4096 2010-08-08 16:00 enable | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 15:47 irq | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 16:00 local_cpulist | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 16:00 local_cpus | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 16:00 modalias | ||
+ | -rw-r--r-- 1 root root 4096 2010-08-08 16:00 msi_bus | ||
+ | drwxr-xr-x 2 root root 0 2010-08-08 16:00 power | ||
+ | --w--w---- 1 root root 4096 2010-08-08 16:00 remove | ||
+ | --w--w---- 1 root root 4096 2010-08-08 16:00 rescan | ||
+ | --w------- 1 root root 4096 2010-08-08 16:00 reset | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 15:47 resource | ||
+ | -rw------- 1 root root 33554432 2010-08-08 16:00 resource0 | ||
+ | -r-------- 1 root root 65536 2010-08-08 16:00 rom | ||
+ | lrwxrwxrwx 1 root root 0 2010-08-08 16:00 subsystem -> ../../../../../bus/pci | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 16:00 subsystem_device | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 16:00 subsystem_vendor | ||
+ | -rw-r--r-- 1 root root 4096 2010-08-08 16:00 uevent | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 15:13 uio_dma_id | ||
+ | -r--r--r-- 1 root root 4096 2010-08-08 15:47 vendor | ||
+ | -rw------- 1 root root 128 2010-08-08 15:47 vpd | ||
+ | $ cat /sys/bus/pci/devices/0000:09:00.0/uio_dma_id | ||
+ | 0x00000002 | ||
+ | </code> | ||
+ | |||
+ | === Extra checks and cleanup === | ||
+ | |||
+ | Along with the changes described above went in some extra checks for common problems like whether we have root access, the device exists at /sys/ at all etc. | ||
+ | Also the ''lpci'' driver now can only support one device at the same time. That comes from the fact that gPXE's ''malloc_dma()'' API is device agnostic and on linux it isn't | ||
+ | (as mentioned earlier linux DMA API requires a device to be passed). | ||
==== bnx2 ==== | ==== bnx2 ==== | ||
+ | I have received [[http://cgi.ebay.com/394791-B21-HP-NC373T-PCIE-MFN-GIGABIT-/380143795317?cmd=ViewItem&pt=COMP_EN_Networking_Components&hash=item588255fc752010-08-01|this nic]] | ||
+ | late on Friday and started working on a driver for it. lspci output below: | ||
+ | <code> | ||
+ | 09:00.0 Ethernet controller [0200]: Broadcom Corporation NetXtreme II BCM5708 Gigabit Ethernet [14e4:164c] (rev 12) | ||
+ | Subsystem: Hewlett-Packard Company NC373T PCI Express Multifunction Gigabit Server Adapter [103c:7037] | ||
+ | Flags: 66MHz, medium devsel, IRQ 16 | ||
+ | Memory at fa000000 (64-bit, non-prefetchable) [size=32M] | ||
+ | Expansion ROM at f9ff0000 [disabled] [size=64K] | ||
+ | Capabilities: [40] PCI-X non-bridge device | ||
+ | Capabilities: [48] Power Management version 2 | ||
+ | Capabilities: [50] Vital Product Data | ||
+ | Capabilities: [58] MSI: Enable- Count=1/1 Maskable- 64bit+ | ||
+ | Kernel driver in use: uio-dma-pci | ||
+ | </code> | ||
+ | On the good side it has a [[http://www.broadcom.com/collateral/pg/NetXtremeII-PG203-R.pdf|datasheet]] and a driver in linux kernel. | ||
+ | On the bad side the linux driver is quite big: | ||
+ | <code> | ||
+ | 8601 linux-2.6/drivers/net/bnx2.c | ||
+ | 7368 linux-2.6/drivers/net/bnx2.h | ||
+ | 15969 total | ||
+ | </code> | ||
+ | and it requires ''firmware'' to work at all. | ||
+ | All in all I'm still a bit overwhelmed, but trying to get ''probe()'' to do something useful ;) | ||
+ | As there is no driver needing firmware in gPXE yet there is no support for it in mainline, | ||
+ | but Josh foresaw that problem last year when working on wireless drivers and worked on a [[http://git.etherboot.org/?p=people/oremanj/gpxe.git;a=shortlog;h=refs/heads/firmware|firmware branch]]. | ||
+ | I have rebased it on current master and will get to use it soon hopefully ;) |