]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.24-rc3 2.2.24-rc3
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:24:37 +0000 (15:24 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:24:37 +0000 (15:24 -0500)
o   Backport the ethernet padding fixes             (Alan Cox)
    | All done except 8139too, rtl8139]

39 files changed:
Makefile
drivers/net/3c501.c
drivers/net/3c505.c
drivers/net/3c507.c
drivers/net/3c523.c
drivers/net/3c527.c
drivers/net/7990.c
drivers/net/82596.c
drivers/net/8390.c
drivers/net/a2065.c
drivers/net/am79c961a.c
drivers/net/ariadne.c
drivers/net/at1700.c
drivers/net/atarilance.c
drivers/net/atp.c
drivers/net/bagetlance.c
drivers/net/de600.c
drivers/net/de620.c
drivers/net/declance.c
drivers/net/depca.c
drivers/net/eepro.c
drivers/net/eexpress.c
drivers/net/epic100.c
drivers/net/eth16i.c
drivers/net/fmv18x.c
drivers/net/hp100.c
drivers/net/lance.c
drivers/net/lp486e.c
drivers/net/ni5010.c
drivers/net/ni52.c
drivers/net/ni65.c
drivers/net/seeq8005.c
drivers/net/sgiseeq.c
drivers/net/sk_g16.c
drivers/net/smc9194.c
drivers/net/via-rhine.c
drivers/net/znet.c
include/linux/skbuff.h
net/core/skbuff.c

index fd26aed5d48e0f73ccb18883fd85debdcb56ec17..a5fa1980fc790e3e343a4c2302a2a3bd55f70ac3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 24
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index 6c2a672ec3920ab7d9d3d88430999324bf77ecdd..05c6498bd244e5998ddf650f41b517533dc00b9b 100644 (file)
@@ -422,8 +422,15 @@ static int el_start_xmit(struct sk_buff *skb, struct device *dev)
        }
        else
        {
-               int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
+               int len = skb->len;
+               int pad = 0;
+               int gp_start;
                unsigned char *buf = skb->data;
+               
+               if(len < ETH_ZLEN)
+                       pad = ETH_ZLEN - len;
+                       
+               gp_start = 0x800 - ( len + pad );
 
 load_it_again_sam:
                lp->tx_pkt_start = gp_start;
@@ -451,7 +458,12 @@ load_it_again_sam:
                
                outw(0x00, RX_BUF_CLR);         /* Set rx packet area to 0. */
                outw(gp_start, GP_LOW);         /* aim - packet will be loaded into buffer start */
-               outsb(DATAPORT,buf,skb->len);   /* load buffer (usual thing each byte increments the pointer) */
+               outsb(DATAPORT,buf,len);        /* load buffer (usual thing each byte increments the pointer) */
+               if(pad)
+               {
+                       while(pad--)            /* Zero fill buffer tail */
+                               outb(0, DATAPORT);
+               }
                outw(gp_start, GP_LOW);         /* the board reuses the same register */
 
                if(lp->loading==2)              /* A receive upset our load, despite our best efforts */
index ac681944605072b70ffa103543d50d31661e5f33..b4ec16d3bcb81114e4ef764c16584684b3a147d9 100644 (file)
@@ -1062,8 +1062,9 @@ static int send_packet(struct device *dev, struct sk_buff *skb)
        adapter->current_dma.direction = 1;
        adapter->current_dma.start_time = jiffies;
 
-       if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS) {
-               memcpy(adapter->dma_buffer, skb->data, nlen);
+       if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) {
+               memcpy(adapter->dma_buffer, skb->data, skb->len);
+               memset(adapter->dma_buffer+skb->len, 0, nlen-skb->len);
                target = virt_to_bus(adapter->dma_buffer);
        }
        else {
index 8d6e20ccce7efa93f42b97770b7f47db3a9e3de1..50030a0a89d1c8da7e86d5de77919b1ba2da95bb 100644 (file)
@@ -290,7 +290,7 @@ static void el16_rx(struct device *dev);
 static int     el16_close(struct device *dev);
 static struct net_device_stats *el16_get_stats(struct device *dev);
 
-static void hardware_send_packet(struct device *dev, void *buf, short length);
+static void hardware_send_packet(struct device *dev, void *buf, short length, short pad);
 static void init_82586_mem(struct device *dev);
 
 \f
@@ -495,10 +495,10 @@ static int el16_send_packet(struct sk_buff *skb, struct device *dev)
                outb(0x80, ioaddr + MISC_CTRL);
 #ifdef CONFIG_SMP
                spin_lock_irqsave(&lp->lock, flags);
-               hardware_send_packet(dev, buf, length);
+               hardware_send_packet(dev, buf, skb->len, length - skb->len);
                spin_unlock_irqrestore(&lp->lock, flags);
 #else
-               hardware_send_packet(dev, buf, length);
+               hardware_send_packet(dev, buf, skb->len, length - skb->len);
 #endif         
                dev->trans_start = jiffies;
                /* Enable the 82586 interrupt input. */
@@ -758,12 +758,13 @@ static void init_82586_mem(struct device *dev)
        return;
 }
 
-static void hardware_send_packet(struct device *dev, void *buf, short length)
+static void hardware_send_packet(struct device *dev, void *buf, short length, short pad)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
        short ioaddr = dev->base_addr;
        ushort tx_block = lp->tx_head;
        unsigned long write_ptr = dev->mem_start + tx_block;
+       static char padding[ETH_ZLEN];
 
        /* Set the write pointer to the Tx block, and put out the header. */
        writew(0x0000,write_ptr);                       /* Tx status */
