Re: weired NE2K ether problem - help!

From: Jun Sun (jsun@mvista.com)
Date: Mon Jul 31 2000 - 18:41:04 EST


Paul,

Your patch did not really solve the problem - the kernel failed in some
place else. Looking into the matter only gets me more confused about
the skb stuff.

It failed in sending out the first bootp packet.
 
static void __init ic_bootp_send_if(struct ic_device *d, u32 jiffies)
{
        int hh_len = (dev->hard_header_len + 15) & ~15;

        /* Allocate packet */
        skb = alloc_skb(sizeof(struct bootp_pkt) + hh_len + 15, GFP_KERNEL);
        if (!skb)
                return;
        skb_reserve(skb, hh_len);
...

Here the dev->hard_header_len is 14 bytes, and hh_len becomes 16. So
after skb_reserve(skb, hh_len) function call, skb->data is aligned along
4-byte boundary.

However, right before the packet is sent, eth_header() function is
called, which copies the 14 bytes ether header (including mac address)
before skb->data, AND substracts skb->data by 14. This perfectly makes
skb->data off 4-byte boundary and causes a bus error in
ei_block_output() when the driver tries to send it out.

Again, I am not a network guru, and I cannot tell where things exactly
go wrong. But I do know someone is to blame here. :-) Any help?

Jun

P.S., is there explanation about the whole skb stuff? What is policy
regarding how skb->data is manipulated and how it should be aligned? To
me it just looks a big black magic uglily scattered around net driver
code ...

Paul Gortmaker wrote:
>
> Jun Sun wrote:
>
> >
> > BTW, I believe I have already found one bug in ne2k-pci.c. The bug
> > is in ne2k_pci_block_input() and ne2k_pci_block_output(). The code
> > checks if ONLY_16BIT_IO is set or not. If not, it will try to read/write
> > using 32bit mode, into/from the buffer (skb->data). However,
> > skb->data is NOT aligned along 4-byte boundary (See related sbk_reserve(2)
> > calls in 8390.c). This causes bus error on my MIPS board.
> >
> > What should be the right fix? I currently use a separate buffer, which is
> > aligned along 4-byte boundary, to copy into/from skb->data to do the IO.
> > Obviously, this is not good.
> >
> > I also tried to change from skb_reserve(2) skb_reserve(4). That seems
> > to causes some other problem. (OK, I admit I am quite ignorant about
> > ether driver.)
>
> The reserve of 2 is because src addr(6) + dst addr(6) + type code(2)=14.
> Adding 2 makes it an even 16 to the start of of the IP header.
>
> In your case you may need to test with something like this.
>
> Paul.
>
> --- drivers/net/8390.c~ Sat Jul 22 12:59:17 2000
> +++ drivers/net/8390.c Wed Jul 26 16:59:38 2000
> @@ -739,7 +739,7 @@
> {
> struct sk_buff *skb;
>
> - skb = dev_alloc_skb(pkt_len+2);
> + skb = dev_alloc_skb(pkt_len+4);
> if (skb == NULL)
> {
> if (ei_debug > 1)
> @@ -750,7 +750,8 @@
> }
> else
> {
> - skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
> + unsigned long offset = (((unsigned long)(skb->data) + 3) & ~3UL) - (unsigned long)(skb->data);
> + skb_reserve(skb,offset);
> skb->dev = dev;
> skb_put(skb, pkt_len); /* Make room */
> ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Jul 31 2000 - 21:00:35 EST