VERSION = 0.99
PATCHLEVEL = 14
-ALPHA = y
+ALPHA = z
all: Version zImage
{
unsigned long count, n;
struct tty_queue *fq, *tq;
+ int skip_readq;
if (from->stopped || EMPTY(&from->write_q))
return;
fq = &from->write_q;
/* Bypass the read_q if this is a pty master. */
- tq = IS_A_PTY_MASTER(to->line) ? &to->secondary : &to->read_q;
+ skip_readq = IS_A_PTY_MASTER(to->line) && to->disc == N_TTY;
+ tq = skip_readq ? &to->secondary : &to->read_q;
count = MIN(CHARS(fq), LEFT(tq));
while (count) {
n = MIN(MIN(TTY_BUF_SIZE - fq->tail, TTY_BUF_SIZE - tq->head),
fq->tail = (fq->tail + n) & (TTY_BUF_SIZE - 1);
tq->head = (tq->head + n) & (TTY_BUF_SIZE - 1);
}
- if (IS_A_PTY_MASTER(to->line))
- wake_up_interruptible(&tq->proc_list);
+ if (skip_readq)
+ wake_up_interruptible(&to->secondary.proc_list);
else
TTY_READ_FLUSH(to);
if (LEFT(fq) > WAKEUP_CHARS)
}
/* Fill in the ethernet header. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
printk("%s: Transmitter access conflict.\n", dev->name);
else {
int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
- unsigned char *buf = (void *)(skb+1);
+ unsigned char *buf = skb->data;
el_status.tx_pkt_start = gp_start;
el_status.collisions = 0;
skb->len = pkt_len;
skb->dev = dev;
- insb(DATAPORT, (void *)(skb+1), pkt_len);
+ insb(DATAPORT, skb->data, pkt_len);
#ifdef HAVE_NETIF_RX
netif_rx(skb);
/* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = (void *)(skb+1);
+ unsigned char *buf = skb->data;
/* Disable the 82586's input to the interrupt line. */
outb(0x80, ioaddr + MISC_CTRL);
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb+1' points to the start of sk_buff data area. */
- memcpy((unsigned char *) (skb + 1), data_frame + 5, pkt_len);
+ /* 'skb->data' points to the start of sk_buff data area. */
+ memcpy(skb->data, data_frame + 5, pkt_len);
#ifdef HAVE_NETIF_RX
netif_rx(skb);
}
/* Fill in the ethernet header. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
outw(skb->len, ioaddr + TX_FIFO);
outw(0x00, ioaddr + TX_FIFO);
/* ... and the packet rounded to a doubleword. */
- outsl(ioaddr + TX_FIFO, (void *)(skb+1), (skb->len + 3) >> 2);
+ outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
dev->trans_start = jiffies;
if (inw(ioaddr + TX_FREE) > 1536) {
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb+1' points to the start of sk_buff data area. */
- insl(ioaddr+RX_FIFO, (void *)(skb+1),
+ /* 'skb->data' points to the start of sk_buff data area. */
+ insl(ioaddr+RX_FIFO, skb->data,
(pkt_len + 3) >> 2);
#ifdef HAVE_NETIF_RX
return 0;
}
/* Fill in the ethernet header. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
return 1;
}
dev->trans_start = jiffies;
- ei_block_output(dev, length, (unsigned char *)(skb+1), output_page);
+ ei_block_output(dev, length, skb->data, output_page);
if (! ei_local->txing) {
NS8390_trigger_send(dev, send_length, output_page);
if (output_page == ei_local->tx_start_page)
tmp_tbusy = 1;
} else {
dev->trans_start = jiffies;
- ei_block_output(dev, length, (unsigned char *)(skb+1),
+ ei_block_output(dev, length, skb->data,
ei_local->tx_start_page);
NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
tmp_tbusy = 1;
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb+1' points to the start of sk_buff data area. */
- ei_block_input(dev, pkt_len, (char *)(skb+1),
+ /* 'skb->data' points to the start of sk_buff data area. */
+ ei_block_input(dev, pkt_len, (char *) skb->data,
current_offset + sizeof(rx_frame));
#ifdef HAVE_NETIF_RX
netif_rx(skb);
/* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = (void *)(skb+1);
+ unsigned char *buf = skb->data;
if (net_debug > 4)
printk("%s: Transmitting a packet of length %d.\n", dev->name,
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb+1' points to the start of sk_buff data area. */
- insw(ioaddr + DATAPORT, (void *)(skb+1), (pkt_len + 1) >> 1);
+ /* 'skb->data' points to the start of sk_buff data area. */
+ insw(ioaddr + DATAPORT, skb->data, (pkt_len + 1) >> 1);
if (net_debug > 5) {
int i;
printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
for (i = 0; i < 14; i++)
- printk(" %02x", ((unsigned char*)(skb + 1))[i]);
+ printk(" %02x", skb->data[i]);
printk(".\n");
}
/* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = (void *)(skb+1);
+ unsigned char *buf = skb->data;
int flags;
/* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb+1' points to the start of sk_buff data area. */
- read_block(ioaddr, pkt_len, (unsigned char *)(skb + 1), dev->if_port);
+ /* 'skb->data' points to the start of sk_buff data area. */
+ read_block(ioaddr, pkt_len, skb->data, dev->if_port);
if (net_debug > 6) {
- unsigned char *data = (unsigned char *)(skb + 1);
+ unsigned char *data = skb->data;
printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x..",
data[0], data[1], data[2], data[3], data[4], data[5],
data[6], data[7], data[8], data[9], data[10], data[11],
int transmit_from;
int len;
int tickssofar;
- unsigned char *buffer = (unsigned char *)(skb + 1);
+ unsigned char *buffer = skb->data;
/*
* If some higher layer thinks we've missed a
/* For ethernet, fill in the header (hardware addresses) with an arp. */
if (!skb->arp)
- if(dev->rebuild_header(skb + 1, dev)) {
+ if(dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
skb->lock = 0;
skb->mem_len = sksize;
skb->mem_addr = skb;
- /* 'skb + 1' points to the start of sk_buff data area. */
- buffer = (unsigned char *)(skb + 1);
+ /* 'skb->data' points to the start of sk_buff data area. */
+ buffer = skb->data;
/* copy the packet into the buffer */
d_link_setup_address(read_from, RW_ADDR);
/* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = (void *)(skb+1);
+ unsigned char *buf = skb->data;
/* Disable the 82586's input to the interrupt line. */
outb(irqrmap[dev->irq], ioaddr + SET_IRQ);
outw(data_buffer_addr + 10, ioaddr + READ_PTR);
- insw(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1);
+ insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
#ifdef HAVE_NETIF_RX
netif_rx(skb);
}
/* Fill in the ethernet header. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
/* If any part of this buffer is >16M we must copy it to a low-memory
buffer. */
- if ((int)(skb+1) + skb->len > 0x01000000) {
+ if ((int)(skb->data) + skb->len > 0x01000000) {
if (lance_debug > 5)
printk("%s: bouncing a high-memory packet (%#x).\n",
- dev->name, (int)(skb+1));
- memcpy(&lp->tx_bounce_buffs[entry], skb+1, skb->len);
+ dev->name, (int)skb->data);
+ memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len);
lp->tx_ring[entry].base =
(int)(lp->tx_bounce_buffs + entry) | 0x83000000;
if (skb->free)
/* Gimme!!! */
if(skb->free==0)
skb_kept_by_device(skb);
- lp->tx_ring[entry].base = (int)(skb+1) | 0x83000000;
+ lp->tx_ring[entry].base = (int)skb->data | 0x83000000;
}
lp->cur_tx++;
skb->mem_addr = skb;
skb->len = pkt_len;
skb->dev = dev;
- memcpy((unsigned char *) (skb + 1),
+ memcpy(skb->data,
(unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff),
pkt_len);
#ifdef HAVE_NETIF_RX
/* Pretend we are an ethernet and fill in the header. This could use
a simplified routine someday. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
skb->arp=1;
dev->trans_start = jiffies;
- ret_val = plip_send_packet(dev, (unsigned char *)(skb+1), skb->len);
+ ret_val = plip_send_packet(dev, skb->data, skb->len);
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev->tbusy = 0;
}
{
/* phase of receiving the data */
- /* 'skb+1' points to the start of sk_buff data area. */
- unsigned char *buf = (unsigned char *) (skb+1);
+ /* 'skb->data' points to the start of sk_buff data area. */
+ unsigned char *buf = skb->data;
unsigned char *eth_p = (unsigned char *)ð
int i;
for ( i = 0; i < sizeof(eth); i++) {
/* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */
- if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = (void *)(skb+1);
+ unsigned char *buf = skb->data;
hardware_send_packet(ioaddr, buf, length);
dev->trans_start = jiffies;
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb+1' points to the start of sk_buff data area. */
- memcpy((unsigned char *) (skb + 1), (void*)dev->rmem_start,
+ /* 'skb->data' points to the start of sk_buff data area. */
+ memcpy(skb->data, (void*)dev->rmem_start,
pkt_len);
/* or */
- insw(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1);
+ insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
#ifdef HAVE_NETIF_RX
netif_rx(skb);
#ifdef CONFIG_AX25
if(sl->mode & SL_MODE_AX25)
{
- if(!skb->arp && dev->rebuild_header(skb+1,dev))
+ if(!skb->arp && dev->rebuild_header(skb->data,dev))
{
skb->dev=dev;
arp_queue(skb);
}
#endif
sl_lock(sl);
-/* sl_hex_dump((unsigned char *)(skb+1),skb->len);*/
- sl_encaps(sl, (unsigned char *) (skb + 1), skb->len);
+/* sl_hex_dump(skb->data,skb->len);*/
+ sl_encaps(sl, skb->data, skb->len);
if (skb->free) kfree_skb(skb, FREE_WRITE);
}
return(0);
struct slip *sl=&sl_ctrl[dev->base_addr];
if(sl->mode&SL_MODE_AX25)
- arp_add(addr,((char *)(skb+1))+8,dev);
+ arp_add(addr,((char *) skb->data)+8,dev);
#endif
}
return(-ENOMEM);
}
+ dev->flags|=IFF_UP;
+ /* Needed because address '0' is special */
+ if(dev->pa_addr==0)
+ dev->pa_addr=ntohl(0xC0000001);
DPRINTF((DBG_SLIP, "SLIP: channel %d opened.\n", sl->line));
return(0);
}
calc_load();
if ((VM_MASK & regs->eflags) || (3 & regs->cs)) {
current->utime++;
- if(current != task[0]) {
- if(current->priority != 15)
+ if (current != task[0]) {
+ if (current->priority < 15)
kstat.cpu_nice++;
else
kstat.cpu_user++;
/* Create and send our response to an ARP request. */
-static int
-arp_response(struct arphdr *arp1, struct device *dev, int addrtype)
+
+/*
+ * We are now a bit smarter. We know the old buffer must be big enough
+ * so why allocate a new one for the reply ?
+ */
+
+static int arp_response(struct sk_buff *skb,struct arphdr *arp1, struct device *dev, int addrtype)
{
struct arphdr *arp2;
- struct sk_buff *skb;
unsigned long src, dst;
unsigned char *ptr1, *ptr2;
int hlen;
+ int len;
struct arp_table *apt = NULL;/* =NULL otherwise the compiler gives warnings */
/* Decode the source (REQUEST) message. */
{
apt=arp_lookup_proxy(dst);
if(apt==NULL)
+ {
+ kfree_skb(skb,FREE_READ);
return(1);
+ }
}
- /* Get some mem and initialize it for the return trip. */
- skb = alloc_skb(sizeof(struct sk_buff) +
- sizeof(struct arphdr) +
- (2 * arp1->ar_hln) + (2 * arp1->ar_pln) +
- dev->hard_header_len, GFP_ATOMIC);
- if (skb == NULL) {
- printk("ARP: no memory available for ARP REPLY!\n");
- return(1);
+ skb->h.raw=skb->data;
+ skb->len+=dev->hard_header_len; /* Grow the packet back to its original form */
+
+ /* Can't check for exceeding the size - some people pad. */
+ len= sizeof(struct arphdr) + (2 * arp1->ar_hln) + (2 * arp1->ar_pln) + dev->hard_header_len;
+ if(len>skb->len)
+ {
+ printk("Received runt ARP request!\n");
+ kfree_skb(skb,FREE_READ);
+ return 1;
}
- skb->mem_addr = skb;
- skb->len = sizeof(struct arphdr) + (2 * arp1->ar_hln) +
- (2 * arp1->ar_pln) + dev->hard_header_len;
- skb->mem_len = sizeof(struct sk_buff) + skb->len;
+ skb->len = len;
+
hlen = dev->hard_header(skb->data, dev, ETH_P_ARP, src, dst, skb->len);
+
if (hlen < 0) {
printk("ARP: cannot create HW frame header for REPLY !\n");
kfree_skb(skb, FREE_WRITE);
* Yes, it is for us.
* Allocate, fill in and send an ARP REPLY packet.
*/
- ret = arp_response(arp, dev, addr_hint);
- kfree_skb(skb, FREE_READ);
+ ret = arp_response(skb,arp, dev, addr_hint);
return(ret);
}
/* Fill in the request. */
skb->sk = NULL;
- skb->mem_addr = skb;
skb->len = sizeof(struct arphdr) +
dev->hard_header_len + (2 * dev->addr_len) + 8;
- skb->mem_len = sizeof(struct sk_buff) + skb->len;
skb->arp = 1;
skb->dev = dev;
- skb->next = NULL;
skb->free = 1;
+ skb->next = NULL;
tmp = dev->hard_header(skb->data, dev, ETH_P_ARP, 0, saddr, skb->len);
if (tmp < 0) {
kfree_skb(skb,FREE_WRITE);
delete_timer(sk);
- if (sk->send_tmp != NULL)
+ while ((skb = tcp_dequeue_partial(sk)) != NULL)
{
- IS_SKB(sk->send_tmp);
- kfree_skb(sk->send_tmp, FREE_WRITE);
+ IS_SKB(skb);
+ kfree_skb(skb, FREE_WRITE);
}
/* Cleanup up the write buffer. */
sk->state = TCP_CLOSE;
sk->dead = 0;
sk->ack_timed = 0;
- sk->send_tmp = NULL;
+ sk->partial = NULL;
sk->user_mss = 0;
sk->debug = 0;
struct sk_buff *volatile send_tail;
struct sk_buff *volatile send_head;
struct sk_buff *volatile back_log;
- struct sk_buff *send_tmp;
+ struct sk_buff *partial;
+ struct timer_list partial_timer;
long retransmits;
struct sk_buff *volatile wback,
*volatile wfront,
}
}
-static struct sk_buff * dequeue_partial(struct sock * sk)
+struct sk_buff * tcp_dequeue_partial(struct sock * sk)
{
struct sk_buff * skb;
unsigned long flags;
save_flags(flags);
cli();
- skb = sk->send_tmp;
- sk->send_tmp = NULL;
+ skb = sk->partial;
+ if (skb) {
+ sk->partial = NULL;
+ del_timer(&sk->partial_timer);
+ }
restore_flags(flags);
return skb;
}
-static void enqueue_partial(struct sk_buff * skb, struct sock * sk)
+static void tcp_send_partial(struct sock *sk)
+{
+ struct sk_buff *skb;
+
+ if (sk == NULL)
+ return;
+ while ((skb = tcp_dequeue_partial(sk)) != NULL)
+ tcp_send_skb(sk, skb);
+}
+
+void tcp_enqueue_partial(struct sk_buff * skb, struct sock * sk)
{
struct sk_buff * tmp;
unsigned long flags;
save_flags(flags);
cli();
- tmp = sk->send_tmp;
- sk->send_tmp = skb;
+ tmp = sk->partial;
+ if (tmp)
+ del_timer(&sk->partial_timer);
+ sk->partial = skb;
+ sk->partial_timer.expires = 5*HZ;
+ sk->partial_timer.function = (void (*)(unsigned long)) tcp_send_partial;
+ sk->partial_timer.data = (unsigned long) sk;
+ add_timer(&sk->partial_timer);
restore_flags(flags);
if (tmp)
tcp_send_skb(sk, tmp);
}
-static void tcp_send_partial(struct sock *sk)
-{
- struct sk_buff *skb;
-
- if (sk == NULL)
- return;
- while ((skb = dequeue_partial(sk)) != NULL)
- tcp_send_skb(sk, skb);
-}
-
/* This routine sends an ack and also updates the window. */
static void
*/
/* Now we need to check if we have a half built packet. */
- if ((skb = dequeue_partial(sk)) != NULL) {
+ if ((skb = tcp_dequeue_partial(sk)) != NULL) {
int hdrlen;
/* IP header + TCP header */
len -= copy;
sk->send_seq += copy;
}
- enqueue_partial(skb, sk);
- if ((skb->len - hdrlen) >= sk->mss || (flags & MSG_OOB)) {
- tcp_send_partial(sk);
- }
+ if ((skb->len - hdrlen) >= sk->mss ||
+ (flags & MSG_OOB) ||
+ !sk->packets_out)
+ tcp_send_skb(sk, skb);
+ else
+ tcp_enqueue_partial(skb, sk);
continue;
}
copy = min(copy, len);
/* We should really check the window here also. */
- if (sk->packets_out && copy < sk->mss && !(flags & MSG_OOB)) {
+ send_tmp = NULL;
+ if (copy < sk->mss && !(flags & MSG_OOB)) {
/* We will release the socket incase we sleep here. */
release_sock(sk);
/* NB: following must be mtu, because mss can be increased.
release_sock(sk);
skb = prot->wmalloc(sk, copy + prot->max_header + sizeof(*skb), 0, GFP_KERNEL);
sk->inuse = 1;
- send_tmp = NULL;
}
/* If we didn't get any memory, we need to sleep. */
skb->free = 0;
sk->send_seq += copy;
- if (send_tmp != NULL) {
- enqueue_partial(send_tmp, sk);
+ if (send_tmp != NULL && sk->packets_out) {
+ tcp_enqueue_partial(send_tmp, sk);
continue;
}
tcp_send_skb(sk, skb);
*/
/* Avoid possible race on send_tmp - c/o Johannes Stille */
- if(sk->send_tmp &&
+ if(sk->partial &&
((!sk->packets_out)
/* If not nagling we can send on the before case too.. */
|| (sk->nonagle && before(sk->send_seq , sk->window_seq))
sk->inuse = 1;
/* Clear out any half completed packets. */
- if (sk->send_tmp) tcp_send_partial(sk);
+ if (sk->partial)
+ tcp_send_partial(sk);
prot =(struct proto *)sk->prot;
th =(struct tcphdr *)&sk->dummy_th;
newsk->intr = 0;
newsk->proc = 0;
newsk->done = 0;
- newsk->send_tmp = NULL;
+ newsk->partial = NULL;
newsk->pair = NULL;
newsk->wmem_alloc = 0;
newsk->rmem_alloc = 0;
sk->rqueue = NULL;
/* Get rid off any half-completed packets. */
- if (sk->send_tmp) {
+ if (sk->partial) {
tcp_send_partial(sk);
}
}
}
- if (sk->packets_out == 0 && sk->send_tmp != NULL &&
+ if (sk->packets_out == 0 && sk->partial != NULL &&
sk->wfront == NULL && sk->send_head == NULL) {
flag |= 1;
tcp_send_partial(sk);
extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern void tcp_enqueue_partial(struct sk_buff *, struct sock *);
+extern struct sk_buff * tcp_dequeue_partial(struct sock *);
+
#endif /* _TCP_H */