@@ -772,7 +773,7 @@ static void hardware_send_packet(struct device *dev, void *buf, short length)
        writew(tx_block+8,write_ptr+=2);                        /* Data Buffer offset. */
 
        /* Output the data buffer descriptor. */
-       writew(length | 0x8000,write_ptr+=2);           /* Byte count parameter. */
+       writew((pad + length) | 0x8000,write_ptr+=2);   /* Byte count parameter. */
        writew(-1,write_ptr+=2);                        /* No next data buffer. */
        writew(tx_block+22+SCB_BASE,write_ptr+=2);      /* Buffer follows the NoOp command. */
        writew(0x0000,write_ptr+=2);                    /* Buffer address high bits (always zero). */
@@ -784,6 +785,8 @@ static void hardware_send_packet(struct device *dev, void *buf, short length)
 
        /* Output the packet at the write pointer. */
        memcpy_toio(write_ptr+2, buf, length);
+       if(pad)
+               memcpy_toio(write_ptr+length+2, padding, pad);
 
        /* Set the old command link pointing to this send packet. */
        writew(tx_block,dev->mem_start + lp->tx_cmd_link);
index b010a95093e0d57bac690417851313a6a569d0aa..1dee4227198a97c39bf43a6b8be6e4ce89ce16e4 100644 (file)
@@ -1118,8 +1118,10 @@ static int elmc_send_packet(struct sk_buff *skb, struct device *dev)
        if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
                printk("%s: Transmitter access conflict.\n", dev->name);
        } else {
-               memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
                len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+               if(len != skb->len)
+                       memset((char *) p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN);
+               memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
 
 #if (NUM_XMIT_BUFFS == 1)
 #ifdef NO_NOPCOMMANDS
index 5a155d45b18b1e253c11c48c84a375aec7a70554..9b7ab67e5f325d88750a93154d6a8e13d10acb18 100644 (file)
@@ -1087,6 +1087,12 @@ static int mc32_send_packet(struct sk_buff *skb, struct device *dev)
                /* We will need this to flush the buffer out */
                lp->tx_ring[lp->tx_ring_head].skb=skb;
           
+               if(skb->len < ETH_ZLEN)
+               {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if(skb == NULL)
+                               goto out;
+               }
                np->length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; 
                        
                np->data        = virt_to_bus(skb->data);
@@ -1096,6 +1102,7 @@ static int mc32_send_packet(struct sk_buff *skb, struct device *dev)
                
                p->control     &= ~CONTROL_EOL;     /* Clear EOL on p */ 
           
+out:
                        dev->tbusy      = 0;           /* Keep feeding me */            
        
                restore_flags(flags);
index 1991659f007146673912cedc7ff3c3e32a83c186..a0a6c0a3cab17783eca87dbd10bc7a5ab8637649 100644 (file)
@@ -542,6 +542,8 @@ int lance_start_xmit (struct sk_buff *skb, struct device *dev)
         ib->btx_ring [entry].length = (-len) | 0xf000;
         ib->btx_ring [entry].misc = 0;
     
+       if(skb->len < ETH_ZLEN)
+               memset((char *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
         memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen);
     
         /* Now, give the packet to the lance */
index 720d10fb2c65a6b91608063100d6b730ada72143..6e6fe2cb082bf2c6da29d57efd0253e78f64fac1 100644 (file)
@@ -1045,9 +1045,19 @@ static int i596_start_xmit(struct sk_buff *skb, struct device *dev)
        if (test_and_set_bit(0, (void *) &dev->tbusy) != 0)
                printk("%s: Transmitter access conflict.\n", dev->name);
        else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+               short length = skb->len;
                dev->trans_start = jiffies;
 
+               if(skb->len < ETH_ZLEN)
+               {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if(skb == NULL)
+                       {
+                               dev->tbusy = 0;
+                               return 0;
+                       }
+                       length = ETH_ZLEN;
+               }
                tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
                tbd = lp->tbds + lp->next_tx_cmd;
 
index 5ce7fbc3d5db1d45f00a98d979619bc805eb858f..a2ea9d32fad5916dacb2deaba93b950a90a196f9 100644 (file)
@@ -196,6 +196,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
        struct ei_device *ei_local = (struct ei_device *) dev->priv;
        int length, send_length, output_page;
        unsigned long flags;
+       char scratch[ETH_ZLEN];
 
        /*
         *  We normally shouldn't be called if dev->tbusy is set, but the
@@ -348,8 +349,16 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
         * isn't already sending. If it is busy, the interrupt handler will
         * trigger the send later, upon receiving a Tx done interrupt.
         */
-
-       ei_block_output(dev, length, skb->data, output_page);
+        
+       if(length == send_length)
+               ei_block_output(dev, length, skb->data, output_page);
+       else
+       {
+               memset(scratch, 0, ETH_ZLEN);
+               memcpy(scratch, skb->data, skb->len);
+               ei_block_output(dev, ETH_ZLEN, scratch, output_page);
+       }
+               
        if (! ei_local->txing) 
        {
                ei_local->txing = 1;
@@ -378,7 +387,14 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
         * reasonable hardware if you only use one Tx buffer.
         */
 
-       ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
+       if(length == send_length)
+               ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
+       else
+       {
+               memset(scratch, 0, ETH_ZLEN);
+               memcpy(scratch, skb->data, skb->len);
+               ei_block_output(dev, ETH_ZLEN, scratch, ei_local->tx_start_page);
+       }
        ei_local->txing = 1;
        NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
        dev->trans_start = jiffies;
index 88cd287494206ae036818ffa39d12256a77abb13..ee4b4dcc71607674419b591d7a1cfb7368d77c43 100644 (file)
@@ -594,7 +594,16 @@ static int lance_start_xmit (struct sk_buff *skb, struct device *dev)
        }
 
        skblen = skb->len;
-
+       len = skblen;
+       
+       if(len < ETH_ZLEN)
+       {
+               len = ETH_ZLEN;
+               skb = skb_padto(skb, ETH_ZLEN);
+               if(skb == NULL)
+                       return 0;
+       }
        save_flags(flags);
        cli();
 
@@ -615,7 +624,6 @@ static int lance_start_xmit (struct sk_buff *skb, struct device *dev)
                }
        }
 #endif
