All of lore.kernel.org
 help / color / mirror / Atom feed
From: Manfred Spraul <manfred@colorfullife.com>
To: Jeff Garzik <jgarzik@pobox.com>
Cc: Carl-Daniel Hailfinger <c-d.hailfinger.kernel.2004@gmx.net>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] [2.4] forcedeth network driver
Date: Sat, 24 Jan 2004 19:53:56 +0100	[thread overview]
Message-ID: <4012BF44.9@colorfullife.com> (raw)

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?

>> +#define NV_MIIPHY_DELAY	10
>> +#define NV_MIIPHY_DELAYMAX	10000
>
>Style:  it's fairly silly to mix enums and constants.
>  
>
Right now: enum for the nic registers, #define for the rest. If you 
don't like it I can change it.

>> +/* General driver defaults */
>> +#define NV_WATCHDOG_TIMEO	(2*HZ)
>
>this seems too short, and might trigger on normal events?
>  
>
I think I copied it from another driver - which value would you recommend?

>> +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.
>  
>
I usually try to write code that compiles as cpp - is that a forbidden 
in kernel modules?

>Locking for this function and update_linkspeed() is a bit random... 
>sometimes it's called inside the lock, sometimes not.
>
Should be always inside the lock - I'll check for bugs.

>> +/*
>> + * nic_ioctl: dev->do_ioctl function
>> + * Called with rtnl_lock held.
>> + */
>> +static int nic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
>> +{
>> +	return -EOPNOTSUPP;
>> +}
>
>These days, I am very much not interested in merging drivers that do not 
>implement the stupid-simple ETHTOOL_GDRVINFO ioctl.
>  
>
Ok.

>> +/*
>> + * 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)
>> +{
>
[snip]

>> +	return 0;
>> +}
>
>skb_reserve() seems to be missing
>  
>
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.

>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?

>> +	np->next_tx++;
>> +
>> +	dev->trans_start = jiffies;
>> +	if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
>> +		netif_stop_queue(dev);
>> +	spin_unlock_irq(&np->lock);
>> +	writel(NVREG_TXRXCTL_KICK, get_hwbase(dev) + NvRegTxRxControl);
>
>need pci_push() here?
>  
>
Ok.

>> +	/* 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.
>  
>
What is the xxx_kfree_skb_xxx function that just works?

>> +		/*
>> +		 * 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.
>  
>
Just guessing - it shouldn't hurt. CPU usage won't be important until 
nForce supports GigE. Should I remove it for now?

>> +/*
>> + * 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?
>
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.

>bug #2:  need a minimum bound for the MTU as well
>  
>
What is the minimum MTU? I remember a flamewar lkml about 200 byte MTU 
for noisy radio links.

>bug:  netif_carrier_xxx not unconditionally initialized in open()
>  
>
Ok.

>Further, I would really prefer that you use the lib functions in 
>drivers/net/mii.c instead of re-coding this stuff from scratch.
>  
>
Merging is on my TODO list.

>> +	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
>  
>
What causes 0xfffffff? Hotplug? I think the irq handler could leave 
immediately if a reserved bit is set. I'll add that.

>Don't reimplement NAPI yourself ;-(  this is just duplicating kernel 
>code....  in a worse fashion.  At least NAPI can load balance using an 
>idea of overall system load, not just load on a single NIC.
>
>  
>
This is not NAPI: on some hardware, the irq bit remained stuck on, 
forever. Instant lock-up. The code is a workaround against that. I'd 
like to leave that in - we get a good bug report, instead of a system 
that doesn't boot.

>> +		id2 = mii_rw(dev, i, MII_PHYSID2, MII_READ);
>> +		if (id2 < 0)
>> +			continue;
>
>also check for 0xffff returned from h/w
>  
>
Ok.

>> +	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
>
>  
>
MII id 0 a valid mii address? Or is that broadcast to all?

>> +	if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0) {
>> +		writel(NVREG_POWERSTATE_POWEREDUP|i, base + NvRegPowerState);
>> +	}
>
>style:  useless brackets
>  
>
Ok.

>> +
>> +	spin_lock_irq(&np->lock);
>> +	np->in_shutdown = 1;
>> +	spin_unlock_irq(&np->lock);
>> +	synchronize_irq(dev->irq);
>
>bug:  eliminate in_shutdown, and directly test netif_running() elsewhere 
>in code.  Again, re-implementing something the net stack already did for 
>you :)
>  
>
I'll check if I can use netif_running.

>> +	np->rx_ring = pci_alloc_consistent(pci_dev, sizeof(struct ring_desc) * (RX_RING + \
>> TX_RING), +						&np->ring_addr);
>> +	if (!np->rx_ring)
>> +		goto out_unmap;
>
>to avoid wasting memory, rx ring should be allocated at ->open() time, 
>and freed at ->close() time.  Otherwise this just reserves memory 
>needlessly when the interface is down.
>  
>
Ok.

>> +out_freering:
>> +	pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
>> +				np->rx_ring, np->ring_addr);
>> +out_unmap:
>> +	iounmap(get_hwbase(dev));
>> +out_relreg:
>> +	pci_release_regions(pci_dev);
>> +out_disable:
>> +	pci_disable_device(pci_dev);
>> +out_free:
>> +	free_netdev(dev);
>> +	pci_set_drvdata(pci_dev, NULL);
>> +out:
>
>The order here is weird...  when unwinding, pci_set_drvdata() call 
>should be first, before pci_free_consistent()
>  
>
Ok.

>> +static int __init init_nic(void)
>> +{
>> +	printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version \
>> %s.\n", FORCEDETH_VERSION); +	return pci_module_init(&driver);
>> +}
>
>minor bug:  for built-in drivers, only print version if you actually 
>found an interface.  For modular drivers, the above is fine.
>
>That's why you see 'printed_version' logic in various net drivers.
>
Ok.

--
    Manfred



             reply	other threads:[~2004-01-24 18:54 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-01-24 18:53 Manfred Spraul [this message]
2004-01-24 20:21 ` [PATCH] [2.4] forcedeth network driver Jeff Garzik
2004-01-24 21:55   ` Carl-Daniel Hailfinger
2004-01-24 23:57     ` Jeff Garzik
2004-01-24 22:05   ` Vojtech Pavlik
2004-01-24 22:33     ` Carl-Daniel Hailfinger
2004-01-24 22:46       ` Vojtech Pavlik
2004-01-24 23:11         ` Paul Mackerras
2004-01-27 13:30   ` Rask Ingemann Lambertsen
  -- strict thread matches above, loose matches on Subject: below --
2004-02-05  0:52 Carl-Daniel Hailfinger
2004-02-05  9:45 ` Jeff Garzik
2004-01-24 17:11 Carl-Daniel Hailfinger
2004-01-24 17:58 ` Jeff Garzik
2004-01-24 21:24   ` Carl-Daniel Hailfinger
2004-01-25  0:01     ` Jeff Garzik
2004-01-24 18:59 ` Francois Romieu
2004-01-24 19:02   ` Manfred Spraul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4012BF44.9@colorfullife.com \
    --to=manfred@colorfullife.com \
    --cc=c-d.hailfinger.kernel.2004@gmx.net \
    --cc=jgarzik@pobox.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.