| From: Prarit Bhargava <prarit@...>
[Note: these are based purely on reading the patch. I am not a kernel
hacker nor am I an ndiswrapper hacker.]
| +/*
| + * ndiswrapper_fix_broken_driver - apply additional HW modifications that are
| + * required to get a driver to work properly under Linux.
| + * @usb_pci_device: pointer to the USB or PCI device that may be modified
| + * @driver_name: pointer to the driver's name
| + *
| + * Applies appropriate modifications to a USB or PCI device if the driver_name
| + * specified is going to be loaded.
| + *
| + */
| +static void ndiswrapper_fix_broken_driver(void *usb_pci_device,
| + char *driver_name)
I think that this function should return an indication of success or
failure. In particular, I suspect that the BC564 is *dangerous* if
the fix does not install. Why? Because it probably zaps memory at
the address of the buffer mod 2^30, and without the fix, this memory
is going to belong to something else. If the fix doesn't install, the
driver load should fail.
The first argument is of type void *. As a C purist, I think that it
should be typed precisely. When is it a struct pci_dev *? What types
might it have? It looks to me:
- struct pci_dev *
- struct usb_interface * /* pre 2.6 kernel */
- struct usb_device * /* 2.6 or later kernel */
I would say that passing these in one parameter is questionable.
Clearly the two USB pointers can be passed in one parameter -- they
perform the same function in different kernel versions. I'd pass the
pci_dev pointer as a separate parameter.
I actually find it surprising that struct ndis_device does not contain
these pointers. I would have thought that code would want to get from
a struct ndis_device * to a corresponding struct pci_dev *.
An even cleaner alternative would be to have separate fixup functions
for USB and PCI. Unfortunately, that distinction has been lost inside
ndiswrapper_load_driver.
| + struct pci_dev *pdev = usb_pci_device;
This just casts the void *. If you separate the parameters as I just
suggested, the declaration is not needed.
| + if (pci_set_dma_mask(pdev, 0x3fffffff))
| + goto fix_error;
| + if (pci_set_consistent_dma_mask(pdev, 0x3fffffff))
| + goto fix_error;
| +
| + printk(KERN_INFO "ndiswrapper: 30-bit Broadcom Wireless "
| + "Work Around enabled\n");
| + return;
| +fix_error:
| + printk(KERN_WARNING "ndiswrapper: 30-bit Broadcom Wireless "
| + "Work Around could not be implemented\n");
I dislike gotos. I would have written this section as:
if (pci_set_dma_mask(pdev, 0x3fffffff)
|| pci_set_consistent_dma_mask(pdev, 0x3fffffff)) {
printk(KERN_WARNING "ndiswrapper: 30-bit Broadcom Wireless "
"Work Around could not be implemented\n");
} else {
printk(KERN_INFO "ndiswrapper: 30-bit Broadcom Wireless "
"Work Around enabled\n");
}
Not only is this shorter, but it has another advantage: it allows for
later code in the function to apply.
|