-       len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
        entry = lp->tx_new & lp->tx_ring_mod_mask;
        ib->btx_ring [entry].length = (-len) | 0xf000;
        ib->btx_ring [entry].misc = 0;
index 92f1dbd59b85c59c3115e5cfdca72ac3a5709158..7c82c44ae179caef761dff32936bb8a94a5c092c 100644 (file)
@@ -524,11 +524,24 @@ am79c961_sendpacket(struct sk_buff *skb, struct device *dev)
        if (!dev->tbusy) {
 again:
                if (!test_and_set_bit(0, (void*)&dev->tbusy)) {
-                       unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+                       unsigned int length = skb->len;
                        unsigned int hdraddr, bufaddr;
                        unsigned int head;
                        unsigned long flags;
 
+
+                       /* FIXME: I thought the 79c961 could do padding - RMK ??? */
+                       if(length < ETH_ZLEN)
+                       {
+                               skb = skb_padto(skb, ETH_ZLEN);
+                               if(skb == NULL)
+                               {
+                                       dev->tbusy = 0;
+                                       return 0;
+                               }
+                               length = ETH_ZLEN;
+                       }
                        head = priv->txhead;
                        hdraddr = priv->txhdr + (head << 3);
                        bufaddr = priv->txbuffer[head];
index 92075a95f92f03ee112d349a33266fb3d5ee7310..3d878256bd8b2f38b860e46ca4ed9a7d34faf330 100644 (file)
@@ -547,6 +547,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct device *dev)
     struct AriadneBoard *board = priv->board;
     int entry;
     unsigned long flags;
+    int len = skb->len;
 
     /* Transmitter timeout, serious problems. */
     if (dev->tbusy) {
@@ -608,6 +609,18 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct device *dev)
     }
 
     /* Fill in a Tx ring entry */
+    /* FIXME: is the 79C960 new enough to do its own padding right ? */
+    if(skb->len < ETH_ZLEN)
+    {
+       skb = skb_padto(skb, ETH_ZLEN);
+       if(skb == NULL)
+       {
+           dev->tbusy = 0;
+           return 0;
+       }
+       len = ETH_ZLEN;
+    }
++
 
 #if 0
     printk("TX pkt type 0x%04x from ", ((u_short *)skb->data)[6]);
@@ -637,7 +650,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct device *dev)
 
     priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
     priv->tx_ring[entry]->TMD3 = 0x0000;
-    memcpyw(priv->tx_buff[entry], (u_short *)skb->data, skb->len);
+    memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
 
 #if 0
     {
index 0acbfc09d48de49f0cce7db69ebf93d03adc5c62..50d0a53d53db05a1cc72b10c2b83654da57231e5 100644 (file)
@@ -576,7 +576,8 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
                printk("%s: Transmitter access conflict.\n", dev->name);
        else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+               short length = skb->len;
+               static u8 pad[ETH_ZLEN];
                unsigned char *buf = skb->data;
 
                /* We may not start transmitting unless we finish transferring
@@ -587,7 +588,17 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
                lp->tx_queue_ready = 0;
                {
                        outw(length, ioaddr + DATAPORT);
+                       /* Packet data */
                        outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+                       /* Check for dribble byte */
+                       if(length & 1)
+                       {
+                               outw(skb->data[skb->len-1], ioaddr + DATAPORT);
+                               length--;
+                       }
+                       /* Check for packet padding */
+                       if(length != skb->len)
+                               outsw(ioaddr + DATAPORT, pad, (length - skb->len + 1) >> 1);
 
                        lp->tx_queue++;
                        lp->tx_queue_len += length + 2;
index c79fd581e0a1b4f69c6f3459a4625ad6e541c5a8..888a7e40ab5390506daa321dec7a9b4ef7867c7a 100644 (file)
@@ -766,6 +766,21 @@ static int lance_start_xmit( struct sk_buff *skb, struct device *dev )
        DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
                                  dev->name, DREG ));
 
+       /* The old LANCE chips doesn't automatically pad buffers to min. size. */
+       len = skb->len;
+       if(len < ETH_ZLEN)
+               len = ETH_ZLEN;
+       /* PAM-Card has a bug: Can only send packets with even number of bytes! */
+       else if (lp->cardtype == PAM_CARD && (len & 1))
+               ++len;
+               
+       if(len > skb->len)
+       {
+               skb = skb_padto(skb, len);
+               if(skb == NULL)
+                       return 0;
+       }
+               
        /* Block a timer-based transmit from overlapping.  This could better be
           done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
        if (test_and_set_bit( 0, (void*)&dev->tbusy ) != 0) {
@@ -807,12 +822,6 @@ static int lance_start_xmit( struct sk_buff *skb, struct device *dev )
         * last.
         */
 
