Commit 50198be8 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.20

parent ec010c86
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 19
SUBLEVEL = 20
all: Version zImage
......
......@@ -80,7 +80,7 @@ if [ "$CONFIG_SLIP" = "y" ]; then
# bool ' SLIP debugging on' SL_DUMP y
fi
bool 'PPP (point-to-point) support' CONFIG_PPP n
bool 'Load balancing support (very experimental)' CONFIG_SLAVE_BALANCING n
bool 'Load balancing support (experimental)' CONFIG_SLAVE_BALANCING n
bool 'PLIP (parallel port) support' CONFIG_PLIP n
bool 'NE2000/NE1000 support' CONFIG_NE2000 n
bool 'WD80*3 support' CONFIG_WD80x3 n
......@@ -95,6 +95,7 @@ bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n
bool 'AT1700 support' CONFIG_AT1700 n
#bool 'Zenith Z-Note support' CONFIG_ZNET n
#bool 'EtherExpress support' CONFIG_EEXPRESS n
#bool 'Apricot Xen-II on board ethernet' CONFIG_APRICOT n
bool 'DEPCA support' CONFIG_DEPCA n
#bool 'NI52EE support' CONFIG_NI52 n
#bool 'NI65EE support' CONFIG_NI65 n
......@@ -107,7 +108,7 @@ fi
comment 'CD-ROM drivers'
bool 'Sony CDU31A CDROM driver support' CONFIG_CDU31A n
bool 'Sony CDU31A/CDU33A CDROM driver support' CONFIG_CDU31A n
bool 'Mitsumi CDROM driver support' CONFIG_MCD n
bool 'Matsushita/Panasonic CDROM driver support' CONFIG_SBPCD n
......
This diff is collapsed.
......@@ -103,6 +103,7 @@ static int mmap_mem(struct inode * inode, struct file * file,
mpnt->vm_start = addr;
mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL;
mpnt->vm_inode = inode;
inode->i_count++;
......@@ -197,6 +198,7 @@ static int mmap_zero(struct inode * inode, struct file * file,
mpnt->vm_start = addr;
mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL;
mpnt->vm_inode = NULL;
mpnt->vm_offset = off;
......
......@@ -291,8 +291,7 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
if (el_debug > 2)
printk(" queued xmit.\n");
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
return 0;
}
......@@ -514,9 +513,9 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
#ifdef MODULE
char kernel_version[] = UTS_RELEASE;
static struct device dev_3c501 = {
"" /*"3c501"*/,
" " /*"3c501"*/,
0, 0, 0, 0,
0x280, 7,
0x280, 5,
0, 0, 0, NULL, el1_probe };
int
......
......@@ -479,8 +479,7 @@ el16_send_packet(struct sk_buff *skb, struct device *dev)
outb(0x84, ioaddr + MISC_CTRL);
}
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
/* You might need to clean up and record Tx statistics here. */
......
......@@ -388,8 +388,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
outw(0x9000 + 1536, ioaddr + EL3_CMD);
}
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
/* Clear the Tx status stack. */
{
......@@ -669,7 +668,7 @@ el3_close(struct device *dev)
#ifdef MODULE
char kernel_version[] = UTS_RELEASE;
static struct device dev_3c509 = {
"" /*"3c509"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el3_probe };
" " /*"3c509"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el3_probe };
int
init_module(void)
......
......@@ -230,8 +230,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
return 0;
}
......@@ -556,7 +555,7 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
rely on higher-level filtering for now. */
outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR);
} else if (num_addrs < 0)
outb_p(E8390_RXCONFIG | 0x10, ioaddr + EN0_RXCR);
outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR);
else
outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR);
}
......
......@@ -136,6 +136,9 @@ ifdef CONFIG_AC3200
NETDRV_OBJS := $(NETDRV_OBJS) net.a(ac3200.o)
CONFIG_8390 = CONFIG_8390
endif
ifdef CONFIG_APRICOT
NETDRV_OBJS := $(NETDRV_OBJS) net.a(apricot.o)
endif
ifdef CONFIG_8390
NETDRV_OBJS := $(NETDRV_OBJS) net.a(8390.o)
......
This diff is collapsed.
......@@ -406,8 +406,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
/* Turn on Tx interrupts back on. */
outb(0x82, ioaddr + TX_INTR);
}
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
return 0;
}
......
......@@ -471,8 +471,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
write_reg_high(ioaddr, IMR, ISRh_RxErr);
}
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
return 0;
}
......
......@@ -453,8 +453,7 @@ de600_start_xmit(struct sk_buff *skb, struct device *dev)
sti(); /* interrupts back on */
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
return 0;
}
......@@ -751,7 +750,7 @@ de600_rspace(struct sock *sk)
#ifdef MODULE
char kernel_version[] = UTS_RELEASE;
static struct device de600_dev = {
"" /*"de600"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe };
" " /*"de600"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe };
int
init_module(void)
......
......@@ -914,9 +914,7 @@ depca_start_xmit(struct sk_buff *skb, struct device *dev)
dev->tbusy=0;
}
if (skb->free) {
kfree_skb (skb, FREE_WRITE);
}
dev_kfree_skb (skb, FREE_WRITE);
}
return 0;
......
......@@ -89,8 +89,7 @@ dummy_xmit(struct sk_buff *skb, struct device *dev)
if (skb == NULL || dev == NULL)
return 0;
if (skb->free)
kfree_skb(skb, FREE_WRITE);
dev_kfree_skb(skb, FREE_WRITE);
#if DUMMY_STATS
stats = (struct enet_statistics *)dev->priv;
......
......@@ -494,8 +494,7 @@ eexp_send_packet(struct sk_buff *skb, struct device *dev)
outb(0x08 | irqrmap[dev->irq], ioaddr + SET_IRQ);
}
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
/* You might need to clean up and record Tx statistics here. */
lp->stats.tx_aborted_errors++;
......
......@@ -555,14 +555,8 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
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)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
} else {
/* We can't free the packet yet, so we inform the memory management
code that we are still using it. */
skb_kept_by_device(skb);
lp->tx_ring[entry].base = (int)(skb->data) | 0x83000000;
}
lp->cur_tx++;
......@@ -650,7 +644,7 @@ lance_interrupt(int reg_ptr)
if (databuff >= (void*)(&lp->tx_bounce_buffs[TX_RING_SIZE])
|| databuff < (void*)(lp->tx_bounce_buffs)) {
struct sk_buff *skb = ((struct sk_buff *)databuff) - 1;
skb_device_release(skb,FREE_WRITE);
dev_kfree_skb(skb,FREE_WRITE);
/* Warning: skb may well vanish at the point you call
device_release! */
......
......@@ -56,9 +56,12 @@ loopback_xmit(struct sk_buff *skb, struct device *dev)
}
dev->tbusy = 1;
sti();
/* FIXME: Optimise so buffers with skb->free=1 are not copied but
instead are lobbed from tx queue to rx queue */
done = dev_rint(skb->data, skb->len, 0, dev);
if (skb->free) kfree_skb(skb, FREE_WRITE);
dev_kfree_skb(skb, FREE_WRITE);
while (done != 1) {
done = dev_rint(NULL, 0, 0, dev);
......
......@@ -52,6 +52,9 @@
static struct device *ethdev_index[MAX_ETH_CARDS];
unsigned long lance_init(unsigned long mem_start, unsigned long mem_end);
unsigned long pi_init(unsigned long mem_start, unsigned long mem_end);
unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end);
/*
net_dev_init() is our network device initialization routine.
......@@ -67,6 +70,9 @@ unsigned long net_dev_init (unsigned long mem_start, unsigned long mem_end)
#endif
#if defined(CONFIG_PI)
mem_start = pi_init(mem_start, mem_end);
#endif
#if defined(CONFIG_APRICOT)
mem_start = apricot_init(mem_start, mem_end);
#endif
return mem_start;
}
......
This diff is collapsed.
......@@ -1798,8 +1798,7 @@ ppp_xmit(struct sk_buff *skb, struct device *dev)
ppp_kick_tty(ppp);
done:
if (skb->free)
kfree_skb(skb, FREE_WRITE);
dev_kfree_skb(skb, FREE_WRITE);
return 0;
}
......
......@@ -292,8 +292,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
hardware_send_packet(ioaddr, buf, length);
dev->trans_start = jiffies;
}
if (skb->free)
kfree_skb (skb, FREE_WRITE);
dev_kfree_skb (skb, FREE_WRITE);
/* You might need to clean up and record Tx statistics here. */
if (inw(ioaddr) == /*RU*/81)
......
......@@ -464,41 +464,11 @@ sl_xmit(struct sk_buff *skb, struct device *dev)
/* We were not, so we are now... :-) */
if (skb != NULL) {
#if 0
#ifdef CONFIG_AX25
if(sl->mode & SL_MODE_AX25)
{
if(!skb->arp && dev->rebuild_header(skb->data,dev))
{
skb->dev=dev;
arp_queue(skb);
return 0;
}
skb->arp=1;
}
#endif
#endif
sl_lock(sl);
size=skb->len;
#if 0
if(!(sl->mode&SL_MODE_AX25))
{
if(size<sizeof(struct iphdr))
{
printk("Runt IP frame fed to slip!\n");
}
else
{
size=((struct iphdr *)(skb->data))->tot_len;
size=ntohs(size);
/* sl_hex_dump(skb->data,skb->len);*/
}
}
#endif
sl_encaps(sl, skb->data, size);
if (skb->free)
kfree_skb(skb, FREE_WRITE);
dev_kfree_skb(skb, FREE_WRITE);
}
return(0);
}
......
......@@ -147,7 +147,7 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
Scsi_Cmnd * SCpnt;
unsigned char opcode;
int inlen, outlen, cmdlen;
int needed;
int needed, buf_needed;
int result;
if (!buffer)
......@@ -159,11 +159,11 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
cmd_in = (char *) ( ((int *)buffer) + 2);
opcode = get_fs_byte(cmd_in);
needed = (inlen > outlen ? inlen : outlen);
if(needed){
needed = (needed + 511) & ~511;
if (needed > MAX_BUF) needed = MAX_BUF;
buf = (char *) scsi_malloc(needed);
needed = buf_needed = (inlen > outlen ? inlen : outlen);
if(buf_needed){
buf_needed = (buf_needed + 511) & ~511;
if (buf_needed > MAX_BUF) buf_needed = MAX_BUF;
buf = (char *) scsi_malloc(buf_needed);
if (!buf) return -ENOMEM;
} else
buf = NULL;
......@@ -202,7 +202,7 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
};
result = SCpnt->result;
SCpnt->request.dev = -1; /* Mark as not busy */
if (buf) scsi_free(buf, needed);
if (buf) scsi_free(buf, buf_needed);
if(scsi_devices[SCpnt->index].scsi_request_fn)
(*scsi_devices[SCpnt->index].scsi_request_fn)();
......
......@@ -13,6 +13,7 @@
/*
* TODO:
* 1. Find out why scatter/gather is limited to 16 requests per command.
* This is fixed, at least on the 24F, as of version 1.12 - CAE.
* 2. Look at command linking (mscp.command_link and
* mscp.command_link_id). (Does not work with many disks,
* and no performance increase. ERY).
......@@ -38,6 +39,15 @@
* unfinished, questionable, or wrong.
*/
/* Changes from version 1.11 alpha to 1.12
*
* Increased the size of the scatter-gather list to 33 entries for
* the 24F adapter (it was 16). I don't have the specs for the 14F
* or the 34F, so they may support larger s-g lists as well.
*
* Caleb Epstein <cae@jpmorgan.com>
*/
/* Changes from version 1.9 to 1.11
*
* Patches to bring this driver up to speed with the default kernel
......@@ -138,7 +148,7 @@
#define ULTRASTOR_DEBUG (UD_ABORT|UD_CSIR|UD_RESET)
#endif
#define VERSION "1.11 alpha"
#define VERSION "1.12"
#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
......@@ -183,7 +193,7 @@ struct mscp {
the MSCP structure because they are associated with SCSI requests. */
void (*done)(Scsi_Cmnd *);
Scsi_Cmnd *SCint;
ultrastor_sg_list sglist[ULTRASTOR_14F_MAX_SG];
ultrastor_sg_list sglist[ULTRASTOR_24F_MAX_SG]; /* use larger size for 24F */
};
......@@ -504,6 +514,7 @@ static int ultrastor_14f_detect(int hostnum)
static int ultrastor_24f_detect(int hostnum)
{
register int i;
struct Scsi_Host * shpnt = NULL;
#if (ULTRASTOR_DEBUG & UD_DETECT)
printk("US24F: detect");
......@@ -580,7 +591,12 @@ static int ultrastor_24f_detect(int hostnum)
config.host_number = hostnum;
scsi_hosts[hostnum].this_id = config.ha_scsi_id;
scsi_hosts[hostnum].unchecked_isa_dma = 0;
scsi_hosts[hostnum].sg_tablesize = ULTRASTOR_14F_MAX_SG;
scsi_hosts[hostnum].sg_tablesize = ULTRASTOR_24F_MAX_SG;
shpnt = scsi_register(hostnum, 0);
shpnt->irq = config.interrupt;
shpnt->dma_channel = config.dma_channel;
shpnt->io_port = config.port_address;
#if ULTRASTOR_MAX_CMDS > 1
config.mscp_free = ~0;
......@@ -594,7 +610,7 @@ static int ultrastor_24f_detect(int hostnum)
outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(addr+12));
outb(0x02, SYS_DOORBELL_MASK(addr+12));
printk("UltraStor driver version " VERSION ". Using %d SG lists.\n",
ULTRASTOR_14F_MAX_SG);
scsi_hosts[hostnum].sg_tablesize);
return TRUE;
}
return FALSE;
......@@ -810,6 +826,10 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
if(config.slot)
return SCSI_ABORT_SNOOZE; /* Do not attempt an abort for the 24f */
/* Simple consistency checking */
if(!SCpnt->host_scribble)
return SCSI_ABORT_NOT_RUNNING;
mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp;
if (mscp_index >= ULTRASTOR_MAX_CMDS)
panic("Ux4F aborting invalid MSCP");
......@@ -899,7 +919,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
#if ULTRASTOR_DEBUG & UD_ABORT
if (config.mscp[mscp_index].SCint != SCpnt)
printk("abort: command mismatch, %x != %x\n",
printk("abort: command mismatch, %p != %p\n",
config.mscp[mscp_index].SCint, SCpnt);
#endif
if (config.mscp[mscp_index].SCint == 0)
......@@ -915,7 +935,6 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
/* Need to set a timeout here in case command never completes. */
return SCSI_ABORT_SUCCESS;
}
int ultrastor_reset(Scsi_Cmnd * SCpnt)
......
......@@ -21,6 +21,8 @@ int ultrastor_reset(Scsi_Cmnd *);
int ultrastor_biosparam(int, int, int *);
#define ULTRASTOR_14F_MAX_SG 16
#define ULTRASTOR_24F_MAX_SG 33
#define ULTRASTOR_MAX_CMDS_PER_LUN 5
#define ULTRASTOR_MAX_CMDS 16
......
......@@ -42,6 +42,7 @@
#include <asm/system.h>
#include <linux/binfmts.h>
#include <linux/personality.h>
#include <asm/segment.h>
#include <asm/system.h>
......@@ -55,12 +56,15 @@ extern void shm_exit (void);
static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(int fd);
static int aout_core_dump(long signr, struct pt_regs * regs);
/*
* Here are the actual binaries that will be accepted:
* add more with "register_binfmt()"..
*/
static struct linux_binfmt aout_format = { NULL, load_aout_binary, load_aout_library };
static struct linux_binfmt aout_format = {
NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump
};
static struct linux_binfmt *formats = &aout_format;
int register_binfmt(struct linux_binfmt * fmt)
......@@ -154,7 +158,7 @@ if (file.f_op->lseek) { \
* field, which also makes sure the core-dumps won't be recursive if the
* dumping of the process results in another error..
*/
int core_dump(long signr, struct pt_regs * regs)
static int aout_core_dump(long signr, struct pt_regs * regs)
{
struct inode * inode = NULL;
struct file file;
......@@ -318,12 +322,12 @@ unsigned long * create_tables(char * p,int argc,int envc,int ibcs)
mpnt->vm_start = PAGE_MASK & (unsigned long) p;
mpnt->vm_end = TASK_SIZE;
mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
mpnt->vm_flags = VM_GROWSDOWN;
mpnt->vm_share = NULL;
mpnt->vm_inode = NULL;
mpnt->vm_offset = 0;
mpnt->vm_ops = NULL;
insert_vm_struct(current, mpnt);
current->mm->stk_vma = mpnt;
}
sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
sp -= envc+1;
......@@ -529,7 +533,6 @@ void flush_old_exec(struct linux_binprm * bprm)
mpnt = current->mm->mmap;
current->mm->mmap = NULL;
current->mm->stk_vma = NULL;
while (mpnt) {
mpnt1 = mpnt->vm_next;
if (mpnt->vm_ops && mpnt->vm_ops->close)
......@@ -571,9 +574,6 @@ void flush_old_exec(struct linux_binprm * bprm)
if (last_task_used_math == current)
last_task_used_math = NULL;
current->used_math = 0;
current->personality = 0;
current->lcall7 = no_lcall7;
current->signal_map = current->signal_invmap = ident_map;
}
/*
......@@ -764,25 +764,6 @@ asmlinkage int sys_execve(struct pt_regs regs)
return error;
}
/*
* signal mapping: this is the default identity mapping used for normal
* linux binaries (it's both the reverse and the normal map, of course)
*/
unsigned long ident_map[33] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32
};
/*
* default lcall7 handler.. The native linux stuff doesn't
* use it at all, so we just segfault on it.
*/
asmlinkage void no_lcall7(struct pt_regs * regs)
{
send_sig(SIGSEGV, current, 1);
}
static void set_brk(unsigned long start, unsigned long end)
{
start = PAGE_ALIGN(start);
......@@ -805,6 +786,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
struct file * file;
int fd, error;
unsigned long p = bprm->p;
unsigned long fd_offset;
ex = *((struct exec *) bprm->buf); /* exec-header */
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
......@@ -814,17 +796,19 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
return -ENOEXEC;
}
if (N_MAGIC(ex) == ZMAGIC &&
(N_TXTOFF(ex) < bprm->inode->i_sb->s_blocksize)) {
printk("N_TXTOFF < BLOCK_SIZE. Please convert binary.");
current->personality = PER_LINUX;
fd_offset = N_TXTOFF(ex);
if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
return -ENOEXEC;
}
if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) == ZMAGIC) {
printk("N_TXTOFF != BLOCK_SIZE. See a.out.h.");
if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
(fd_offset < bprm->inode->i_sb->s_blocksize)) {
printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
return -ENOEXEC;
}
/* OK, This is the point of no return */
flush_old_exec(bprm);
......@@ -845,7 +829,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data);
} else {
if (ex.a_text & 0xfff || ex.a_data & 0xfff)
printk("%s: executable not page aligned\n", current->comm);
printk(KERN_NOTICE "executable not page aligned\n");
fd = open_inode(bprm->inode, O_RDONLY);
......@@ -857,23 +841,26 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
do_mmap(NULL, 0, ex.a_text+ex.a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
read_exec(bprm->inode, N_TXTOFF(ex),
read_exec(bprm->inode, fd_offset,
(char *) N_TXTADDR(ex), ex.a_text+ex.a_data);
goto beyond_if;
}
error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
if (ex.a_text) {
error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_SHARED, N_TXTOFF(ex));
MAP_FIXED | MAP_SHARED, fd_offset);
if (error != N_TXTADDR(ex)) {
sys_close(fd);
send_sig(SIGSEGV, current, 0);
return 0;
};
if (error != N_TXTADDR(ex)) {
sys_close(fd);
send_sig(SIGSEGV, current, 0);
return 0;
};
}
error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, N_TXTOFF(ex) + ex.a_text);
MAP_FIXED | MAP_PRIVATE, fd_offset + ex.a_text);
sys_close(fd);
if (error != N_TXTADDR(ex) + ex.a_text) {
send_sig(SIGSEGV, current, 0);
......@@ -883,11 +870,24 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
bprm->inode->i_count++;
}
beyond_if:
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)--;
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &aout_format;
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)++;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)++;
set_brk(current->mm->start_brk, current->mm->brk);
p += change_ldt(ex.a_text,bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long) create_tables((char *)p,bprm->argc,bprm->envc,0);
p = (unsigned long)create_tables((char *)p,
bprm->argc, bprm->envc,
current->personality != PER_LINUX);
current->mm->start_stack = p;
regs->eip = ex.a_entry; /* eip, magic happens :-) */
regs->esp = p; /* stack pointer */
......
......@@ -63,46 +63,59 @@ static struct super_operations isofs_sops = {
NULL
};
struct iso9660_options{
char map;
char rock;
char cruft;
unsigned char conversion;
unsigned int blocksize;
gid_t gid;
uid_t uid;
};
static int parse_options(char *options,char *map,char *conversion, char * rock, char * cruft, unsigned int * blocksize)
static int parse_options(char *options, struct iso9660_options * popt)
{
char *this_char,*value;
*map = 'n';
*rock = 'y';
*cruft = 'n';
*conversion = 'a';
*blocksize = 1024;
popt->map = 'n';
popt->rock = 'y';
popt->cruft = 'n';
popt->conversion = 'a';
popt->blocksize = 1024;
popt->gid = 0;
popt->uid = 0;
if (!options) return 1;
for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
if (strncmp(this_char,"norock",6) == 0) {
*rock = 'n';
popt->rock = 'n';
continue;
};
if (strncmp(this_char,"cruft",5) == 0) {
*cruft = 'y';
popt->cruft = 'y';
continue;
};
if ((value = strchr(this_char,'=')) != NULL)
*value++ = 0;
if (!strcmp(this_char,"map") && value) {
if (value[0] && !value[1] && strchr("on",*value))
*map = *value;
else if (!strcmp(value,"off")) *map = 'o';
else if (!strcmp(value,"normal")) *map = 'n';
popt->map = *value;
else if (!strcmp(value,"off")) popt->map = 'o';
else if (!strcmp(value,"normal")) popt->map = 'n';
else return 0;
}
else if (!strcmp(this_char,"conv") && value) {
if (value[0] && !value[1] && strchr("bta",*value))
*conversion = *value;
else if (!strcmp(value,"binary")) *conversion = 'b';
else if (!strcmp(value,"text")) *conversion = 't';
else if (!strcmp(value,"mtext")) *conversion = 'm';
else if (!strcmp(value,"auto")) *conversion = 'a';
popt->conversion = *value;
else if (!strcmp(value,"binary")) popt->conversion = 'b';
else if (!strcmp(value,"text")) popt->conversion = 't';
else if (!strcmp(value,"mtext")) popt->conversion = 'm';
else if (!strcmp(value,"auto")) popt->conversion = 'a';
else return 0;
}
else if (!strcmp(this_char,"block") && value) {
else if (value &&
(!strcmp(this_char,"block") ||
!strcmp(this_char,"uid") ||
!strcmp(this_char,"gid"))) {
char * vpnt = value;
unsigned int ivalue;
ivalue = 0;
......@@ -112,8 +125,18 @@ static int parse_options(char *options,char *map,char *conversion, char * rock,
vpnt++;
};
if (*vpnt) return 0;
if (ivalue != 1024 && ivalue != 2048) return 0;
*blocksize = ivalue;
switch(*this_char) {
case 'b':
if (ivalue != 1024 && ivalue != 2048) return 0;
popt->blocksize = ivalue;
break;
case 'g':
popt->uid = ivalue;
break;
case 'u':
popt->gid = ivalue;
break;
}
}
else return 0;
}
......@@ -125,7 +148,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
{
struct buffer_head *bh;
int iso_blknum;
unsigned int blocksize, blocksize_bits;
unsigned int blocksize_bits;
int high_sierra;
int dev=s->s_dev;
struct iso_volume_descriptor *vdp;
......@@ -136,29 +159,39 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
struct iso_directory_record *rootp;
char map, conversion, rock, cruft;
struct iso9660_options opt;
if (!parse_options((char *) data,&map,&conversion, &rock, &cruft, &blocksize)) {
if (!parse_options((char *) data,&opt)) {
s->s_dev = 0;
return NULL;
}
#if 0
printk("map = %c\n", opt.map);
printk("rock = %c\n", opt.rock);
printk("cruft = %c\n", opt.cruft);
printk("conversion = %c\n", opt.conversion);
printk("blocksize = %d\n", opt.blocksize);
printk("gid = %d\n", opt.gid);
printk("uid = %d\n", opt.uid);
#endif
blocksize_bits = 0;
{
int i = blocksize;
int i = opt.blocksize;
while (i != 1){
blocksize_bits++;
i >>=1;
};
};
set_blocksize(dev, blocksize);
set_blocksize(dev, opt.blocksize);
lock_super(s);
s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), blocksize))) {
if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), opt.blocksize))) {
s->s_dev=0;
printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
dev, iso_blknum);
......@@ -178,7 +211,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
s->u.isofs_sb.s_high_sierra = 1;
high_sierra = 1;
rock = 'n';
opt.rock = 'n';
h_pri = (struct hs_primary_descriptor *)vdp;
break;
};
......@@ -235,7 +268,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
to allow suid. (suid or devices will not show up unless we have
Rock Ridge extensions) */
s->s_flags = MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) {
printk("1 <<Block bits != Block size\n");
......@@ -256,11 +289,13 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
s->s_dev = dev;
s->s_op = &isofs_sops;
s->u.isofs_sb.s_mapping = map;
s->u.isofs_sb.s_rock = (rock == 'y' ? 1 : 0);
s->u.isofs_sb.s_conversion = conversion;
s->u.isofs_sb.s_cruft = cruft;
s->s_blocksize = blocksize;
s->u.isofs_sb.s_mapping = opt.map;
s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0);
s->u.isofs_sb.s_conversion = opt.conversion;
s->u.isofs_sb.s_cruft = opt.cruft;
s->u.isofs_sb.s_uid = opt.uid;
s->u.isofs_sb.s_gid = opt.gid;
s->s_blocksize = opt.blocksize;
s->s_blocksize_bits = blocksize_bits;
s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
unlock_super(s);
......@@ -389,8 +424,8 @@ void isofs_read_inode(struct inode * inode)
if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
inode->i_mode |= S_IXUGO; /* execute permission */
}
inode->i_uid = 0;
inode->i_gid = 0;
inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
inode->i_size = isonum_733 (raw_inode->size);
/* There are defective discs out there - we do this to protect
......@@ -416,15 +451,6 @@ void isofs_read_inode(struct inode * inode)
inode->i_size = 0;
}
#ifdef DEBUG
/* I have no idea what extended attributes are used for, so
we will flag it for now */
if(raw_inode->ext_attr_length[0] != 0){
printk("Extended attributes present for ISO file (%ld).\n",
inode->i_ino);
}
#endif
/* I have no idea what file_unit_size is used for, so
we will flag it for now */
if(raw_inode->file_unit_size[0] != 0){
......@@ -446,7 +472,9 @@ void isofs_read_inode(struct inode * inode)
inode->i_mtime = inode->i_atime = inode->i_ctime =
iso_date(raw_inode->date, high_sierra);
inode->u.isofs_i.i_first_extent = isonum_733 (raw_inode->extent) <<
inode->u.isofs_i.i_first_extent =
(isonum_733 (raw_inode->extent) +
isonum_711 (raw_inode->ext_attr_length)) <<
(ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS(inode));
inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
......
......@@ -73,6 +73,7 @@ int nfs_mmap(struct inode * inode, struct file * file,
mpnt->vm_start = addr;
mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL;
mpnt->vm_inode = inode;
inode->i_count++;
......
/*
* linux/fs/binfmt_elf.c
*
* These are the functions used to load ELF format executables as used
* on SVr4 machines. Information on the format may be found in the book
* "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support
* Tools".
*
* Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
*/
#include <linux/fs.h>
#include <linux/sched.h>
......@@ -14,6 +21,7 @@
#include <linux/ptrace.h>
#include <linux/malloc.h>
#include <linux/shm.h>
#include <linux/personality.h>
#include <asm/segment.h>
......@@ -139,7 +147,7 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
if((interp_elf_ex->e_type != ET_EXEC &&
interp_elf_ex->e_type != ET_DYN) ||
(interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) ||
(!interpreter_inode->i_op || !interpreter_inode->i_op->bmap ||
(!interpreter_inode->i_op ||
!interpreter_inode->i_op->default_file_ops->mmap)){
return 0xffffffff;
};
......@@ -251,7 +259,7 @@ static unsigned int load_aout_interp(struct exec * interp_ex,
#define INTERPRETER_AOUT 1
#define INTERPRETER_ELF 2
int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
struct elfhdr elf_ex;
struct elfhdr interp_elf_ex;
......@@ -496,8 +504,17 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
kfree(elf_phdata);
if(!elf_interpreter) sys_close(elf_exec_fileno);
current->elf_executable = 1;
if(interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno);
/* The following 3 lines need a little bit of work if we are loading
an iBCS2 binary. We should initially load it this way, and if
we get a lcall7, then we should look to see if the iBCS2 execution
profile is present. If it is, then switch to that, otherwise
bomb. */
current->personality = PER_LINUX;
current->lcall7 = no_lcall7;
current->signal_map = current->signal_invmap = ident_map;
current->executable = bprm->inode;
bprm->inode->i_count++;
#ifdef LOW_ELF_STACK
......@@ -545,7 +562,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* This is really simpleminded and specialized - we are loading an
a.out library that is given an ELF header. */
int load_elf_library(int fd){
static int load_elf_library(int fd){
struct file * file;
struct elfhdr elf_ex;
struct elf_phdr *elf_phdata = NULL;
......@@ -576,7 +593,7 @@ int load_elf_library(int fd){
/* First of all, some simple consistency checks */
if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
(elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
(!inode->i_op || !inode->i_op->bmap ||
(!inode->i_op ||
!inode->i_op->default_file_ops->mmap)){
return -ENOEXEC;
};
......@@ -634,3 +651,5 @@ int load_elf_library(int fd){
kfree(elf_phdata);
return 0;
}
struct linux_binfmt elf_format = { NULL, load_elf_binary, load_elf_library };
......@@ -30,8 +30,10 @@ struct linux_binprm{
*/
struct linux_binfmt {
struct linux_binfmt * next;
int *use_count;
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
int (*load_shlib)(int fd);
int (*core_dump)(long signr, struct pt_regs * regs);
};
extern int register_binfmt(struct linux_binfmt *);
......
......@@ -135,6 +135,7 @@
#define SONY_HWC_GET_LOAD_MECH(c) (c.hw_config[0] & 0x03)
#define SONY_HWC_EJECT(c) (c.hw_config[0] & 0x04)
#define SONY_HWC_LED_SUPPORT(c) (c.hw_config[0] & 0x08)
#define SONY_HWC_DOUBLE_SPEED(c) (c.hw_config[0] & 0x10)
#define SONY_HWC_GET_BUF_MEM_SIZE(c) ((c.hw_config[0] & 0xc0) >> 6)
#define SONY_HWC_AUDIO_PLAYBACK(c) (c.hw_config[1] & 0x01)
#define SONY_HWC_ELECTRIC_VOLUME(c) (c.hw_config[1] & 0x02)
......
......@@ -60,7 +60,7 @@ struct ifaddr {
/*
* Device mapping structure. I'd just gone off and designed a
* beautiful scheme using only loadable modules with arguments
* for driver options and along come the PCMICA people 8)
* for driver options and along come the PCMCIA people 8)
*
* Ah well. The get() side of this is good for WDSETUP, and it'll
* be handy for debugging things. The set side is fine for now and
......
/*
* NET3 PLIP tuning facilities for the new Niibe PLIP.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#ifndef _LINUX_IF_PLIP_H
#define _LINUX_IF_PLIP_H
#include <linux/sockios.h>
#define SIOCDEVPLIP SIOCDEVPRIVATE
struct plipconf
{
unsigned short pcmd;
unsigned long nibble;
unsigned long trigger;
};
#define PLIP_GET_TIMEOUT 0x1
#define PLIP_SET_TIMEOUT 0x2
#endif
......@@ -18,6 +18,10 @@ struct isofs_sb_info {
unsigned char s_cruft; /* Broken disks with high
byte of length containing
junk */
unsigned char s_nosuid;
unsigned char s_nodev;
gid_t s_gid;
uid_t s_uid;
};
#endif
......
......@@ -19,6 +19,7 @@ struct modify_ldt_ldt_s {
unsigned int contents:2;
unsigned int read_exec_only:1;
unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
};
#define MODIFY_LDT_CONTENTS_DATA 0
......
......@@ -9,18 +9,7 @@
#define VERIFY_READ 0
#define VERIFY_WRITE 1
int __verify_write(unsigned long addr, unsigned long count);
extern inline int verify_area(int type, const void * addr, unsigned long size)
{
if (TASK_SIZE <= (unsigned long) addr)
return -EFAULT;
if (size > TASK_SIZE - (unsigned long) addr)
return -EFAULT;
if (wp_works_ok || type == VERIFY_READ || !size)
return 0;
return __verify_write((unsigned long) addr,size);
}
extern int verify_area(int, const void *, unsigned long);
/*
* Linux kernel virtual memory manager primitives.
......@@ -42,6 +31,7 @@ struct vm_area_struct {
unsigned long vm_start;
unsigned long vm_end;
unsigned short vm_page_prot;
unsigned short vm_flags;
struct vm_area_struct * vm_next; /* linked list */
struct vm_area_struct * vm_share; /* linked list */
struct inode * vm_inode;
......@@ -49,6 +39,12 @@ struct vm_area_struct {
struct vm_operations_struct * vm_ops;
};
/*
* vm_flags..
*/
#define VM_GROWSDOWN 0x01
#define VM_GROWSUP 0x02
/*
* These are the virtual MM functions - opening of an area, closing it (needed to
* keep files on disk up-to-date etc), pointer to the functions called when a
......
......@@ -22,14 +22,6 @@
#define NFS_READDIR_CACHE_SIZE 64
/*
* WARNING! The I/O buffer size cannot be bigger than about 3900 for now.
* It needs to fit inside a 4096-byte page and leave room for the RPC and
* NFS headers. But it ought to at least be a multiple of 512 and probably
* should be a power of 2. I don't think Linux TCP/IP can handle more than
* about 1800 yet.
*/
#define NFS_MAX_FILE_IO_BUFFER_SIZE (7*512)
#define NFS_DEF_FILE_IO_BUFFER_SIZE 1024
......
#ifndef _PERSONALITY_H
#define _PERSONALITY_H
#include <linux/linkage.h>
#include <linux/ptrace.h>
/* Flags for bug emulation. These occupy the top three bytes. */
#define STICKY_TIMEOUTS 0x8000000
#define WHOLE_SECONDS 0x4000000
#define STICKY_TIMEOUTS 0x4000000
#define WHOLE_SECONDS 0x2000000
/* Personality types. These go in the low byte. */
/* Personality types. These go in the low byte. Avoid using the top bit,
* it will conflict with error returns.
*/
#define PER_MASK (0x00ff)
#define PER_LINUX (0x0000)
#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS)
......@@ -10,3 +19,33 @@
#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS)
#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS)
#define PER_BSD (0x0006)
/* Prototype for an lcall7 syscall handler. */
typedef asmlinkage void (*lcall7_func)(struct pt_regs *);
/* Description of an execution domain - personality range supported,
* lcall7 syscall handler, start up / shut down functions etc.
* N.B. The name and lcall7 handler must be where they are since the
* offset of the handler is hard coded in kernel/sys_call.S.
*/
struct exec_domain {
char *name;
lcall7_func handler;
unsigned char pers_low, pers_high;
unsigned long * signal_map;
unsigned long * signal_invmap;
int *use_count;
struct exec_domain *next;
};
extern struct exec_domain default_exec_domain;
extern struct exec_domain *lookup_exec_domain(unsigned long personality);
extern int register_exec_domain(struct exec_domain *it);
extern int unregister_exec_domain(struct exec_domain *it);
extern asmlinkage int sys_personality(unsigned long personality);
#endif /* _PERSONALITY_H */
......@@ -36,6 +36,8 @@ __asm__ __volatile__("decl _intr_count")
extern int EISA_bus;
#define MCA_bus 0
#include <linux/binfmts.h>
#include <linux/personality.h>
#include <linux/tasks.h>
#include <asm/system.h>
......@@ -228,7 +230,6 @@ struct mm_struct {
short swap_page; /* current page */
#endif NEW_SWAP
struct vm_area_struct * mmap;
struct vm_area_struct * stk_vma;
};
#define INIT_MM { \
......@@ -240,7 +241,7 @@ struct mm_struct {
/* ?_flt */ 0, 0, 0, 0, \
0, \
/* swap */ 0, 0, 0, 0, 0, \
NULL, NULL }
NULL }
struct task_struct {
/* these are hardcoded - don't touch */
......@@ -252,12 +253,11 @@ struct task_struct {
unsigned long flags; /* per process flags, defined below */
int errno;
int debugreg[8]; /* Hardware debugging registers */
asmlinkage void (*lcall7)(struct pt_regs *);
struct exec_domain *exec_domain;
/* various fields */
struct linux_binfmt *binfmt;
struct task_struct *next_task, *prev_task;
struct sigaction sigaction[32];
unsigned long * signal_map;
unsigned long * signal_invmap;
unsigned long saved_kernel_stack;
unsigned long kernel_stack_page;
int exit_code, exit_signal;
......@@ -326,9 +326,10 @@ struct task_struct {
#define INIT_TASK \
/* state etc */ { 0,15,15,0,0,0,0, \
/* debugregs */ { 0, }, \
/* lcall 7 */ no_lcall7, \
/* exec domain */&default_exec_domain, \
/* binfmt */ NULL, \
/* schedlink */ &init_task,&init_task, \
/* signals */ {{ 0, },}, ident_map, ident_map, \
/* signals */ {{ 0, },}, \
/* stack */ 0,(unsigned long) &init_kernel_stack, \
/* ec,brk... */ 0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \
......@@ -361,9 +362,6 @@ extern unsigned long itimer_next;
extern struct timeval xtime;
extern int need_resched;
extern unsigned long ident_map[33];
extern asmlinkage void no_lcall7(struct pt_regs *);
#define CURRENT_TIME (xtime.tv_sec)
extern void sleep_on(struct wait_queue ** p);
......
......@@ -108,11 +108,11 @@ extern void skb_append(struct sk_buff *old,struct sk_buff *newsk);
extern void skb_unlink(struct sk_buff *buf);
extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list);
extern struct sk_buff * alloc_skb(unsigned int size, int priority);
extern void kfree_skbmem(void *mem, unsigned size);
extern void kfree_skbmem(struct sk_buff *skb, unsigned size);
extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
extern void skb_kept_by_device(struct sk_buff *skb);
extern void skb_device_release(struct sk_buff *skb,
int mode);
extern void skb_device_lock(struct sk_buff *skb);
extern void skb_device_unlock(struct sk_buff *skb);
extern void dev_kfree_skb(struct sk_buff *skb, int mode);
extern int skb_device_locked(struct sk_buff *skb);
/*
* Peek an sk_buff. Unlike most other operations you _MUST_
......
......@@ -33,12 +33,15 @@ struct linger {
#define AF_AX25 3
#define AF_IPX 4
#define AF_MAX 8 /* For now.. */
/* Protocol families, same as address families. */
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_AX25 AF_AX25
#define PF_IPX AF_IPX
#define PF_MAX AF_MAX
/* Flags we can use with send/ and recv. */
#define MSG_OOB 1
#define MSG_PEEK 2
......
......@@ -26,7 +26,7 @@
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
#define SIOCGSTAMP 0x8096 /* Get stamp */
#define SIOCGSTAMP 0x8906 /* Get stamp */
/* Routing table calls. */
#define SIOCADDRT 0x890B /* add routing table entry */
......
#ifndef _LINUX_UN_H
#define _LINUX_UN_H
#define UNIX_PATH_MAX 108
struct sockaddr_un {
unsigned short sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
#endif /* _LINUX_UN_H */
......@@ -142,6 +142,7 @@
#define __NR_fchdir 133
#define __NR_bdflush 134
#define __NR_sysfs 135
#define __NR_personality 136
extern int errno;
......
......@@ -16,7 +16,7 @@
.c.o:
$(CC) $(CFLAGS) -c $<
OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o \
OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o exec_domain.o \
panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o \
signal.o ptrace.o ioport.o itimer.o \
info.o ldt.o time.o tqueue.o vm86.o
......
#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/sched.h>
static asmlinkage void no_lcall7(struct pt_regs * regs);
static unsigned long ident_map[32] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31
};
struct exec_domain default_exec_domain = {
"Linux", /* name */
no_lcall7, /* lcall7 causes a seg fault. */
0, 0xff, /* All personalities. */
ident_map, /* Identiy map signals. */
ident_map, /* - both ways. */
NULL, /* No usage counter. */
NULL /* Nothing after this in the list. */
};
static struct exec_domain *exec_domains = &default_exec_domain;
static asmlinkage void no_lcall7(struct pt_regs * regs)
{
send_sig(SIGSEGV, current, 1);
}
struct exec_domain *lookup_exec_domain(unsigned long personality)
{
unsigned long pers = personality & PER_MASK;
struct exec_domain *it;
for (it=exec_domains; it; it=it->next)
if (pers >= it->pers_low
&& pers <= it->pers_high)
return it;
/* Should never get this far. */
printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
return NULL;
}
int register_exec_domain(struct exec_domain *it)
{
struct exec_domain *tmp;
if (!it)
return -EINVAL;
if (it->next)
return -EBUSY;
for (tmp=exec_domains; tmp; tmp=tmp->next)
if (tmp == it)
return -EBUSY;
it->next = exec_domains;
exec_domains = it;
return 0;
}
int unregister_exec_domain(struct exec_domain *it)
{
struct exec_domain ** tmp;
tmp = &exec_domains;
while (*tmp) {
if (it == *tmp) {
*tmp = it->next;
it->next = NULL;
return 0;
}
tmp = &(*tmp)->next;
}
return -EINVAL;
}
asmlinkage int sys_personality(unsigned long personality)
{
struct exec_domain *it;
unsigned long old_personality;
if (personality == 0xffffffff)
return current->personality;
it = lookup_exec_domain(personality);
if (!it)
return -EINVAL;
old_personality = current->personality;
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
current->personality = personality;
current->exec_domain = it;
if (current->exec_domain->use_count)
(*current->exec_domain->use_count)++;
return old_personality;
}
......@@ -483,6 +483,10 @@ NORET_TYPE void do_exit(long code)
#ifdef DEBUG_PROC_TREE
audit_ptree();
#endif
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)--;
schedule();
/*
* In order to get rid of the "volatile function does return" message
......
......@@ -94,7 +94,6 @@ static int dup_mmap(struct task_struct * tsk)
struct vm_area_struct * mpnt, **p, *tmp;
tsk->mm->mmap = NULL;
tsk->mm->stk_vma = NULL;
p = &tsk->mm->mmap;
for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
tmp = (struct vm_area_struct *) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
......@@ -107,8 +106,6 @@ static int dup_mmap(struct task_struct * tsk)
tmp->vm_inode->i_count++;
*p = tmp;
p = &tmp->vm_next;
if (current->mm->stk_vma == mpnt)
tsk->mm->stk_vma = tmp;
}
return 0;
}
......@@ -184,6 +181,12 @@ asmlinkage int sys_fork(struct pt_regs regs)
goto bad_fork_free;
task[nr] = p;
*p = *current;
if (p->exec_domain && p->exec_domain->use_count)
(*p->exec_domain->use_count)++;
if (p->binfmt && p->binfmt->use_count)
(*p->binfmt->use_count)++;
p->did_exec = 0;
p->kernel_stack_page = 0;
p->state = TASK_UNINTERRUPTIBLE;
......
......@@ -306,7 +306,7 @@ void free_irq(unsigned int irq)
static void math_error_irq(int cpl)
{
outb(0,0xF0);
if (ignore_irq13)
if (ignore_irq13 || !hard_math)
return;
math_error();
}
......
......@@ -16,6 +16,7 @@
#include <linux/utsname.h>
#include <linux/interrupt.h>
#include <linux/binfmts.h>
#include <linux/personality.h>
#ifdef CONFIG_INET
#include <linux/netdevice.h>
#endif
......@@ -61,7 +62,7 @@ struct {
X(wp_works_ok),
/* process memory management */
X(__verify_write),
X(verify_area),
X(do_mmap),
X(do_munmap),
X(insert_vm_struct),
......@@ -97,6 +98,11 @@ struct {
X(register_binfmt),
X(unregister_binfmt),
/* execution environment registration */
X(lookup_exec_domain),
X(register_exec_domain),
X(unregister_exec_domain),
/* interrupt handling */
X(request_irq),
X(free_irq),
......
......@@ -58,8 +58,10 @@ static int write_ldt(void * ptr, unsigned long bytecount)
limit *= PAGE_SIZE;
limit += base;
#ifdef NOTDEF_KLUDGE
if (limit < base || limit >= 0xC0000000)
return -EINVAL;
#endif
if (!current->ldt) {
for (i=1 ; i<NR_TASKS ; i++) {
......@@ -88,7 +90,8 @@ static int write_ldt(void * ptr, unsigned long bytecount)
((ldt_info.read_exec_only ^ 1) << 9) |
(ldt_info.seg_32bit << 22) |
(ldt_info.limit_in_pages << 23) |
0xf000;
((ldt_info.seg_not_present ^1) << 15) |
0x7000;
return 0;
}
......
......@@ -18,8 +18,6 @@
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
extern int core_dump(long signr,struct pt_regs * regs);
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
......@@ -246,7 +244,10 @@ static void setup_frame(struct sigaction * sa, unsigned long ** fp, unsigned lon
do_exit(SIGSEGV);
/* set up the "normal" stack seen by the signal handler (iBCS2) */
put_fs_long(__CODE,frame);
put_fs_long(current->signal_invmap[signr], frame+1);
if (current->exec_domain && current->exec_domain->signal_invmap)
put_fs_long(current->exec_domain->signal_invmap[signr], frame+1);
else
put_fs_long(signr, frame+1);
put_fs_long(regs->gs, frame+2);
put_fs_long(regs->fs, frame+3);
put_fs_long(regs->es, frame+4);
......@@ -348,8 +349,10 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV:
if (core_dump(signr,regs))
signr |= 0x80;
if (current->binfmt && current->binfmt->core_dump) {
if (current->binfmt->core_dump(signr, regs))
signr |= 0x80;
}
/* fall through */
default:
current->signal |= _S(signr & 0x7f);
......
......@@ -39,6 +39,9 @@ asmlinkage int sys_idle(void)
{
int i;
if (current->pid != 0)
return -EPERM;
/* Map out the low memory: it's no longer needed */
for (i = 0 ; i < 768 ; i++)
swapper_pg_dir[i] = 0;
......
......@@ -78,7 +78,7 @@ flags = 20
errno = 24
dbgreg6 = 52
dbgreg7 = 56
lcall7 = 60
exec_domain = 60
ENOSYS = 38
......@@ -144,7 +144,8 @@ _lcall7:
movl %esp,%eax
movl _current,%edx
pushl %eax
movl lcall7(%edx),%edx
movl exec_domain(%edx),%edx # Get the execution domain
movl 4(%edx),%edx # Get the lcall7 handler for the domain
call *%edx
popl %eax
jmp ret_from_sys_call
......@@ -535,5 +536,6 @@ _sys_call_table:
.long _sys_fchdir
.long _sys_bdflush
.long _sys_sysfs /* 135 */
.long _sys_personality
.space (NR_syscalls-135)*4
.space (NR_syscalls-136)*4
......@@ -40,7 +40,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
}
#define get_seg_byte(seg,addr) ({ \
register char __res; \
register unsigned char __res; \
__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
:"=a" (__res):"0" (seg),"m" (*(addr))); \
__res;})
......@@ -123,21 +123,30 @@ DO_ERROR( 7, SIGSEGV, "device not available", device_not_available, current)
DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current)
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math)
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
DO_ERROR(11, SIGSEGV, "segment not present", segment_not_present, current)
DO_ERROR(12, SIGSEGV, "stack segment", stack_segment, current)
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current)
DO_ERROR(15, SIGSEGV, "reserved", reserved, current)
DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{
int signr = SIGSEGV;
if (regs->eflags & VM_MASK) {
handle_vm86_fault((struct vm86_regs *) regs, error_code);
return;
}
die_if_kernel("general protection",regs,error_code);
switch (get_seg_byte(regs->cs, (char *)regs->eip)) {
case 0xCD: /* INT */
case 0xF4: /* HLT */
case 0xFA: /* CLI */
case 0xFB: /* STI */
signr = SIGILL;
}
current->tss.error_code = error_code;
current->tss.trap_no = 13;
send_sig(SIGSEGV, current, 1);
die_if_kernel("general protection",regs,error_code);
send_sig(signr, current, 1);
}
asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
......
......@@ -59,6 +59,7 @@ extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */
extern void sound_mem_init(void);
extern void die_if_kernel(char *,struct pt_regs *,long);
extern void show_net_buffers(void);
/*
* The free_area_list arrays point to the queue heads of the free areas
......@@ -78,11 +79,11 @@ unsigned short * mem_map = NULL;
/*
* oom() prints a message (so that the user knows why the process died),
* and gives the process an untrappable SIGSEGV.
* and gives the process an untrappable SIGKILL.
*/
void oom(struct task_struct * task)
{
printk("\nout of memory\n");
printk("\nOut of memory.\n");
task->sigaction[SIGKILL-1].sa_handler = NULL;
task->blocked &= ~(1<<(SIGKILL-1));
send_sig(SIGKILL,task,1);
......@@ -660,7 +661,7 @@ void do_wp_page(unsigned long error_code, unsigned long address,
*pg_table = 0;
}
int __verify_write(unsigned long start, unsigned long size)
static int __verify_write(unsigned long start, unsigned long size)
{
size--;
size += start & ~PAGE_MASK;
......@@ -673,6 +674,38 @@ int __verify_write(unsigned long start, unsigned long size)
return 0;
}
int verify_area(int type, const void * addr, unsigned long size)
{
struct vm_area_struct * vma;
for (vma = current->mm->mmap ; ; vma = vma->vm_next) {
if (!vma)
goto bad_area;
if (vma->vm_end > (unsigned long) addr)
break;
}
if (vma->vm_start <= (unsigned long) addr)
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
if (vma->vm_end - (unsigned long) addr > current->rlim[RLIMIT_STACK].rlim_cur)
goto bad_area;
good_area:
while (vma->vm_end - (unsigned long) addr < size) {
struct vm_area_struct * next = vma->vm_next;
if (!next)
goto bad_area;
if (vma->vm_end != next->vm_start)
goto bad_area;
vma = next;
}
if (wp_works_ok || type == VERIFY_READ || !size)
return 0;
return __verify_write((unsigned long) addr,size);
bad_area:
return -EFAULT;
}
static inline void get_empty_page(struct task_struct * tsk, unsigned long address)
{
unsigned long tmp;
......@@ -843,8 +876,8 @@ void do_no_page(unsigned long error_code, unsigned long address,
tmp = *(unsigned long *) page;
if (tmp & PAGE_PRESENT)
return;
++tsk->mm->rss;
if (tmp) {
++tsk->mm->rss;
++tsk->mm->maj_flt;
swap_in((unsigned long *) page);
return;
......@@ -859,10 +892,12 @@ void do_no_page(unsigned long error_code, unsigned long address,
continue;
}
if (!mpnt->vm_ops || !mpnt->vm_ops->nopage) {
++tsk->mm->rss;
++tsk->mm->min_flt;
get_empty_page(tsk,address);
return;
}
++tsk->mm->rss;
mpnt->vm_ops->nopage(error_code, mpnt, address);
return;
}
......@@ -870,7 +905,7 @@ void do_no_page(unsigned long error_code, unsigned long address,
goto ok_no_page;
if (address >= tsk->mm->end_data && address < tsk->mm->brk)
goto ok_no_page;
if (mpnt && mpnt == tsk->mm->stk_vma &&
if (mpnt && (mpnt->vm_flags & VM_GROWSDOWN) &&
address - tmp > mpnt->vm_start - address &&
tsk->rlim[RLIMIT_STACK].rlim_cur > mpnt->vm_end - address) {
mpnt->vm_start = address;
......@@ -883,6 +918,7 @@ void do_no_page(unsigned long error_code, unsigned long address,
if (error_code & 4) /* user level access? */
return;
ok_no_page:
++tsk->mm->rss;
++tsk->mm->min_flt;
get_empty_page(tsk,address);
}
......@@ -1021,6 +1057,7 @@ void show_mem(void)
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
show_buffers();
show_net_buffers();
}
extern unsigned long free_area_init(unsigned long, unsigned long);
......
......@@ -340,6 +340,7 @@ int generic_mmap(struct inode * inode, struct file * file,
mpnt->vm_start = addr;
mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL;
mpnt->vm_inode = inode;
inode->i_count++;
......@@ -459,6 +460,7 @@ static int anon_map(struct inode *ino, struct file * file,
mpnt->vm_start = addr;
mpnt->vm_end = addr + len;
mpnt->vm_page_prot = mask;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL;
mpnt->vm_inode = NULL;
mpnt->vm_offset = 0;
......
This is snapshot 014
This is snapshot 015
Changes for the 015 snapshot
o All read/write buffers are validated at the top level _only_
o All address structures are moved to and from user mode at the top
level. Thus you can now issue proto->bind(....) calls and related
functions such as connect from another kernel task. All thats left
to fix now is a kernel alloc_socket()/free_socket() and accompanying
proto->make_kernel(socket)
o Small fixes to address behaviour caused by the above
o Max NFS size of 16K bytes
o Added the apricot driver as a test (#'ed out in config.in)
o Fixed a missing function definition in net_init.c
o Added G4KLX ax25_router code
o Added Niibe's PLIP driver and altered it to support timer
configuration and IRQ/port setting. Added if_plip.h. Comments and
feedback appreciated on this (both to Niibe and me).
o Added AF_MAX/PF_MAX defines
o Added a note that the DE600 driver also works for a noname 'PE1200'.
o Network buffer statistics on shift-scroll_lock
o Fixed a serious race in the device driver code. This was causing odd
crashes with the Lance drivers, lockups with the ne2000 cards and
a few other 'bad' goings on. All drivers are effected. See
README.DEV if porting a driver to this revision.
If you see entries in your 'free while locked' count, those would
typically have crashed a pre 1.20 kernel.
o TCP keeps the timers above 0.2sec round-trip time because of the use of
delayed ACK's by BSD style kernels.
o Fixed a small BSD error in the return from datagram socket
recv/recvfrom() calls when data is truncated. BSD returns the true
length of the message, Linux returned the amount copied which broke
programs that did a MSG_PEEK with a small buffer and grew it if need
be (some of the AV/RTP stuff notably).
o Added TIOCINQ/OUTQ to AX.25 and IPX.
o Added driver ioctl() calls to IPX.
o Corrected the skb->len==0 in the tcp_data reset on shutdown to check
skb->copied_seq.
o IP options reflect onto SO_PRIORITY.
o When a driver is downed its ARP entries are flushed. Should solve
the occasional crash when taking out a modular driver.
o Added Donald's multicast reception while promiscuous fix for the
8390 drivers.
o Potential ARP TCP-retransmit clear race fixed. Incredibly
unlikely to occur but no doubt it will 8(.
To Do
o Fast path the tcp for packets in order with no flags set - we ought
to hit cable speed on slower machines if we fix that and the below.
(under test - define TCP_FASTPATH in tcp.c if you want to be brave
and report any findings.)
o Include the HP onboard lance fixes.
o Fix Unix domain sockets.
o Fix the _SLOW_ TCP window calculation junk in tcp_data/tcp_ack.
o Make the dev_add_proto() list hashed by protocol type.
o Remove the call to dev->header_type - load it into the skbuff.
instead to avoid the extra calls and cache misses.
o Include new sk_buff skb_push() code and move toward using it.
o Fix the PI driver so pi0a can be down when pi0b is up without getting
crashes. Also fix the stuff to allow piconfig to set the parameters.
o Make AX.25 set the packet type - certainly before it hits IP.
o sk_buff building at the top level - pure kernel interfaces to the
protocol layers
o Clean up NFS, merge NFS/TCP code.
o SIGIO
o IP forwarding use of options properly (needs new sk_buff code)
o Reroute TCP retransmits if needed (needs new sk_buffs)
Fixes added for 1.1.19
o Unix domain bind error code.
o skb->localroute starts cleared.
o Compiles with networking disabled
Fixes added for 1.1.18
o Dummy driver includes correctly.
o PPP fixes from A.L.
o ifslave fixes
o Small error causing nfsd to coredump fixed by Linus.
Fixes added for 1.1.17
......@@ -10,10 +93,12 @@ o Module fixes by Bj0rn.
o PLIP fix by Tanabe.
Fixes added for 1.1.16
o Charles Hedricks fixes to TCP.
o Small fixes all over the place.
Fixes added for 1.1.15
o Modular PLIP and 3c501 drivers. Now you -can- have multiple 3c501's
(sort of).
o Integrated new AX.25 - this will be ready for the big time in a few
......
This diff is collapsed.
......@@ -27,6 +27,7 @@
*
* Ross Martin : Rewrote arp_rcv() and arp_get_info()
* Stephen Henson : Add AX25 support to arp_get_info()
* Alan Cox : Drop data when a device is downed.
*/
#include <linux/types.h>
......@@ -228,20 +229,62 @@ static void arp_check_expire(unsigned long dummy)
static void arp_release_entry(struct arp_table *entry)
{
struct sk_buff *skb;
unsigned long flags;
if (entry->flags & ATF_PUBL)
proxies--;
save_flags(flags);
cli();
/* Release the list of `skb' pointers. */
while ((skb = skb_dequeue(&entry->skb)) != NULL)
{
if (skb->free)
kfree_skb(skb, FREE_WRITE);
skb_device_lock(skb);
restore_flags(flags);
dev_kfree_skb(skb, FREE_WRITE);
}
restore_flags(flags);
del_timer(&entry->timer);
kfree_s(entry, sizeof(struct arp_table));
return;
}
/*
* Purge a device from the ARP queue
*/
void arp_device_down(struct device *dev)
{
int i;
unsigned long flags;
/*
* This is a bit OTT - maybe we need some arp semaphores instead.
*/
save_flags(flags);
cli();
for (i = 0; i < ARP_TABLE_SIZE; i++)
{
struct arp_table *entry;
struct arp_table **pentry = &arp_tables[i];
while ((entry = *pentry) != NULL)
{
if(entry->dev==dev)
{
*pentry = entry->next; /* remove from list */
if (entry->flags & ATF_PUBL)
proxies--;
del_timer(&entry->timer); /* Paranoia */
kfree_s(entry, sizeof(struct arp_table));
}
else
pentry = &entry->next; /* go to next entry */
}
}
restore_flags(flags);
}
/*
* Create and send an arp packet. If (dest_hw == NULL), we create a broadcast
......@@ -393,6 +436,7 @@ static void arp_send_q(struct arp_table *entry, unsigned char *hw_dest)
{
struct sk_buff *skb;
unsigned long flags;
/*
* Empty the entire queue, building its data up ready to send
......@@ -405,9 +449,14 @@ static void arp_send_q(struct arp_table *entry, unsigned char *hw_dest)
return;
}
save_flags(flags);
cli();
while((skb = skb_dequeue(&entry->skb)) != NULL)
{
IS_SKB(skb);
skb_device_lock(skb);
restore_flags(flags);
if(!skb->dev->rebuild_header(skb->data,skb->dev,skb->raddr,skb))
{
skb->arp = 1;
......@@ -419,12 +468,13 @@ static void arp_send_q(struct arp_table *entry, unsigned char *hw_dest)
else
{
/* This routine is only ever called when 'entry' is
complete. Thus this can't fail (but does) */
complete. Thus this can't fail. */
printk("arp_send_q: The impossible occurred. Please notify Alan.\n");
printk("arp_send_q: active entity %s\n",in_ntoa(entry->ip));
printk("arp_send_q: failed to find %s\n",in_ntoa(skb->raddr));
}
}
restore_flags(flags);
}
......
......@@ -4,6 +4,7 @@
extern void arp_init(void);
extern void arp_destroy(unsigned long paddr, int force);
extern void arp_device_down(struct device *dev);
extern int arp_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt);
extern int arp_find(unsigned char *haddr, unsigned long paddr,
......
......@@ -16,6 +16,11 @@
* Alan Cox <gw4pts@gw4pts.ampr.org>
* David Hinds <dhinds@allegro.stanford.edu>
*
* Changes:
* Alan Cox : device private ioctl copies fields back.
* Alan Cox : Transmit queue code does relevant stunts to
* keep the queue safe.
*
* Cleaned up and recommented by Alan Cox 2nd April 1994. I hope to have
* the rest as well commented in the end.
*/
......@@ -292,7 +297,8 @@ int dev_close(struct device *dev)
*/
#ifdef CONFIG_INET
ip_rt_flush(dev);
#endif
arp_device_down(dev);
#endif
#ifdef CONFIG_IPX
ipxrtr_device_down(dev);
#endif
......@@ -321,6 +327,10 @@ int dev_close(struct device *dev)
/*
* Send (or queue for sending) a packet.
*
* IMPORTANT: When this is called to resend frames. The caller MUST
* already have locked the sk_buff. Apart from that we do the
* rest of the magic.
*/
void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
......@@ -328,13 +338,16 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
unsigned long flags;
int where = 0; /* used to say if the packet should go */
/* at the front or the back of the */
/* queue. */
/* queue - front is a retranmsit try */
if (dev == NULL)
{
printk("dev.c: dev_queue_xmit: dev = NULL\n");
return;
}
if(pri>=0 && !skb_device_locked(skb))
skb_device_lock(skb); /* Shove a lock on the frame */
#ifdef CONFIG_SLAVE_BALANCING
save_flags(flags);
cli();
......@@ -386,6 +399,7 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
*/
if (!skb->arp && dev->rebuild_header(skb->data, dev, skb->raddr, skb)) {
skb_device_unlock(skb); /* It's now safely on the arp queue */
return;
}
......@@ -396,7 +410,9 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
skb->in_dev_queue=1;
#endif
skb_queue_tail(dev->buffs + pri,skb);
skb_device_unlock(skb); /* Buffer is on the device queue and can be freed safely */
skb = skb_dequeue(dev->buffs + pri);
skb_device_lock(skb); /* New buffer needs locking down */
#ifdef CONFIG_SLAVE_BALANCING
skb->in_dev_queue=0;
#endif
......@@ -404,6 +420,9 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
restore_flags(flags);
if (dev->hard_start_xmit(skb, dev) == 0) {
/*
* Packet is now solely the responsibility of the driver
*/
#ifdef CONFIG_SLAVE_BALANCING
dev->pkt_queue--;
#endif
......@@ -411,13 +430,15 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
}
/*
* Transmission failed, put skb back into a list.
* Transmission failed, put skb back into a list. Once on the list its safe and
* no longer device locked (it can be freed safely from the device queue)
*/
cli();
#ifdef CONFIG_SLAVE_BALANCING
skb->in_dev_queue=1;
dev->pkt_queue++;
#endif
skb_device_unlock(skb);
skb_queue_head(dev->buffs + pri,skb);
restore_flags(flags);
}
......@@ -783,7 +804,9 @@ void dev_tint(struct device *dev)
{
int i;
struct sk_buff *skb;
unsigned long flags;
save_flags(flags);
/*
* Work the queues in priority order
*/
......@@ -794,8 +817,15 @@ void dev_tint(struct device *dev)
* Pull packets from the queue
*/
cli();
while((skb=skb_dequeue(&dev->buffs[i]))!=NULL)
{
/*
* Stop anyone freeing the buffer while we retransmit it
*/
skb_device_lock(skb);
restore_flags(flags);
/*
* Feed them to the output stage and if it fails
* indicate they re-queue at the front.
......@@ -806,8 +836,10 @@ void dev_tint(struct device *dev)
*/
if (dev->tbusy)
return;
cli();
}
}
restore_flags(flags);
}
......@@ -1222,7 +1254,9 @@ static int dev_ifsioc(void *arg, unsigned int getset)
case SIOCDEVPRIVATE:
if(dev->do_ioctl==NULL)
return -EOPNOTSUPP;
return dev->do_ioctl(dev, &ifr);
ret=dev->do_ioctl(dev, &ifr);
memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
break;
case SIOCGIFMAP:
ifr.ifr_map.mem_start=dev->mem_start;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment