Jeff wrote:
* Interrupt handler is SCARY. You can potentially take and release the spinlock -many times- during a single interrupt.I think that can happen only in theory: A new packet is completed while the driver processes rx packets. I all normal cases there should be one spinlock operation per tx irq, and 0 per rx irq.
And error handling IMHO doesn't count: it should be rare.
Or do I overlook a common case?
Right now: enum for the nic registers, #define for the rest. If you don't like it I can change it.+#define NV_MIIPHY_DELAY 10
+#define NV_MIIPHY_DELAYMAX 10000
Style: it's fairly silly to mix enums and constants.
I think I copied it from another driver - which value would you recommend?+/* General driver defaults */
+#define NV_WATCHDOG_TIMEO (2*HZ)
this seems too short, and might trigger on normal events?
I usually try to write code that compiles as cpp - is that a forbidden in kernel modules?+static inline struct fe_priv *get_nvpriv(struct net_device *dev)
+{
+ return (struct fe_priv *) dev->priv;
+}
What's the point of this wrapper?
You don't need to cast from a void pointer, either.
[snip]+/*
+ * alloc_rx: fill rx ring entries.
+ * Return 1 if the allocations for the skbs failed and the
+ * rx engine is without Available descriptors
+ */
+static int alloc_rx(struct net_device *dev)
+{
Do you have specs that show that all nForce versions support unaligned buffers? skb_reserve is a performance feature, I don't want to add it yet. Testing that it works is on our TODO list.+ return 0;
+}
skb_reserve() seems to be missing
I wonder about calling dev_kfree_skb() from dev->tx_timeout() with dev->xmit_lock held...Is that bug in the networking core still not fixed?
What is the xxx_kfree_skb_xxx function that just works?+ /* 2) check that the packets were not sent already: */
+ tx_done(dev);
bug: tx_done unconditionally calls dev_kfree_skb_irq(), but here we are not in an interrupt.
Just guessing - it shouldn't hurt. CPU usage won't be important until nForce supports GigE. Should I remove it for now?+ /*
+ * the packet is for us - immediately tear down the pci mapping, and
+ * prefetch the first cacheline of the packet.
+ */
+ pci_unmap_single(np->pci_dev, np->rx_dma[i],
+ np->rx_skbuff[i]->len,
+ PCI_DMA_FROMDEVICE);
+ prefetch(np->rx_skbuff[i]->data);
is this just guessing? or has this actually shown some value?
I would prefer not to put stuff like this in unless it shows a measureable CPU usage or cache miss impact.
What should the nic do? I'll continue to allocate 1.8 kB buffers because I don't know how to reconfigure the nic hardware to reject large packets.+/*
+ * change_mtu: dev->change_mtu function
+ * Called with dev_base_lock held for read.
+ */
+static int change_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu > DEFAULT_MTU)
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
bug #1: have you tested changing the MTU while the NIC is actually running?
bug #2: need a minimum bound for the MTU as wellWhat is the minimum MTU? I remember a flamewar lkml about 200 byte MTU for noisy radio links.
What causes 0xfffffff? Hotplug? I think the irq handler could leave immediately if a reserved bit is set. I'll add that.+ for (i=0; ; i++) {
+ events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
+ writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+ pci_push(base);
+ dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
+ if (!(events & np->irqmask))
+ break;
bug: check for 0xffffffff
MII id 0 a valid mii address? Or is that broadcast to all?+ if (i == 32) {
+ printk(KERN_INFO "%s: open: failing due to lack of suitable PHY.\n",
+ dev->name);
+ ret = -EINVAL;
+ goto out_drain;
+ }
bug: check #0 after checking #1, before giving up