-       /* The old LANCE chips doesn't automatically pad buffers to min. size. */
-       len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
-       /* PAM-Card has a bug: Can only send packets with even number of bytes! */
-       if (lp->cardtype == PAM_CARD && (len & 1))
-               ++len;
-
        head->length = -len;
        head->misc = 0;
        lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
index 89ca21cfea95cd38b98838ed6c8b50e727a3c56b..9cb6a193c5968defb7bb062e9a3b8a90b2497c2d 100644 (file)
@@ -133,7 +133,7 @@ static void get_node_ID(struct device *dev);
 static unsigned short eeprom_op(short ioaddr, unsigned int cmd);
 static int net_open(struct device *dev);
 static void hardware_init(struct device *dev);
-static void write_packet(short ioaddr, int length, unsigned char *packet, int mode);
+static void write_packet(short ioaddr, int length, unsigned char *packet, int pad, int mode);
 static void trigger_send(short ioaddr, int length);
 static int     net_send_packet(struct sk_buff *skb, struct device *dev);
 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -381,15 +381,23 @@ static void trigger_send(short ioaddr, int length)
        write_reg(ioaddr, CMR1, CMR1_Xmit);
 }
 
-static void write_packet(short ioaddr, int length, unsigned char *packet, int data_mode)
+static void write_packet(short ioaddr, int length, unsigned char *packet, int pad_len, int data_mode)
 {
-    length = (length + 1) & ~1;                /* Round up to word length. */
+    if(length & 1)
+    {
+       length++;
+       pad_len++;
+    }
+
     outb(EOC+MAR, ioaddr + PAR_DATA);
     if ((data_mode & 1) == 0) {
                /* Write the packet out, starting with the write addr. */
                outb(WrAddr+MAR, ioaddr + PAR_DATA);
                do {
                        write_byte_mode0(ioaddr, *packet++);
+               } while (--length > pad_len) ;
+               do {
+                       write_byte_mode0(ioaddr, 0);
                } while (--length > 0) ;
     } else {
                /* Write the packet out in slow mode. */
@@ -403,8 +411,10 @@ static void write_packet(short ioaddr, int length, unsigned char *packet, int da
                outbyte >>= 4;
                outb(outbyte & 0x0f, ioaddr + PAR_DATA);
                outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
-               while (--length > 0)
+               while (--length > pad_len)
                        write_byte_mode1(ioaddr, *packet++);
+               while (--length > 0)
+                       write_byte_mode1(ioaddr, 0);
     }
     /* Terminate the Tx frame.  End of write: ECB. */
     outb(0xff, ioaddr + PAR_DATA);
@@ -450,7 +460,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
                write_reg_high(ioaddr, IMR, 0);
                restore_flags(flags);
 
-               write_packet(ioaddr, length, buf, dev->if_port);
+               write_packet(ioaddr, length, buf, length-skb->len, dev->if_port);
 
                lp->pac_cnt_in_tx_buf++;
                if (lp->tx_unit_busy == 0) {
index 5a6f8fd4aecdb9cf381d3727b89550dd2056552c..8e7bc16331d626ae7a933ca8cd8fc7519d26d6c5 100644 (file)
@@ -831,6 +831,19 @@ static int lance_start_xmit( struct sk_buff *skb, struct device *dev )
        struct lance_tx_head *head;
        unsigned long flags;
 
+       /* The old LANCE chips doesn't automatically pad buffers to min. size. */
+       len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+       /* PAM-Card has a bug: Can only send packets with even number of bytes! */
+       if (lp->cardtype == PAM_CARD && (len & 1))
+               ++len;
+
+       if (len > skb->len)
+       {
+               skb = skb_padto(skb, len);
+               if(skb == NULL)
+                       return 0;
+       }       
+
        /* Transmitter timeout, serious problems. */
        if (dev->tbusy) {
                int tickssofar = jiffies - dev->trans_start;
@@ -917,12 +930,6 @@ static int lance_start_xmit( struct sk_buff *skb, struct device *dev )
         * last.
         */
 
-       /* The old LANCE chips doesn't automatically pad buffers to min. size. */
-       len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
-       /* PAM-Card has a bug: Can only send packets with even number of bytes! */
-       if (lp->cardtype == PAM_CARD && (len & 1))
-               ++len;
-
        head->length = -len;
        head->misc = 0;
        lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
index 03a3205ed8a45a84dcc60b9767dedf7b39bfe17f..593d50d4f353ae4a815f46fea1b3361ccd972f0d 100644 (file)
@@ -404,6 +404,7 @@ de600_start_xmit(struct sk_buff *skb, struct device *dev)
        int     len;
        int     tickssofar;
        byte    *buffer = skb->data;
+       int     i;
 
        if (free_tx_pages <= 0) {       /* Do timeouts, to avoid hangs. */
                tickssofar = jiffies - dev->trans_start;
@@ -447,8 +448,10 @@ de600_start_xmit(struct sk_buff *skb, struct device *dev)
 #endif
 
        de600_setup_address(transmit_from, RW_ADDR);
-       for ( ; len > 0; --len, ++buffer)
+       for (i = 0;  i < skb->len ; ++i, ++buffer)
                de600_put_byte(*buffer);
+       for (; i < len; ++i)
+               de600_put_byte(0);
 
        if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */
                dev->trans_start = jiffies;
index 80d7a119133b2a828cb8c4f657ee37e49ed8baea..297c2be9ba8d3ee958e5b8370aaec2001cf58def 100644 (file)
@@ -310,7 +310,7 @@ de620_read_byte(struct device *dev)
 }
 
 static inline void
-de620_write_block(struct device *dev, byte *buffer, int count)
+de620_write_block(struct device *dev, byte *buffer, int count, int pad)
 {
 #ifndef LOWSPEED
        byte uflip = NIC_Cmd ^ (DS0 | DS1);
@@ -329,6 +329,9 @@ de620_write_block(struct device *dev, byte *buffer, int count)
        for ( ; count > 0; --count, ++buffer) {
                de620_put_byte(dev,*buffer);
        }
+       for ( count = pad ; count > 0; --count, ++buffer) {
+               de620_put_byte(dev, 0);
+       }
        de620_send_command(dev,W_DUMMY);
 #ifdef COUNT_LOOPS
        /* trial debug output: loops per byte in de620_ready() */
@@ -570,7 +573,7 @@ de620_start_xmit(struct sk_buff *skb, struct device *dev)
                return 1;
                break;
        }
-       de620_write_block(dev, buffer, len);
+       de620_write_block(dev, buffer, skb->len, len-skb->len);
 
        dev->trans_start = jiffies;
        dev->tbusy = (using_txbuf == (TXBF0 | TXBF1)); /* Boolean! */
index b0183061c8d1b19874bbd527ebd98608bfbcdffd..780458e366c8cc8d55be50ddfbeba12a5ea6f299 100644 (file)
@@ -873,12 +873,23 @@ static int lance_start_xmit(struct sk_buff *skb, struct device *dev)
                return -1;
        }
        skblen = skb->len;
+       len = skblen;
+       
+       if(len < ETH_ZLEN)
+       {
+               skb = skb_padto(skb, ETH_ZLEN);
+               if(skb == NULL)
+               {
+                       dev->tbusy = 0;
+                       return 0;
+               }
+               len = ETH_ZLEN;
+       }
        save_and_cli(flags);
        if (!TX_BUFFS_AVAIL) {
                restore_flags(flags);
                return -1;
        }
-       len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
 
        lp->stats.tx_bytes += len;
 
index 6062a282fd7a73fabbd2c895cef0b00b3816b984..b6a596af52857f9957a6170dcf42d0f4e95c7d42 100644 (file)
@@ -836,6 +836,13 @@ static int depca_start_xmit(struct sk_buff *skb, struct device *dev)
                }
                return status;
        } else if (skb->len > 0) {
+               if(skb->len < ETH_ZLEN)
+               {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if(skb == NULL)
+                               return 0;
+               }
+
                /* Enforce 1 process per h/w access */
                if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
                        printk("%s: Transmitter access conflict.\n", dev->name);
index 72859cb146081fb6a2aa13059e0b31895ae49c2f..b03bfc11db34ce31fc97531c1d2f778033751a62 100644 (file)
@@ -1067,12 +1067,21 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        int ioaddr = dev->base_addr;
+       short length = skb->len;
 
        unsigned long flags;
 
        if (net_debug > 5)
                printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
 
+       if(length < ETH_ZLEN)
+       {
+               skb = skb_padto(skb, ETH_ZLEN);
+               if(skb == NULL)
+                       return 0;
+               length = ETH_ZLEN;
+       }
+
        eepro_dis_int(ioaddr);
        spin_lock_irqsave(&lp->lock, flags);
 
@@ -1094,7 +1103,6 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
                printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
                lp->stats.tx_aborted_errors++;
        } else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 
                if (hardware_send_packet(dev, skb->data, length))
                        /* we won't unset tbusy because we're out of space. */
index 8e03023c9e311bb09e940748ef92af7b68107630..0fb3f94d900cd24627436a3a4531e33dec33fecc 100644 (file)
@@ -522,12 +522,21 @@ static void unstick_cu(struct device *dev)
 static int eexp_xmit(struct sk_buff *buf, struct device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
+       short length = buf->len;
        unsigned long flags;
 
 #if NET_DEBUG > 6
        printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
 #endif
 
+       if(buf->len < ETH_ZLEN)
+       {
+               buf = skb_padto(buf, ETH_ZLEN);
+               if(buf == NULL)
+                       return 0;
+               length = buf->len;
+       }
+
        disable_irq(dev->irq);
 
        /*
@@ -571,8 +580,6 @@ static int eexp_xmit(struct sk_buff *buf, struct device *dev)
        }
        else
        {
-               unsigned short length = (ETH_ZLEN < buf->len) ? buf->len :
-                       ETH_ZLEN;
                unsigned short *data = (unsigned short *)buf->data;
 
                lp->stats.tx_bytes += length;
index 445d72c6770c281de8ea1cd749aaf7ff2c60a61f..4571e06c48db1a2ea95e7ff8bff37469b4b629ee 100644 (file)
@@ -879,6 +879,13 @@ epic_start_xmit(struct sk_buff *skb, struct device *dev)
        int entry, free_count;
        u32 ctrl_word;
        long flags;
+       
+       if(skb->len < ETH_ZLEN)
+       {
+               skb = skb_padto(skb, ETH_ZLEN);
+               if(skb == NULL)
+                       return 0;
+       }
 
        /* Block a timer-based transmit from overlapping.  This could better be
           done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
index 0f6e95bb6365ffd51114fce2b235b64e37858716..6fc3d0b525a72d42157803680f49aadab83462f5 100644 (file)
@@ -1122,9 +1122,19 @@ static int eth16i_tx(struct sk_buff *skb, struct device *dev)
                status = -1;
        }
        else {
-               ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+               ushort length = skb->len;
                unsigned char *buf = skb->data;
 
+               if(length < ETH_ZLEN)
+               {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if(skb == NULL)
+                       {
+                               dev->tbusy = 0;
+                               return 0;
+                       }
+                       length = ETH_ZLEN;
+               }
                if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
                        if(eth16i_debug > 0) 
                                printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);  
index 749e1f1239c2a858eca2302cb68c1ed7d9c07a4d..ce6e8ff1e366275f4706c6ed324a7349a365b2f1 100644 (file)
@@ -369,7 +369,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
                printk("%s: Transmitter access conflict.\n", dev->name);
        else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+               short length = skb->len;
                unsigned char *buf = skb->data;
 
                if (length > ETH_FRAME_LEN) {
@@ -378,6 +378,17 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
                                        dev->name, length);
                        return 1;
                }
+       
+               if (length < ETH_ZLEN)
+               {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if(skb == NULL)
+                       {
+                               dev->tbusy = 0;
+                               return 0;
+                       }
+                       length = ETH_ZLEN;
+               }       
 
                if (net_debug > 4)
                        printk("%s: Transmitting a packet of length %lu.\n", dev->name,
index 5ac9da0a3051da2a14c79cc50fae31e0a0e89d65..663c8bd458005974ba5e026bc418ec6bc555de96 100644 (file)
@@ -1658,6 +1658,13 @@ static int hp100_start_xmit_bm( struct sk_buff *skb, struct device *dev )
        
   if ( skb->len <= 0 ) return 0;
        
+  if (skb->len < ETH_ZLEN && lp->chip == HP100_CHIPID_SHASTA)
+  {
+    skb = skb_padto(skb, ETH_ZLEN);
+    if(skb == NULL)
+      return 0;
+  }
   /* Get Tx ring tail pointer */
   if( lp->txrtail->next==lp->txrhead )
     {
index 19b5ca7005f40b88959433c308819953f4797ae7..6ee6403470d45dbd8e4ba13c87a963dfd7e2014c 100644 (file)
@@ -919,8 +919,15 @@ static int lance_start_xmit(struct sk_buff *skb, struct device *dev)
 
        /* The old LANCE chips doesn't automatically pad buffers to min. size. */
        if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) {
-               lp->tx_ring[entry].length =
-                       -(ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
+               if(skb->len < ETH_ZLEN)
+               {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if(skb == NULL)
+                               goto out;
+                       lp->tx_ring[entry].length = -ETH_ZLEN;
+               }
+               else 
+                       lp->tx_ring[entry].length = -skb->len;
        } else
                lp->tx_ring[entry].length = -skb->len;
 
@@ -950,6 +957,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct device *dev)
 
        dev->trans_start = jiffies;
 
+out:
        save_flags(flags);
        cli();
        lp->lock = 0;
index 5daaf80b0e48f9fa065d2fa97c475d2f5174aaf2..25ba8f4f9b8d9accfda80eff04a6ff3c3a9b5d7e 100644 (file)
@@ -932,9 +932,22 @@ i596_start_xmit(struct sk_buff *skb, struct device *dev) {
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
                printk("%s: Transmitter access conflict.\n", dev->name);
        } else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+               short length;
                dev->trans_start = jiffies;
 
+               length = skb->len;
+
+               if(length < ETH_ZLEN)
+               {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if(skb == NULL)
+                       {
+                               dev->tbusy = 0;
+                               return 0;
+                       }
+                       length = ETH_ZLEN;
+               }
+       
                tx_cmd = (struct tx_cmd *)
                        kmalloc ((sizeof (struct tx_cmd)
                                  + sizeof (struct i596_tbd)), GFP_ATOMIC);
index b5e959dddedad2107736b964bae992f682499a59..060f1bd9586c9ec846ea877c2c28945fa4d9ef63 100644 (file)
@@ -113,7 +113,7 @@ static void reset_receiver(struct device *dev);
 
 static int     process_xmt_interrupt(struct device *dev);
 #define tx_done(dev) 1
-extern void    hardware_send_packet(struct device *dev, char *buf, int length);
+extern void    hardware_send_packet(struct device *dev, char *buf, int length, int pad);
 extern void    chipset_init(struct device *dev, int startp);
 static void    dump_packet(void *buf, int len);
 static void    show_registers(struct device *dev);
@@ -457,7 +457,7 @@ static int ni5010_send_packet(struct sk_buff *skb, struct device *dev)
        } else {
                int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 
-               hardware_send_packet(dev, (unsigned char *)skb->data, length);
+               hardware_send_packet(dev, (unsigned char *)skb->data, length, length-skb->len);
                dev->trans_start = jiffies;
        }
        dev_kfree_skb (skb);
@@ -702,7 +702,7 @@ ni5010_set_multicast_list(struct device *dev)
        }
 }
 
