From: linux@horizon.com
To: linux@horizon.com, romieu@fr.zoreil.com
Cc: akpm@linux-foundation.org, davem@davemloft.net, netdev@vger.kernel.org
Subject: ipg.c bugs
Date: 10 Jan 2008 02:28:09 -0500 [thread overview]
Message-ID: <20080110072809.1473.qmail@science.horizon.com> (raw)
In-Reply-To: <20080109233056.GA5673@electric-eye.fr.zoreil.com>
I'm just about to test that second memory leak patch, but I gave the
original code a careful reading, and found a few problems:
* Huge monstrous glaring bug
In ipg_interrupt_handler the code to habdle a shared interrupt
not caused by this device:
if (!(status & IPG_IS_RSVD_MASK))
goto out_enable
is *before* spin_lock(&sp->lock), but the code following
out_enable does spin_unlock(&sp->lock).
Thus, the sp->lock is all f*ed up. The lack of any sort of
locking between the interrupt handler and hard_start_xmit
could cause all sort of issues.
I'm not actually sure if it's even necessary; I'd think some
suitable atomic access to sp->tx_current would suffice.
* Lesser bugs
There's a general pattern of loops over the range from
s->rx_current to sp->rx_dirty. Some of them are call code
that refers to s->rx_current, even though that hasn't been
updated yet.
One instance is in ipg_nic_check_frame_type.
A second is in ipg_nic_check_error.
In ipg_nic_set_multicast(), the code to enable the multicast flags
is of the form "if (dev->flags & IFF_MULTICAST & (dev->mc_count > ...))".
But IFF_MULTI CAST is not 1, so this will always be false.
The seond & needs to be && (2x).
In ipg_io_config(), there's
/* Transmitter and receiver must be disabled before setting
* IFSSelect.
*/
ipg_w32((origmacctrl & (IPG_MC_RX_DISABLE | IPG_MC_TX_DISABLE)) &
IPG_MC_RSVD_MASK, MAC_CTRL);
I don't know what's going on there, but unless the IPG_MC_RX_DISABLE
bit is already set in origmacctrl, that's going to write 0, which
won't disable anything.
Immediately following, there's some similarly buggy code doing something
I don't understand with IPG_MC_IFS_96BIT.
The setting of curr in ipg_nic_txfree, with that bizarre do_div, can't
possibly be working right.
* Possible bugs
I'm not very sanguine about the handling in init_rfdlist, of the
code that handles a failed ipg_get_rxbuff. In particular, it leaves
rxfd->frag_info uninitialized in that case, but does set rxfd->rfs to
"buffer ready to be received into", which could lead to receiving into
random memory locations.
In ipg_nic_hard_start_xmit(), the code
if (sp->tx_current == (sp->tx_dirty + IPG_TFDLIST_LENGTH))
netif_wake_queue(dev);
shouldn't that *stop* the queue if the TFDLIST is full?
I think that the places where the rxfd->rfs and txfd->tfc fields
are filled in (containing the hardware-handoff flag) should
have memory barriers.
* Stupid code
In ipg_io_config, there are three writes to DEBUG_CTRL "Per silicon
B3 eratta". First, that's "errata". But more significantly,
can those writes be combined into one? Is it necessary to read
the DEBUG_CTRL register each time?
The initialization of rxfd->rfs in init_rfdlist() and ipg_nix_rxrestore()
should be moved into ipg_get_rxbuf(). And since the ready bit is there,
it should be set AFTER the pointer fields AND there should be a barrier
so the hardware doesn't read the fields out of order.
In ipg_nic_txcleanup(), there's code to call netif_wake_queue every
time through the loop in 10 MBit mode (to balance some bug-workaround
call that stops the queue every packet in that case), which is
quite unnecessary, as ipg_nic_txfree() will do it.
The IPG_INSERT_MANUAL_VLAN_TAG code (fortunately disabled by default)
is just plain bizarre. What exactly is the use of assigning a tag of
0xABC to every packet?
The code in ipg_hw_init to set up dev->dev_addr reads each of the
16-bit address reigsters twice, for no apparent reason.
There's a lots of code in e.g. ipg_nic_rx() that does endless
manipulation of rxfd->rfs with an le64_to_cpu() call around each
instance, that should copy it to a CPU-ordered native value and be
done with it. (Some sparse annotations would help, too.)
Likewise for messing with txfd->tfc in ipg_nic_hard_start_xmit().
The Frame_WithEnd enum is a very strange value (decimal 10) to use as
a bitmapped status flag.
The four frame fragment functions
nic_rx_with_start_and_end
nic_rx_with_start
nic_rx_with_end
nic_rx_so_start_no_end
could easily be unified into one.
* Performance left on the floor
The hardware supports scallter/gather, hardware checksums, VLAN tagging,
and 64-bit (well, 40-bit) DMA, but the driver sets no feature flags.
The jumbo frame reception code could generate fragmented skbs rather
that doing all those memcopies.
Would it be worth splitting the 64-bit ->rfs and ->txc fields into
two 32-bit fields?
Would it be worth copying small incoming packets to small skbs and
keeping the large skb in the receive queue?
* Questions
In net_device_stats, are all those statistics registers cleared by
a read?
How do we determine the silicon revision numbers, so we can stop enabling
bug workarounds on versions that don't need it?
Where can I find docs about the scatter/gather features? The bitfield
definitions are a bit vague.
prev parent reply other threads:[~2008-01-10 7:29 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-28 2:06 2.6.23-rc8 network problem. Mem leak? ip1000a? linux
2007-09-28 9:20 ` Andrew Morton
2007-09-30 7:59 ` linux
2007-09-30 9:23 ` Andrew Morton
2007-09-30 11:40 ` linux
2008-01-08 6:52 ` linux
2008-01-08 7:07 ` David Miller
2008-01-08 7:14 ` David Miller
2008-01-08 7:51 ` Francois Romieu
2008-01-08 12:28 ` [PATCH 1/3] drivers/net/ipg.c: Fix skbuff leak linux
2008-01-08 13:19 ` linux
2008-01-08 21:36 ` Francois Romieu
2008-01-08 23:00 ` David Miller
2008-01-08 23:28 ` Francois Romieu
2008-01-09 0:38 ` linux
2008-01-09 8:39 ` David Miller
2008-01-09 23:34 ` Francois Romieu
2008-01-09 23:56 ` David Miller
2008-01-09 23:30 ` Francois Romieu
2008-01-10 7:28 ` linux [this message]
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=20080110072809.1473.qmail@science.horizon.com \
--to=linux@horizon.com \
--cc=akpm@linux-foundation.org \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
--cc=romieu@fr.zoreil.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).