-extern void hardware_send_packet(struct device *dev, char *buf, int length)
+extern void hardware_send_packet(struct device *dev, char *buf, int length, int pad)
 {
        struct ni5010_local *lp = (struct ni5010_local *)dev->priv;
        int ioaddr = dev->base_addr;
@@ -727,8 +727,8 @@ extern void hardware_send_packet(struct device *dev, char *buf, int length)
        
        if (NI5010_DEBUG > 3) dump_packet(buf, length);
 
-        buf_offs = NI5010_BUFSIZE - length;
-        lp->o_pkt_size = length;
+        buf_offs = NI5010_BUFSIZE - length - pad ;
+        lp->o_pkt_size = length + pad ;
 
        save_flags(flags);      
        cli();
@@ -739,6 +739,9 @@ extern void hardware_send_packet(struct device *dev, char *buf, int length)
 
        outw(buf_offs, IE_GP); /* Point GP at start of packet */
        outsb(IE_XBUF, buf, length); /* Put data in buffer */
+       while(pad--)
+               outb(0, IE_XBUF);
+               
        outw(buf_offs, IE_GP); /* Rewrite where packet starts */
 
        /* should work without that outb() (Crynwr used it) */
index 2035907fae96267147a67f4bf38432f784970d8d..c762300ee40d2b70c45f3f1e17dc0074b81c962b 100644 (file)
@@ -1174,8 +1174,13 @@ static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
 #endif
        else
        {
+               len = skb->len;
+               if(len < ETH_ZLEN)
+               {
+                       len = ETH_ZLEN;
+                       memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0, len - skb->len);
+               }
                memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
-               len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 
 #if (NUM_XMIT_BUFFS == 1)
 #      ifdef NO_NOPCOMMANDS
index 9e22ce1a412de81a649049395e351a99ca3a86f7..98a0a6d6634f4a48235d045a221bc735301f7bfa 100644 (file)
@@ -1124,6 +1124,8 @@ static int ni65_send_packet(struct sk_buff *skb, struct device *dev)
 
                        memcpy((char *) p->tmdbounce[p->tmdbouncenum] ,(char *)skb->data,
                                                         (skb->len > T_BUF_SIZE) ? T_BUF_SIZE : skb->len);
+                       if(len > skb->len)
+                               memset((char *)p->tmdbounce[p->tmdbouncenum]+skb->len, 0, len-skb->len);
                        dev_kfree_skb (skb);
 
                        save_flags(flags);
index 3e183948b822d8f2181365982fa202f81e532d9a..1ed48ca7aab041dfcb27651ad2d1394eca733eb3 100644 (file)
@@ -393,9 +393,20 @@ seeq8005_send_packet(struct sk_buff *skb, struct device *dev)
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
                printk("%s: Transmitter access conflict.\n", dev->name);
        else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+               short length = skb->len;
                unsigned char *buf = skb->data;
 
+               if(length < ETH_ZLEN)
+               {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if(skb == NULL)
+                       {
+                               dev->tbusy = 0;
+                               return 0;
+                       }
+                       length = ETH_ZLEN;
+               }
+
                hardware_send_packet(dev, buf, length); 
                dev->trans_start = jiffies;
                lp->stats.tx_bytes += length;
index 89db13ed42c95b159dcaf218306a327333715986..3febed9b5421184499fa8761932c294fb1deab50 100644 (file)
@@ -562,6 +562,8 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct device *dev)
         *    added this new entry and restarted it.
         */
        memcpy((char *)td->buf_vaddr, skb->data, skblen);
+       if(len != skblen)
+               memset((char *)(long)td->buf_vaddr + skb->len, 0, len-skblen);
        td->tdma.cntinfo = ((len) & HPCDMA_BCNT) |
                (HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX);
        if(sp->tx_old != sp->tx_new) {
index 244df754479c659acbdb6c276e2dc3bf8b61d74f..0fdbb9c2118738c0745f0fa60c80f4584b0c1ea3 100644 (file)
@@ -1175,6 +1175,7 @@ static int SK_send_packet(struct sk_buff *skb, struct device *dev)
 {
     struct priv *p = (struct priv *) dev->priv;
     struct tmd *tmdp;
+    static char pad[64];
 
     if (dev->tbusy)
     {
@@ -1221,6 +1222,8 @@ static int SK_send_packet(struct sk_buff *skb, struct device *dev)
        /* Copy data into dual ported ram */
 
        memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len);
+       if(len != skb->len)
+               memcpy_toio((tmdp->u.buffer & 0x00ffffff) + skb->len, pad, len-skb->len);
 
        writew(-len, tmdp->blen);            /* set length to transmit */
 
index 6ffedd1159652e8e856226c24a3082c573a560f6..39f5128028aea605a0c8e74df062cac42033aa93 100644 (file)
@@ -563,10 +563,20 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct device * dev )
                printk(CARDNAME": Bad Craziness - sent packet while busy.\n" );
                return 1;
        }
-       lp->saved_skb = skb;
 
-       length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+       length = skb->len;
 
+       if(length < ETH_ZLEN)
+       {
+               skb = skb_padto(skb, ETH_ZLEN);
+               if(skb == NULL)
+               {
+                       netif_wake_queue(dev);
+                       return 0;
+               }
+               length = ETH_ZLEN;
+       }
+       lp->saved_skb = skb;
                
        /*
        ** The MMU wants the number of pages to be the number of 256 bytes
index 1c2cddbf3644c2814d39b6c1fe492742a4431074..a55ed1bd04a512f59a73cf2371c71cf2bf2a6b34 100644 (file)
@@ -969,6 +969,15 @@ static int start_tx(struct sk_buff *skb, struct device *dev)
        /* Calculate the next Tx descriptor entry. */
        entry = np->cur_tx % TX_RING_SIZE;
 
+       if (skb->len < ETH_ZLEN) {
+               skb = skb_padto(skb, ETH_ZLEN);
+               if(skb == NULL)
+               {
+                       dev->tbusy = 0;
+                       return 0;
+               }
+       }
+
        np->tx_skbuff[entry] = skb;
 
        if ((np->drv_flags & ReqTxAlign)  && ((long)skb->data & 3)) {
index 0884cb0d84406af4ae3f49563752e86ab53f71ad..6a692797fbd77efe082bab19549e9af267cc50ba 100644 (file)
@@ -318,10 +318,19 @@ static int znet_send_packet(struct sk_buff *skb, struct device *dev)
 {
        int ioaddr = dev->base_addr;
        struct net_local *lp = (struct net_local *)dev->priv;
+       short length = skb->len;
 
        if (znet_debug > 4)
                printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy);
 
+       if(length < ETH_ZLEN)
+       {
+               skb = skb_padto(skb, ETH_ZLEN);
+               if(skb == NULL)
+                       return 0;
+               length = ETH_ZLEN;
+       }
+       
        /* Transmitter timeout, likely just recovery after suspending the machine. */
        if (dev->tbusy) {
                ushort event, tx_status, rx_offset, state;
@@ -353,7 +362,6 @@ static int znet_send_packet(struct sk_buff *skb, struct device *dev)
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
                printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
        else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
                unsigned char *buf = (void *)skb->data;
                ushort *tx_link = zn.tx_cur - 1;
                ushort rnd_len = (length + 1)>>1;
index 1090e35a3b03762061061c8ebf79e4e6a555cafd..07aa1f490c988f549cfacb67ef50b8e57bec8191 100644 (file)
@@ -149,6 +149,7 @@ extern void                 kfree_skbmem(struct sk_buff *skb);
 extern struct sk_buff *                skb_clone(struct sk_buff *skb, int priority);
 extern struct sk_buff *                skb_copy(struct sk_buff *skb, int priority);
 extern struct sk_buff *                skb_realloc_headroom(struct sk_buff *skb, int newheadroom);
+extern struct sk_buff *                skb_pad(struct sk_buff *skb, int pad);
 #define dev_kfree_skb(a)       kfree_skb(a)
 extern unsigned char *         skb_put(struct sk_buff *skb, unsigned int len);
 extern unsigned char *         skb_push(struct sk_buff *skb, unsigned int len);
@@ -576,6 +577,26 @@ skb_cow(struct sk_buff *skb, unsigned int headroom)
        return skb;
 }
 
+/**
+ *     skb_padto       - pad an skbuff up to a minimal size
+ *     @skb: buffer to pad
+ *     @len: minimal length
+ *
+ *     Pads up a buffer to ensure the trailing bytes exist and are
+ *     blanked. If the buffer already contains sufficient data it
+ *     is untouched. Returns the buffer, which may be a replacement
+ *     for the original, or NULL for out of memory - in which case
+ *     the original buffer is still freed.
+ */
+static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len)
+{
+       unsigned int size = skb->len;
+       if(size >= len)
+               return skb;
+       return skb_pad(skb, len-size);
+}
+
 extern struct sk_buff *                skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
 extern unsigned int            datagram_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait);
 extern int                     skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
index 93b757c980176f7a7972a0ef4e5f7592f50738dc..e2f3c941ad0e2182d26ffdab3686a83ba15c1993 100644 (file)
@@ -312,6 +312,55 @@ struct sk_buff *skb_copy(struct sk_buff *skb, int gfp_mask)
        return n;
 }
 
+struct sk_buff *skb_copy_grow(struct sk_buff *skb, int pad, int gfp_mask)
+{
+       struct sk_buff *n;
+       unsigned long offset;
+
+       /*
+        *      Allocate the copy buffer
+        */
+        
+       n=alloc_skb(skb->end - skb->head + pad, gfp_mask);
+       if(n==NULL)
+               return NULL;
+
+       /*
+        *      Shift between the two data areas in bytes
+        */
+        
+       offset=n->head-skb->head;
+
+       /* Set the data pointer */
+       skb_reserve(n,skb->data-skb->head);
+       /* Set the tail pointer and length */
+       skb_put(n,skb->len);
+       /* Copy the bytes */
+       memcpy(n->head,skb->head,skb->end-skb->head);
+       n->csum = skb->csum;
+       n->list=NULL;
+       n->sk=NULL;
+       n->dev=skb->dev;
+       n->priority=skb->priority;
+       n->protocol=skb->protocol;
+       n->dst=dst_clone(skb->dst);
+       n->h.raw=skb->h.raw+offset;
+       n->nh.raw=skb->nh.raw+offset;
+       n->mac.raw=skb->mac.raw+offset;
+       memcpy(n->cb, skb->cb, sizeof(skb->cb));
+       n->used=skb->used;
+       n->is_clone=0;
+       atomic_set(&n->users, 1);
+       n->pkt_type=skb->pkt_type;
+       n->stamp=skb->stamp;
+       n->destructor = NULL;
+       n->security=skb->security;
+#ifdef CONFIG_IP_FIREWALL
+        n->fwmark = skb->fwmark;
+#endif
+       return n;
+}
+
 struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, int newheadroom)
 {
        struct sk_buff *n;
@@ -362,6 +411,36 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, int newheadroom)
        return n;
 }
 
+/**
+ *     skb_pad                 -       zero pad the tail of an skb
+ *     @skb: buffer to pad
+ *     @pad: space to pad
+ *
+ *     Ensure that a buffer is followed by a padding area that is zero
+ *     filled. Used by network drivers which may DMA or transfer data
+ *     beyond the buffer end onto the wire.
+ *
+ *     May return NULL in out of memory cases.
+ */
+struct sk_buff *skb_pad(struct sk_buff *skb, int pad)
+{
+       struct sk_buff *nskb;
+       
+       /* If the skbuff is non linear tailroom is always zero.. */
+       if(skb_tailroom(skb) >= pad)
+       {
+               memset(skb->data+skb->len, 0, pad);
+               return skb;
+       }
+       
+       nskb = skb_copy_grow(skb, pad, GFP_ATOMIC);
+       kfree_skb(skb);
+       if(nskb)
+               memset(nskb->data+nskb->len, 0, pad);
+       return nskb;
+}      
 #if 0
 /* 
  *     Tune the memory allocator for a new MTU size.