diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/Configure.help linux/Documentation/Configure.help --- linux.vanilla/Documentation/Configure.help Fri Aug 30 14:49:08 2002 +++ linux/Documentation/Configure.help Fri Aug 30 14:57:33 2002 @@ -2088,7 +2088,7 @@ Also SL/SLC/SLC2/SLC3/SX/SX2, NexGen Nx586 and UMC U5D or U5S. "586/K5/5x86/6x86" Select this for an x586 or x686 processor such - as the AMD K5, the Intel 5x86 or 6x86, or the Intel 6x86MX. + as the AMD K5, the Cyrix 5x86 or 6x86, or the Cyrix 6x86MX. This choice does not assume the RDTSC (time stamp counter) instruction. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- linux.vanilla/Documentation/usb/ov511.txt Sun Mar 25 17:32:00 2001 +++ linux/Documentation/usb/ov511.txt Fri Aug 30 15:28:07 2002 @@ -178,16 +178,6 @@ programs that expect RGB data (e.g. gqcam) to work with this driver. If your colors look VERY wrong, you may want to change this. - NAME: buf_timeout - TYPE: integer - DEFAULT: 5 (seconds) - DESC: Number of seconds before unused frame buffers are deallocated. - Previously, memory was allocated upon open() and deallocated upon - close(). Deallocation now occurs only if the driver is closed and this - timeout is reached. If you are capturing frames less frequently than - the default timeout, increase this. This will not make any difference - with programs that capture multiple frames during an open/close cycle. - NAME: cams TYPE: integer (1-4 for OV511, 1-31 for OV511+) DEFAULT: 1 @@ -242,7 +232,7 @@ HOW TO CONTACT ME: -You can email me at mwm@i.am . Please prefix the subject line +You can email me at mark@alpha.dyndns.org . Please prefix the subject line with "OV511: " so that I am certain to notice your message. CREDITS: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/MAINTAINERS linux/MAINTAINERS --- linux.vanilla/MAINTAINERS Fri Aug 30 14:49:08 2002 +++ linux/MAINTAINERS Fri Aug 30 15:02:33 2002 @@ -1176,6 +1176,11 @@ W: http://cvs.conectiva.com.br/drivers/ZFL-watchdog/ S: Maintained +LINUX 2.2 FIXES +P: Alan Cox +M: alan@lxorguk.ukuu.org.uk +S: Maintained + THE REST P: Linus Torvalds S: Buried alive in reporters diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Makefile linux/Makefile --- linux.vanilla/Makefile Fri Aug 30 14:49:08 2002 +++ linux/Makefile Mon Sep 16 16:15:34 2002 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 2 -SUBLEVEL = 21 +SUBLEVEL = 22 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- linux.vanilla/arch/alpha/kernel/entry.S Fri Nov 2 16:39:05 2001 +++ linux/arch/alpha/kernel/entry.S Fri Aug 30 14:57:33 2002 @@ -556,7 +556,7 @@ lda $5,sys_call_table lda $27,sys_ni_syscall cmpult $0,$4,$4 - ldq $3,TASK_FLAGS($8) + ldq $3,TASK_PTRACE($8) stq $17,SP_OFF+32($30) s8addq $0,$5,$5 and $3,PT_PTRACED,$3 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- linux.vanilla/arch/i386/kernel/apm.c Sun Mar 25 17:37:29 2001 +++ linux/arch/i386/kernel/apm.c Fri Aug 30 15:18:00 2002 @@ -1072,7 +1072,7 @@ as = fp->private_data; if (check_apm_user(as, "read")) return -EIO; - if (count < sizeof(apm_event_t)) + if ((int)count < sizeof(apm_event_t)) return -EINVAL; if (queue_empty(as)) { if (fp->f_flags & O_NONBLOCK) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- linux.vanilla/arch/i386/kernel/mtrr.c Sun Mar 25 17:31:45 2001 +++ linux/arch/i386/kernel/mtrr.c Fri Aug 30 15:18:27 2002 @@ -1337,8 +1337,11 @@ static ssize_t mtrr_read (struct file *file, char *buf, size_t len, loff_t *ppos) { + if (*ppos < 0) return -EINVAL; if (*ppos >= ascii_buf_bytes) return 0; - if (*ppos + len > ascii_buf_bytes) len = ascii_buf_bytes - *ppos; + if (len > ascii_buf_bytes || + *ppos + len > ascii_buf_bytes) + len = ascii_buf_bytes - *ppos; if ( copy_to_user (buf, ascii_buffer + *ppos, len) ) return -EFAULT; *ppos += len; return len; @@ -1359,6 +1362,7 @@ if ( !suser () ) return -EPERM; /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) return -ESPIPE; + if (len < 1) return -EINVAL; memset (line, 0, LINE_SIZE); if (len > LINE_SIZE) len = LINE_SIZE; if ( copy_from_user (line, buf, len - 1) ) return -EFAULT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- linux.vanilla/arch/i386/kernel/setup.c Fri Aug 30 14:49:08 2002 +++ linux/arch/i386/kernel/setup.c Fri Aug 30 14:57:33 2002 @@ -635,6 +635,15 @@ l2size = 64; } + /* VIA C3 CPUs (Samuel2, Ezra & Ezra-T) need further shifting. */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && + boot_cpu_data.x86 == 6 && + (boot_cpu_data.x86_model == 7 || + boot_cpu_data.x86_model == 8)) + { + l2size = l2size >> 8; + } + if (l2size == 0) return; /* Again, no L2 cache is possible */ @@ -1056,13 +1065,18 @@ } /* Set 3DNow! on Winchip 2 and above. */ - if (c->x86_model >=8) + if (c->x86_model >=8) { c->x86_capability |= X86_FEATURE_AMD3D; - + get_model_name(c); + display_cacheinfo(c); + } c->x86_capability |=X86_FEATURE_CX8; } /* Cyrix III 'Samuel' CPU */ - if(c->x86 == 6 && c->x86_model == 6) + if(c->x86 == 6 && + (c->x86_model == 6 || + c->x86_model == 7 || + c->x86_model == 8)) { rdmsr(0x1107, lv, hv); lv|=(1<<1); /* Report CX8 */ @@ -1075,6 +1089,9 @@ cpuid(0x80000001, &lv, &lv, &lv, &hv); if(hv&(1<<31)) c->x86_capability |= X86_FEATURE_AMD3D; + + get_model_name(c); + display_cacheinfo(c); } } @@ -1278,6 +1295,10 @@ { X86_VENDOR_CENTAUR, 5, { NULL, NULL, NULL, NULL, "C6", NULL, NULL, NULL, "C6-2", NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, + { X86_VENDOR_CENTAUR, 6, + { NULL, NULL, NULL, NULL, NULL, NULL, "Samuel 1", + "Samuel 2/Ezra", "Ezra-T", NULL, NULL, + NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_NEXGEN, 5, { "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/config.in linux/arch/sparc/config.in --- linux.vanilla/arch/sparc/config.in Sun Mar 25 17:37:30 2001 +++ linux/arch/sparc/config.in Fri Aug 30 15:03:56 2002 @@ -93,6 +93,9 @@ tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 fi +if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then + bool ' Boot support (linear, striped)' CONFIG_MD_BOOT +fi tristate 'RAM disk support' CONFIG_BLK_DEV_RAM if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- linux.vanilla/arch/sparc64/kernel/ioctl32.c Fri Aug 30 14:49:09 2002 +++ linux/arch/sparc64/kernel/ioctl32.c Fri Aug 30 15:18:52 2002 @@ -249,7 +249,7 @@ return -EINVAL; /* Peculiar interface... */ - if(nclips < 0) + if(nclips < 0 || nclips > VIDEO_CLIPMAP_SIZE) nclips = VIDEO_CLIPMAP_SIZE; kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/loop.c linux/drivers/block/loop.c --- linux.vanilla/drivers/block/loop.c Sun Mar 25 17:31:24 2001 +++ linux/drivers/block/loop.c Fri Sep 13 14:31:45 2002 @@ -334,8 +334,9 @@ set_fs(old_fs); if (retval < 0) { - printk(KERN_WARNING "loop: cannot create block - FS write failed: code %d\n", - retval); + printk(KERN_WARNING + "loop: cannot create block - FS write failed: code %d\n", + (int)retval); return FALSE; } else { return TRUE; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c --- linux.vanilla/drivers/cdrom/cdu31a.c Sun Mar 25 17:31:36 2001 +++ linux/drivers/cdrom/cdu31a.c Fri Aug 30 15:18:56 2002 @@ -3027,6 +3027,8 @@ return 0; } + if (ra.nframes > INT_MAX / CD_FRAMESIZE_RAW) + return -EINVAL; i=verify_area(VERIFY_WRITE, ra.buf, CD_FRAMESIZE_RAW * ra.nframes); if(i<0) return i; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/bttv.c linux/drivers/char/bttv.c --- linux.vanilla/drivers/char/bttv.c Fri Aug 30 14:49:09 2002 +++ linux/drivers/char/bttv.c Fri Aug 30 15:19:08 2002 @@ -1610,6 +1610,8 @@ struct bttv *btv= (struct bttv *)v; int q,todo; /* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */ + if (count > INT_MAX) + return -EINVAL; todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { @@ -1639,7 +1641,7 @@ } } } - if (todo) + if (todo > 0 && todo <= VBIBUF_SIZE-btv->vbip) { if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo)) return -EFAULT; @@ -1979,8 +1981,8 @@ vfree(vcp); return -EFAULT; } - } else if (vw.clipcount > 2048) - return -ENOMEM; + } else if (vw.clipcount > 2048) + return -EINVAL; else if (vw.clipcount) { if((vcp=vmalloc(sizeof(struct video_clip)* (vw.clipcount))) == NULL) @@ -2457,6 +2459,8 @@ struct bttv *btv=(struct bttv *)(v-2); int q,todo; + if (count > INT_MAX) + return -EINVAL; todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { @@ -2486,7 +2490,7 @@ } } } - if (todo) + if (todo > 0 && todo <= VBIBUF_SIZE-btv->vbip) { if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo)) return -EFAULT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/buz.c linux/drivers/char/buz.c --- linux.vanilla/drivers/char/buz.c Sun Mar 25 17:31:27 2001 +++ linux/drivers/char/buz.c Fri Aug 30 15:19:14 2002 @@ -2586,7 +2586,8 @@ /* Check for vaild parameters */ if (vw.width < BUZ_MIN_WIDTH || vw.height < BUZ_MIN_HEIGHT || - vw.width > BUZ_MAX_WIDTH || vw.height > BUZ_MAX_HEIGHT) { + vw.width > BUZ_MAX_WIDTH || vw.height > BUZ_MAX_HEIGHT || + vw.clipcount < 0 || vw.clipcount > 2048) { return -EINVAL; } #ifdef XAWTV_HACK diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/console.c linux/drivers/char/console.c --- linux.vanilla/drivers/char/console.c Sun Mar 25 17:37:31 2001 +++ linux/drivers/char/console.c Fri Aug 30 15:19:21 2002 @@ -2101,6 +2101,8 @@ return -EINVAL; if (current->tty != tty && !suser()) return -EPERM; + /* Further code uses __put_user() relying on this get_user() having + * done the address range checking. */ if (get_user(type, (char *)arg)) return -EFAULT; switch (type) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/consolemap.c linux/drivers/char/consolemap.c --- linux.vanilla/drivers/char/consolemap.c Sun Mar 25 17:31:25 2001 +++ linux/drivers/char/consolemap.c Fri Sep 13 14:29:37 2002 @@ -611,16 +611,18 @@ if ((p2 = *(p1++))) for (k = 0; k < 64; k++) { if (*p2 < MAX_GLYPH && ect++ < ct) { - __put_user((u_short)((i<<11)+(j<<6)+k), - &list->unicode); - __put_user((u_short) *p2, - &list->fontpos); + put_user_ret((u_short)((i<<11)+(j<<6)+k), + &list->unicode, + -EFAULT); + put_user_ret((u_short) *p2, + &list->fontpos, + -EFAULT); list++; } p2++; } } - __put_user(ect, uct); + put_user_ret(ect, uct, -EFAULT); return ((ect <= ct) ? 0 : -ENOMEM); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/lp.c linux/drivers/char/lp.c --- linux.vanilla/drivers/char/lp.c Fri Nov 2 16:39:06 2001 +++ linux/drivers/char/lp.c Fri Aug 30 15:19:30 2002 @@ -649,7 +649,7 @@ } if ((i & 1) != 0) { Byte |= (z<<4); - if (__put_user (Byte, temp)) + if (put_user (Byte, temp)) { count = -EFAULT; break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/planb.c linux/drivers/char/planb.c --- linux.vanilla/drivers/char/planb.c Fri Aug 30 14:49:09 2002 +++ linux/drivers/char/planb.c Fri Aug 30 15:19:38 2002 @@ -1750,6 +1750,11 @@ /* Reset clip mask */ memset ((void *) pb->mask, 0xff, (pb->maxlines * ((PLANB_MAXPIXELS + 7) & ~7)) / 8); + /* XXX: The first check may be optimized away if the + * compiler thinks a pointer can't wraparound */ + if (vw.clips + vw.clipcount < vw.clips || + vw.clipcount < 0 || vw.clipcount > 2048) + return -EINVAL; /* Add any clip rects */ for (i = 0; i < vw.clipcount; i++) { if (copy_from_user(&clip, vw.clips + i, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/vt.c linux/drivers/char/vt.c --- linux.vanilla/drivers/char/vt.c Sun Mar 25 17:31:24 2001 +++ linux/drivers/char/vt.c Fri Aug 30 15:19:45 2002 @@ -394,8 +394,9 @@ if (copy_from_user(&tmp, user_ud, sizeof tmp)) return -EFAULT; if (tmp.entries) { - i = verify_area(VERIFY_WRITE, tmp.entries, - tmp.entry_ct*sizeof(struct unipair)); + /* tmp.entry_ct is an unsigned short */ + i = verify_area(VERIFY_WRITE, tmp.entries, + (size_t)tmp.entry_ct * sizeof(struct unipair)); if (i) return i; } switch (cmd) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- linux.vanilla/drivers/isdn/isdn_common.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/isdn/isdn_common.c Fri Sep 13 14:31:20 2002 @@ -64,7 +64,7 @@ #endif /* CONFIG_ISDN_DIVERSION */ -static int isdn_writebuf_stub(int, int, const u_char *, int, int); +static ssize_t isdn_writebuf_stub(int, int, const u_char *, size_t, int); static void set_global_features(void); static int isdn_wildmat(char *s, char *p); @@ -1008,6 +1008,10 @@ goto out; } chidx = isdn_minor2chan(minor); + if (count > 131072) { + retval = -EINVAL; + goto out; + } if (!(p = kmalloc(count, GFP_KERNEL))) { retval = -ENOMEM; goto out; @@ -1099,9 +1103,11 @@ goto out; } chidx = isdn_minor2chan(minor); - while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count) + do { + retval = isdn_writebuf_stub(drvidx, chidx, buf, count, 1); + if (retval == count || retval < 0) break; interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]); - retval = count; + } while (1); goto out; } if (minor <= ISDN_MINOR_CTRLMAX) { @@ -1874,22 +1880,29 @@ /* * writebuf replacement for SKB_ABLE drivers */ -static int -isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len, +static ssize_t +isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, size_t len, int user) { - int ret; - int hl = dev->drv[drvidx]->interface->hl_hdrlen; - struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC); + int ret = 0; + unsigned int hl; + struct sk_buff *skb; + + hl = dev->drv[drvidx]->interface->hl_hdrlen; + if (len > INT_MAX / 2 || hl > INT_MAX / 2) + return -EINVAL; + skb = alloc_skb(hl + len, GFP_ATOMIC); if (!skb) - return 0; + return -ENOMEM; skb_reserve(skb, hl); if (user) - copy_from_user(skb_put(skb, len), buf, len); + ret = copy_from_user(skb_put(skb, len), buf, len) ? -EFAULT : 0; else memcpy(skb_put(skb, len), buf, len); - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb); + if (!ret) + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, + chan, 1, skb); if (ret <= 0) dev_kfree_skb(skb); if (ret > 0) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c --- linux.vanilla/drivers/isdn/isdn_ppp.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/isdn/isdn_ppp.c Fri Aug 30 15:19:59 2002 @@ -678,8 +678,8 @@ * reports, that there is data */ -int -isdn_ppp_read(int min, struct file *file, char *buf, int count) +ssize_t +isdn_ppp_read(int min, struct file *file, char *buf, size_t count) { struct ippp_struct *is; struct ippp_buf_queue *b; @@ -721,8 +721,8 @@ * ipppd wanna write a packet to the card .. non-blocking */ -int -isdn_ppp_write(int min, struct file *file, const char *buf, int count) +ssize_t +isdn_ppp_write(int min, struct file *file, const char *buf, size_t count) { isdn_net_local *lp; struct ippp_struct *is; @@ -757,7 +757,7 @@ if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && lp->dialstate == 0 && (lp->flags & ISDN_NET_CONNECTED)) { - unsigned short hl; + unsigned int hl; struct sk_buff *skb; /* * we need to reserve enought space in front of @@ -765,11 +765,11 @@ * 16 bytes, now we are looking what the driver want */ hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + if (hl > INT_MAX / 2 || count > INT_MAX / 2) + return -EINVAL; skb = alloc_skb(hl+count, GFP_ATOMIC); - if (!skb) { - printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); - return count; - } + if (!skb) + return -ENOMEM; skb_reserve(skb, hl); if (copy_from_user(skb_put(skb, count), buf, count)) { @@ -1170,7 +1170,7 @@ #ifdef CONFIG_ISDN_PPP_VJ if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */ struct sk_buff *new_skb; - unsigned short hl; + unsigned int hl; /* * we need to reserve enought space in front of * sk_buff. old call to dev_alloc_skb only reserved diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h --- linux.vanilla/drivers/isdn/isdn_ppp.h Fri Aug 30 14:49:10 2002 +++ linux/drivers/isdn/isdn_ppp.h Fri Aug 30 15:38:26 2002 @@ -12,8 +12,8 @@ #include /* for PPP_PROTOCOL */ #include /* for isdn_ppp info */ -extern int isdn_ppp_read(int, struct file *, char *, int); -extern int isdn_ppp_write(int, struct file *, const char *, int); +extern ssize_t isdn_ppp_read(int, struct file *, char *, size_t); +extern ssize_t isdn_ppp_write(int, struct file *, const char *, size_t); extern int isdn_ppp_open(int, struct file *); extern int isdn_ppp_init(void); extern void isdn_ppp_cleanup(void); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/pcbit/capi.c linux/drivers/isdn/pcbit/capi.c --- linux.vanilla/drivers/isdn/pcbit/capi.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/isdn/pcbit/capi.c Fri Aug 30 15:19:59 2002 @@ -425,7 +425,7 @@ #ifdef DEBUG printk(KERN_DEBUG "CPN: Octect 3 %02x\n", skb->data[1]); #endif - if ((skb->data[1] & 0x80) == 0) + if (len >= 2 && (skb->data[1] & 0x80) == 0) count = 2; if (!(info->data.setup.CallingPN = kmalloc(len - count + 1, GFP_ATOMIC))) @@ -453,7 +453,7 @@ if (len > 0) { int count = 1; - if ((skb->data[1] & 0x80) == 0) + if (len >= 2 && (skb->data[1] & 0x80) == 0) count = 2; if (!(info->data.setup.CalledPN = kmalloc(len - count + 1, GFP_ATOMIC))) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c --- linux.vanilla/drivers/isdn/pcbit/drv.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/isdn/pcbit/drv.c Fri Aug 30 15:20:12 2002 @@ -408,7 +408,7 @@ switch(dev->l2_state) { case L2_LWMODE: /* check (size <= rdp_size); write buf into board */ - if (len > BANK4 + 1) + if (len < 0 || len > BANK4 + 1 || len > 1024) { printk("pcbit_writecmd: invalid length %d\n", len); return -EFAULT; @@ -418,7 +418,7 @@ { u_char cbuf[1024]; - copy_from_user(cbuf, buf, len); + copy_from_user_ret(cbuf, buf, len, -EFAULT); for (i=0; ish_mem + i); } @@ -436,7 +436,7 @@ /* get it into kernel space */ if ((ptr = kmalloc(len, GFP_KERNEL))==NULL) return -ENOMEM; - copy_from_user(ptr, buf, len); + copy_from_user_ret(ptr, buf, len, -EFAULT); loadbuf = ptr; } else diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-hw-comx.c linux/drivers/net/comx-hw-comx.c --- linux.vanilla/drivers/net/comx-hw-comx.c Sun Mar 25 17:31:21 2001 +++ linux/drivers/net/comx-hw-comx.c Fri Aug 30 15:20:27 2002 @@ -1061,10 +1061,17 @@ if (!(page = (char *)__get_free_page(GFP_KERNEL))) { return -ENOMEM; } - copy_from_user(page, buffer, count = (min(count, PAGE_SIZE))); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, + count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; } else { byte *tmp; @@ -1077,6 +1084,8 @@ hw->firmware->data = NULL; } + if (file->f_pos > 0x10000 || count > 0x10000) + return -EINVAL; if ((tmp = kmalloc(count + file->f_pos, GFP_KERNEL)) == NULL) { return -ENOMEM; } @@ -1089,7 +1098,10 @@ if (hw->firmware->data) { kfree(hw->firmware->data); } - copy_from_user(tmp + file->f_pos, buffer, count); + if (copy_from_user(tmp + file->f_pos, buffer, count)) { + kfree(tmp); + return -EFAULT; + } hw->firmware->len = entry->size = file->f_pos + count; hw->firmware->data = tmp; file->f_pos += count; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-hw-locomx.c linux/drivers/net/comx-hw-locomx.c --- linux.vanilla/drivers/net/comx-hw-locomx.c Sun Mar 25 17:31:21 2001 +++ linux/drivers/net/comx-hw-locomx.c Fri Aug 30 15:20:27 2002 @@ -346,10 +346,16 @@ return -ENOMEM; } - copy_from_user(page, buffer, count = min(count, PAGE_SIZE)); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_IO) == 0) { val = simple_strtoul(page, NULL, 0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-hw-mixcom.c linux/drivers/net/comx-hw-mixcom.c --- linux.vanilla/drivers/net/comx-hw-mixcom.c Sun Mar 25 17:31:21 2001 +++ linux/drivers/net/comx-hw-mixcom.c Fri Aug 30 15:20:27 2002 @@ -758,10 +758,16 @@ return -ENOMEM; } - copy_from_user(page, buffer, count = min(count, PAGE_SIZE)); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_IO) == 0) { value = simple_strtoul(page, NULL, 0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-proto-fr.c linux/drivers/net/comx-proto-fr.c --- linux.vanilla/drivers/net/comx-proto-fr.c Sun Mar 25 17:31:21 2001 +++ linux/drivers/net/comx-proto-fr.c Fri Aug 30 15:20:27 2002 @@ -666,10 +666,16 @@ return -ENOMEM; } - copy_from_user(page, buffer, count); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_DLCI) == 0) { u16 dlci_new = simple_strtoul(page, NULL, 10); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-proto-lapb.c linux/drivers/net/comx-proto-lapb.c --- linux.vanilla/drivers/net/comx-proto-lapb.c Sun Mar 25 17:31:21 2001 +++ linux/drivers/net/comx-proto-lapb.c Fri Aug 30 15:20:27 2002 @@ -239,10 +239,16 @@ return -ENOMEM; } - copy_from_user(page, buffer, count); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_T1) == 0) { parm=simple_strtoul(page,NULL,10); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx.c linux/drivers/net/comx.c --- linux.vanilla/drivers/net/comx.c Sun Mar 25 17:31:21 2001 +++ linux/drivers/net/comx.c Fri Aug 30 15:20:36 2002 @@ -636,9 +636,16 @@ if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; - copy_from_user(page, buffer, count); - - if (*(page + count - 1) == '\n') *(page + count - 1) = 0; + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { + *(page + count - 1) = 0; + } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_DEBUG) == 0) { int i; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/depca.c linux/drivers/net/depca.c --- linux.vanilla/drivers/net/depca.c Sun Mar 25 17:31:16 2001 +++ linux/drivers/net/depca.c Fri Aug 30 15:20:36 2002 @@ -268,7 +268,7 @@ static int depca_debug = 1; #endif -#define DEPCA_NDA 0xffe0 /* No Device Address */ +#define DEPCA_NDA 0xffe0 /* No Device Address */ /* ** Ethernet PROM defines @@ -283,18 +283,18 @@ ** ** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ) */ -#define NUM_RX_DESC 8 /* Number of RX descriptors */ -#define NUM_TX_DESC 8 /* Number of TX descriptors */ -#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ -#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ +#define NUM_RX_DESC 8 /* Number of RX descriptors */ +#define NUM_TX_DESC 8 /* Number of TX descriptors */ +#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ +#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ +#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ +#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ /* ** EISA bus defines */ -#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ +#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ #define MAX_EISA_SLOTS 16 #define EISA_SLOT_INC 0x1000 @@ -321,7 +321,7 @@ "DE422",\ ""} static enum { - DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown + DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown } adapter; /* @@ -336,70 +336,71 @@ ** DESC_ALIGN. ALIGN aligns the start address of the private memory area ** and hence the RX descriptor ring's first entry. */ -#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ -#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */ -#define ALIGN ALIGN8 /* Keep the LANCE happy... */ +#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ +#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */ +#define ALIGN ALIGN8 /* Keep the LANCE happy... */ /* ** The DEPCA Rx and Tx ring descriptors. */ struct depca_rx_desc { - volatile s32 base; - s16 buf_length; /* This length is negative 2's complement! */ - s16 msg_length; /* This length is "normal". */ + volatile s32 base; + s16 buf_length; /* This length is negative 2's complement! */ + s16 msg_length; /* This length is "normal". */ }; struct depca_tx_desc { - volatile s32 base; - s16 length; /* This length is negative 2's complement! */ - s16 misc; /* Errors and TDR info */ + volatile s32 base; + s16 length; /* This length is negative 2's complement! */ + s16 misc; /* Errors and TDR info */ }; -#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM +#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM to LANCE memory address space */ /* ** The Lance initialization block, described in databook, in common memory. */ struct depca_init { - u16 mode; /* Mode register */ - u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */ - u8 mcast_table[8]; /* Multicast Hash Table. */ - u32 rx_ring; /* Rx ring base pointer & ring length */ - u32 tx_ring; /* Tx ring base pointer & ring length */ + u16 mode; /* Mode register */ + u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */ + u8 mcast_table[8]; /* Multicast Hash Table. */ + u32 rx_ring; /* Rx ring base pointer & ring length */ + u32 tx_ring; /* Tx ring base pointer & ring length */ }; #define DEPCA_PKT_STAT_SZ 16 -#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you - increase DEPCA_PKT_STAT_SZ */ +#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you + increase DEPCA_PKT_STAT_SZ */ struct depca_private { - char devname[DEPCA_STRLEN]; /* Device Product String */ - char adapter_name[DEPCA_STRLEN];/* /proc/ioports string */ - char adapter; /* Adapter type */ - char mca_slot; /* MCA slot, if MCA else -1 */ struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */ - struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */ - struct depca_init init_block;/* Shadow Initialization block */ - char *rx_memcpy[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ - char *tx_memcpy[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ - u_long bus_offset; /* (E)ISA bus address offset vs LANCE */ - u_long sh_mem; /* Physical start addr of shared mem area */ - u_long dma_buffs; /* LANCE Rx and Tx buffers start address. */ - int rx_new, tx_new; /* The next free ring entry */ - int rx_old, tx_old; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - struct { /* Private stats counters */ - u32 bins[DEPCA_PKT_STAT_SZ]; - u32 unicast; - u32 multicast; - u32 broadcast; - u32 excessive_collisions; - u32 tx_underruns; - u32 excessive_underruns; - } pktStats; - int txRingMask; /* TX ring mask */ - int rxRingMask; /* RX ring mask */ - s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ - s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */ + char devname[DEPCA_STRLEN]; /* Device Product String */ + char adapter_name[DEPCA_STRLEN]; /* /proc/ioports string */ + char adapter; /* Adapter type */ + char mca_slot; /* MCA slot, if MCA else -1 */ + struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */ + struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */ + struct depca_init init_block; /* Shadow Initialization block */ + char *rx_memcpy[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ + char *tx_memcpy[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ + u_long bus_offset; /* (E)ISA bus address offset vs LANCE */ + u_long sh_mem; /* Physical start addr of shared mem area */ + u_long dma_buffs; /* LANCE Rx and Tx buffers start address. */ + int rx_new, tx_new; /* The next free ring entry */ + int rx_old, tx_old; /* The ring entries to be free()ed. */ + struct net_device_stats stats; + struct { /* Private stats counters */ + u32 bins[DEPCA_PKT_STAT_SZ]; + u32 unicast; + u32 multicast; + u32 broadcast; + u32 excessive_collisions; + u32 tx_underruns; + u32 excessive_underruns; + } pktStats; + int txRingMask; /* TX ring mask */ + int rxRingMask; /* RX ring mask */ + s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ + s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */ }; /* @@ -416,783 +417,766 @@ /* ** Public Functions */ -static int depca_open(struct device *dev); -static int depca_start_xmit(struct sk_buff *skb, struct device *dev); -static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static int depca_close(struct device *dev); -static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd); +static int depca_open(struct device *dev); +static int depca_start_xmit(struct sk_buff *skb, struct device *dev); +static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int depca_close(struct device *dev); +static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd); static struct net_device_stats *depca_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); +static void set_multicast_list(struct device *dev); /* ** Private functions */ -static int depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot); -static void depca_init_ring(struct device *dev); -static int depca_rx(struct device *dev); -static int depca_tx(struct device *dev); - -static void LoadCSRs(struct device *dev); -static int InitRestartDepca(struct device *dev); -static void DepcaSignature(char *name, u_long paddr); -static int DevicePresent(u_long ioaddr); -static int get_hw_addr(struct device *dev); -static int EISA_signature(char *name, s32 eisa_id); -static void SetMulticastFilter(struct device *dev); -static void isa_probe(struct device *dev, u_long iobase); -static void eisa_probe(struct device *dev, u_long iobase); -#ifdef CONFIG_MCA -static void mca_probe(struct device *dev, u_long iobase); +static int depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot); +static void depca_init_ring(struct device *dev); +static int depca_rx(struct device *dev); +static int depca_tx(struct device *dev); + +static void LoadCSRs(struct device *dev); +static int InitRestartDepca(struct device *dev); +static void DepcaSignature(char *name, u_long paddr); +static int DevicePresent(u_long ioaddr); +static int get_hw_addr(struct device *dev); +static int EISA_signature(char *name, s32 eisa_id); +static void SetMulticastFilter(struct device *dev); +static void isa_probe(struct device *dev, u_long iobase); +static void eisa_probe(struct device *dev, u_long iobase); +#ifdef CONFIG_MCA +static void mca_probe(struct device *dev, u_long iobase); #endif static struct device *alloc_device(struct device *dev, u_long iobase); -static int depca_dev_index(char *s); -static struct device *insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)); -static int load_packet(struct device *dev, struct sk_buff *skb); -static void depca_dbg_open(struct device *dev); +static int depca_dev_index(char *s); +static struct device *insert_device(struct device *dev, u_long iobase, int (*init) (struct device *)); +static int load_packet(struct device *dev, struct sk_buff *skb); +static void depca_dbg_open(struct device *dev); #ifdef MODULE -int init_module(void); -void cleanup_module(void); -static int autoprobed = 1, loading_module = 1; +int init_module(void); +void cleanup_module(void); +static int autoprobed = 1, loading_module = 1; # else -static u_char de1xx_irq[] __initdata = {2,3,4,5,7,9,0}; -static u_char de2xx_irq[] __initdata = {5,9,10,11,15,0}; -static u_char de422_irq[] __initdata = {5,9,10,11,0}; +static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 }; +static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 }; +static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 }; static u_char *depca_irq; -static int autoprobed = 0, loading_module = 0; -#endif /* MODULE */ +static int autoprobed = 0, loading_module = 0; +#endif /* MODULE */ -static char name[DEPCA_STRLEN]; -static int num_depcas = 0, num_eth = 0; -static int mem=0; /* For loadable module assignment - use insmod mem=0x????? .... */ -static char *adapter_name = '\0'; /* If no PROM when loadable module - use insmod adapter_name=DE??? ... - */ +static char name[DEPCA_STRLEN]; +static int num_depcas = 0, num_eth = 0; +static int mem = 0; /* For loadable module assignment + use insmod mem=0x????? .... */ +static char *adapter_name = '\0'; /* If no PROM when loadable module + use insmod adapter_name=DE??? ... + */ /* ** Miscellaneous defines... */ #define STOP_DEPCA \ outw(CSR0, DEPCA_ADDR);\ outw(STOP, DEPCA_DATA) - -__initfunc(int -depca_probe(struct device *dev)) + +__initfunc(int depca_probe(struct device *dev)) { - int tmp = num_depcas, status = -ENODEV; - u_long iobase = dev->base_addr; + int tmp = num_depcas, status = -ENODEV; + u_long iobase = dev->base_addr; - if ((iobase == 0) && loading_module){ - printk("Autoprobing is not supported when loading a module based driver.\n"); - status = -EIO; - } else { -#ifdef CONFIG_MCA - mca_probe(dev, iobase); + if ((iobase == 0) && loading_module) { + printk("Autoprobing is not supported when loading a module based driver.\n"); + status = -EIO; + } else { +#ifdef CONFIG_MCA + mca_probe(dev, iobase); #endif - isa_probe(dev, iobase); - eisa_probe(dev, iobase); + isa_probe(dev, iobase); + eisa_probe(dev, iobase); + + if ((tmp == num_depcas) && (iobase != 0) && loading_module) { + printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase); + } - if ((tmp == num_depcas) && (iobase != 0) && loading_module) { - printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, - iobase); - } - - /* - ** Walk the device list to check that at least one device - ** initialised OK - */ - for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); - - if (dev->priv) status = 0; - if (iobase == 0) autoprobed = 1; - } - - return status; -} - -__initfunc(static int -depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot)) -{ - struct depca_private *lp; - int i, j, offset, netRAM, mem_len, status=0; - s16 nicsr; - u_long mem_start=0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; - - STOP_DEPCA; - - nicsr = inb(DEPCA_NICSR); - nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM); - outb(nicsr, DEPCA_NICSR); - - if (inw(DEPCA_DATA) == STOP) { - do { - strcpy(name, (adapter_name ? adapter_name : "")); - mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]); - DepcaSignature(name, mem_start); - } while (!mem && mem_base[mem_chkd] && (adapter == unknown)); - - if ((adapter != unknown) && mem_start) { /* found a DEPCA device */ - dev->base_addr = ioaddr; - - if (mca_slot != -1) { - printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, - ioaddr, mca_slot); - } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ - printk("%s: %s at 0x%04lx (EISA slot %d)", - dev->name, name, ioaddr, (int)((ioaddr>>12)&0x0f)); - } else { /* ISA port address */ - printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); - } - - printk(", h/w address "); - status = get_hw_addr(dev); - for (i=0; idev_addr[i]); - } - printk("%2.2x", dev->dev_addr[i]); - - if (status == 0) { - /* Set up the maximum amount of network RAM(kB) */ - netRAM = ((adapter != DEPCA) ? 64 : 48); - if ((nicsr & _128KB) && (adapter == de422)) netRAM = 128; - offset = 0x0000; - - /* Shared Memory Base Address */ - if (nicsr & BUF) { - offset = 0x8000; /* 32kbyte RAM offset*/ - nicsr &= ~BS; /* DEPCA RAM in top 32k */ - netRAM -= 32; - } - mem_start += offset; /* (E)ISA start address */ - if ((mem_len = (NUM_RX_DESC*(sizeof(struct depca_rx_desc)+RX_BUFF_SZ) + - NUM_TX_DESC*(sizeof(struct depca_tx_desc)+TX_BUFF_SZ) + - sizeof(struct depca_init))) <= - (netRAM<<10)) { - printk(",\n has %dkB RAM at 0x%.5lx", netRAM, mem_start); - - /* Enable the shadow RAM. */ - if (adapter != DEPCA) { - nicsr |= SHE; - outb(nicsr, DEPCA_NICSR); - } - - /* Define the device private memory */ - dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - lp = (struct depca_private *)dev->priv; - memset((char *)dev->priv, 0, sizeof(struct depca_private)); - lp->adapter = adapter; - lp->mca_slot = mca_slot; - sprintf(lp->adapter_name,"%s (%s)", name, dev->name); - request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name); - - /* Initialisation Block */ - lp->sh_mem = mem_start; - mem_start += sizeof(struct depca_init); - - /* Tx & Rx descriptors (aligned to a quadword boundary) */ - mem_start = (mem_start + ALIGN) & ~ALIGN; - lp->rx_ring = (struct depca_rx_desc *)mem_start; - - mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); - lp->tx_ring = (struct depca_tx_desc *)mem_start; - - mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); - lp->bus_offset = mem_start & 0x00ff0000; - mem_start &= LA_MASK; /* LANCE re-mapped start address */ - - lp->dma_buffs = mem_start; - - /* Finish initialising the ring information. */ - lp->rxRingMask = NUM_RX_DESC - 1; - lp->txRingMask = NUM_TX_DESC - 1; - - /* Calculate Tx/Rx RLEN size for the descriptors. */ - for (i=0, j = lp->rxRingMask; j>0; i++) { - j >>= 1; - } - lp->rx_rlen = (s32)(i << 29); - for (i=0, j = lp->txRingMask; j>0; i++) { - j >>= 1; - } - lp->tx_rlen = (s32)(i << 29); - - /* Load the initialisation block */ - depca_init_ring(dev); - - /* Initialise the control and status registers */ - LoadCSRs(dev); - - /* Enable DEPCA board interrupts for autoprobing */ - nicsr = ((nicsr & ~IM)|IEN); - outb(nicsr, DEPCA_NICSR); - - /* To auto-IRQ we enable the initialization-done and DMA err, - interrupts. For now we will always get a DMA error. */ - if (dev->irq < 2) { + /* + ** Walk the device list to check that at least one device + ** initialised OK + */ + for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); + + if (dev->priv) + status = 0; + if (iobase == 0) + autoprobed = 1; + } + + return status; +} + +__initfunc(static int depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot)) +{ + struct depca_private *lp; + int i, j, offset, netRAM, mem_len, status = 0; + s16 nicsr; + u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; + + STOP_DEPCA; + + nicsr = inb(DEPCA_NICSR); + nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM); + outb(nicsr, DEPCA_NICSR); + + if (inw(DEPCA_DATA) == STOP) { + do { + strcpy(name, (adapter_name ? adapter_name : "")); + mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]); + DepcaSignature(name, mem_start); + } while (!mem && mem_base[mem_chkd] && (adapter == unknown)); + + if ((adapter != unknown) && mem_start) { /* found a DEPCA device */ + dev->base_addr = ioaddr; + + if (mca_slot != -1) { + printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot); + } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ + printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f)); + } else { /* ISA port address */ + printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); + } + + printk(", h/w address "); + status = get_hw_addr(dev); + for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet address */ + printk("%2.2x:", dev->dev_addr[i]); + } + printk("%2.2x", dev->dev_addr[i]); + + if (status == 0) { + /* Set up the maximum amount of network RAM(kB) */ + netRAM = ((adapter != DEPCA) ? 64 : 48); + if ((nicsr & _128KB) && (adapter == de422)) + netRAM = 128; + offset = 0x0000; + + /* Shared Memory Base Address */ + if (nicsr & BUF) { + offset = 0x8000; /* 32kbyte RAM offset */ + nicsr &= ~BS; /* DEPCA RAM in top 32k */ + netRAM -= 32; + } + mem_start += offset; /* (E)ISA start address */ + if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init))) <= (netRAM << 10)) { + printk(",\n has %dkB RAM at 0x%.5lx", netRAM, mem_start); + + /* Enable the shadow RAM. */ + if (adapter != DEPCA) { + nicsr |= SHE; + outb(nicsr, DEPCA_NICSR); + } + + /* Define the device private memory */ + dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + lp = (struct depca_private *) dev->priv; + memset((char *) dev->priv, 0, sizeof(struct depca_private)); + lp->adapter = adapter; + lp->mca_slot = mca_slot; + sprintf(lp->adapter_name, "%s (%s)", name, dev->name); + request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name); + + /* Initialisation Block */ + lp->sh_mem = mem_start; + mem_start += sizeof(struct depca_init); + + /* Tx & Rx descriptors (aligned to a quadword boundary) */ + mem_start = (mem_start + ALIGN) & ~ALIGN; + lp->rx_ring = (struct depca_rx_desc *) mem_start; + + mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); + lp->tx_ring = (struct depca_tx_desc *) mem_start; + + mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); + lp->bus_offset = mem_start & 0x00ff0000; + mem_start &= LA_MASK; /* LANCE re-mapped start address */ + + lp->dma_buffs = mem_start; + + /* Finish initialising the ring information. */ + lp->rxRingMask = NUM_RX_DESC - 1; + lp->txRingMask = NUM_TX_DESC - 1; + + /* Calculate Tx/Rx RLEN size for the descriptors. */ + for (i = 0, j = lp->rxRingMask; j > 0; i++) { + j >>= 1; + } + lp->rx_rlen = (s32) (i << 29); + for (i = 0, j = lp->txRingMask; j > 0; i++) { + j >>= 1; + } + lp->tx_rlen = (s32) (i << 29); + + /* Load the initialisation block */ + depca_init_ring(dev); + + /* Initialise the control and status registers */ + LoadCSRs(dev); + + /* Enable DEPCA board interrupts for autoprobing */ + nicsr = ((nicsr & ~IM) | IEN); + outb(nicsr, DEPCA_NICSR); + + /* To auto-IRQ we enable the initialization-done and DMA err, + interrupts. For now we will always get a DMA error. */ + if (dev->irq < 2) { #ifndef MODULE - unsigned char irqnum; - autoirq_setup(0); - - /* Assign the correct irq list */ - switch (lp->adapter) { - case DEPCA: - case de100: - case de101: - depca_irq = de1xx_irq; - break; - case de200: - case de201: - case de202: - case de210: - case de212: - depca_irq = de2xx_irq; - break; - case de422: - depca_irq = de422_irq; - break; - } - - /* Trigger an initialization just for the interrupt. */ - outw(INEA | INIT, DEPCA_DATA); - - irqnum = autoirq_report(1); - if (!irqnum) { - printk(" and failed to detect IRQ line.\n"); - status = -ENXIO; - } else { - for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++) { - if (irqnum == depca_irq[i]) { - dev->irq = irqnum; - printk(" and uses IRQ%d.\n", dev->irq); - } - } - - if (!dev->irq) { - printk(" but incorrect IRQ line detected.\n"); - status = -ENXIO; - } - } -#endif /* MODULE */ - } else { - printk(" and assigned IRQ%d.\n", dev->irq); - } - if (status) release_region(ioaddr, DEPCA_TOTAL_SIZE); + unsigned char irqnum; + autoirq_setup(0); + + /* Assign the correct irq list */ + switch (lp->adapter) { + case DEPCA: + case de100: + case de101: + depca_irq = de1xx_irq; + break; + case de200: + case de201: + case de202: + case de210: + case de212: + depca_irq = de2xx_irq; + break; + case de422: + depca_irq = de422_irq; + break; + } + + /* Trigger an initialization just for the interrupt. */ + outw(INEA | INIT, DEPCA_DATA); + + irqnum = autoirq_report(1); + if (!irqnum) { + printk(" and failed to detect IRQ line.\n"); + status = -ENXIO; + } else { + for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++) { + if (irqnum == depca_irq[i]) { + dev->irq = irqnum; + printk(" and uses IRQ%d.\n", dev->irq); + } + } + + if (!dev->irq) { + printk(" but incorrect IRQ line detected.\n"); + status = -ENXIO; + } + } +#endif /* MODULE */ + } else { + printk(" and assigned IRQ%d.\n", dev->irq); + } + if (status) + release_region(ioaddr, DEPCA_TOTAL_SIZE); + } else { + printk(",\n requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM); + status = -ENXIO; + } + } else { + printk(" which has an Ethernet PROM CRC error.\n"); + status = -ENXIO; + } + } else { + status = -ENXIO; + } + if (!status) { + if (depca_debug > 1) { + printk(version); + } + + /* The DEPCA-specific entries in the device structure. */ + dev->open = &depca_open; + dev->hard_start_xmit = &depca_start_xmit; + dev->stop = &depca_close; + dev->get_stats = &depca_get_stats; + dev->set_multicast_list = &set_multicast_list; + dev->do_ioctl = &depca_ioctl; + + dev->mem_start = 0; + + /* Fill in the generic field of the device structure. */ + ether_setup(dev); + } else { /* Incorrectly initialised hardware */ + if (dev->priv) { + kfree_s(dev->priv, sizeof(struct depca_private)); + dev->priv = NULL; + } + } } else { - printk(",\n requests %dkB RAM: only %dkB is available!\n", - (mem_len>>10), netRAM); - status = -ENXIO; - } - } else { - printk(" which has an Ethernet PROM CRC error.\n"); - status = -ENXIO; - } - } else { - status = -ENXIO; - } - if (!status) { - if (depca_debug > 1) { - printk(version); - } - - /* The DEPCA-specific entries in the device structure. */ - dev->open = &depca_open; - dev->hard_start_xmit = &depca_start_xmit; - dev->stop = &depca_close; - dev->get_stats = &depca_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &depca_ioctl; - - dev->mem_start = 0; - - /* Fill in the generic field of the device structure. */ - ether_setup(dev); - } else { /* Incorrectly initialised hardware */ - if (dev->priv) { - kfree_s(dev->priv, sizeof(struct depca_private)); - dev->priv = NULL; - } - } - } else { - status = -ENXIO; - } + status = -ENXIO; + } - return status; + return status; } - -static int -depca_open(struct device *dev) + +static int depca_open(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - s16 nicsr; - int status = 0; - - STOP_DEPCA; - nicsr = inb(DEPCA_NICSR); - - /* Make sure the shadow RAM is enabled */ - if (adapter != DEPCA) { - nicsr |= SHE; - outb(nicsr, DEPCA_NICSR); - } - - /* Re-initialize the DEPCA... */ - depca_init_ring(dev); - LoadCSRs(dev); - - depca_dbg_open(dev); - - if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) { - printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); - status = -EAGAIN; - } else { - - /* Enable DEPCA board interrupts and turn off LED */ - nicsr = ((nicsr & ~IM & ~LED)|IEN); - outb(nicsr, DEPCA_NICSR); - outw(CSR0,DEPCA_ADDR); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - status = InitRestartDepca(dev); - - if (depca_debug > 1){ - printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); - printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR)); - } - } - - MOD_INC_USE_COUNT; - - return status; + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + s16 nicsr; + int status = 0; + + STOP_DEPCA; + nicsr = inb(DEPCA_NICSR); + + /* Make sure the shadow RAM is enabled */ + if (adapter != DEPCA) { + nicsr |= SHE; + outb(nicsr, DEPCA_NICSR); + } + + /* Re-initialize the DEPCA... */ + depca_init_ring(dev); + LoadCSRs(dev); + + depca_dbg_open(dev); + + if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) { + printk("depca_open(): Requested IRQ%d is busy\n", dev->irq); + status = -EAGAIN; + } else { + + /* Enable DEPCA board interrupts and turn off LED */ + nicsr = ((nicsr & ~IM & ~LED) | IEN); + outb(nicsr, DEPCA_NICSR); + outw(CSR0, DEPCA_ADDR); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + status = InitRestartDepca(dev); + + if (depca_debug > 1) { + printk("CSR0: 0x%4.4x\n", inw(DEPCA_DATA)); + printk("nicsr: 0x%02x\n", inb(DEPCA_NICSR)); + } + } + + MOD_INC_USE_COUNT; + + return status; } /* Initialize the lance Rx and Tx descriptor rings. */ -static void -depca_init_ring(struct device *dev) +static void depca_init_ring(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_int i; - u_long p; - - /* Lock out other processes whilst setting up the hardware */ - test_and_set_bit(0, (void *)&dev->tbusy); - - lp->rx_new = lp->tx_new = 0; - lp->rx_old = lp->tx_old = 0; - - /* Initialize the base addresses and length of each buffer in the ring */ - for (i = 0; i <= lp->rxRingMask; i++) { - writel((p=lp->dma_buffs+i*RX_BUFF_SZ) | R_OWN, &lp->rx_ring[i].base); - writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length); - lp->rx_memcpy[i]=(char *)(p+lp->bus_offset); - } - for (i = 0; i <= lp->txRingMask; i++) { - writel((p=lp->dma_buffs+(i+lp->txRingMask+1)*TX_BUFF_SZ) & 0x00ffffff, - &lp->tx_ring[i].base); - lp->tx_memcpy[i]=(char *)(p+lp->bus_offset); - } - - /* Set up the initialization block */ - lp->init_block.rx_ring = ((u32)((u_long)lp->rx_ring)&LA_MASK) | lp->rx_rlen; - lp->init_block.tx_ring = ((u32)((u_long)lp->tx_ring)&LA_MASK) | lp->tx_rlen; - - SetMulticastFilter(dev); - - for (i = 0; i < ETH_ALEN; i++) { - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - } + struct depca_private *lp = (struct depca_private *) dev->priv; + u_int i; + u_long p; + + /* Lock out other processes whilst setting up the hardware */ + test_and_set_bit(0, (void *) &dev->tbusy); + + lp->rx_new = lp->tx_new = 0; + lp->rx_old = lp->tx_old = 0; + + /* Initialize the base addresses and length of each buffer in the ring */ + for (i = 0; i <= lp->rxRingMask; i++) { + writel((p = lp->dma_buffs + i * RX_BUFF_SZ) | R_OWN, &lp->rx_ring[i].base); + writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length); + lp->rx_memcpy[i] = (char *) (p + lp->bus_offset); + } + for (i = 0; i <= lp->txRingMask; i++) { + writel((p = lp->dma_buffs + (i + lp->txRingMask + 1) * TX_BUFF_SZ) & 0x00ffffff, &lp->tx_ring[i].base); + lp->tx_memcpy[i] = (char *) (p + lp->bus_offset); + } - lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ + /* Set up the initialization block */ + lp->init_block.rx_ring = ((u32) ((u_long) lp->rx_ring) & LA_MASK) | lp->rx_rlen; + lp->init_block.tx_ring = ((u32) ((u_long) lp->tx_ring) & LA_MASK) | lp->tx_rlen; - return; + SetMulticastFilter(dev); + + for (i = 0; i < ETH_ALEN; i++) { + lp->init_block.phys_addr[i] = dev->dev_addr[i]; + } + + lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ + + return; } /* ** Writes a socket buffer to TX descriptor ring and starts transmission */ -static int -depca_start_xmit(struct sk_buff *skb, struct device *dev) +static int depca_start_xmit(struct sk_buff *skb, struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - int status = 0; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 1*HZ) { - status = -1; - } else { - printk("%s: transmit timed out, status %04x, resetting.\n", - dev->name, inw(DEPCA_DATA)); - - STOP_DEPCA; - depca_init_ring(dev); - LoadCSRs(dev); - dev->interrupt = UNMASK_INTERRUPTS; - dev->start = 1; - dev->tbusy=0; - dev->trans_start = jiffies; - InitRestartDepca(dev); - } - return status; - } else if (skb->len > 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); - status = -1; - } else { - if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ - status = load_packet(dev, skb); - - if (!status) { - /* Trigger an immediate send demand. */ - outw(CSR0, DEPCA_ADDR); - outw(INEA | TDMD, DEPCA_DATA); - - dev->trans_start = jiffies; - dev_kfree_skb(skb); - } - if (TX_BUFFS_AVAIL) { - dev->tbusy=0; - } - } else { - status = -1; - } - } - } - - return status; + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + int status = 0; + + /* Transmitter timeout, serious problems. */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 1 * HZ) { + status = -1; + } else { + printk("%s: transmit timed out, status %04x, resetting.\n", dev->name, inw(DEPCA_DATA)); + + STOP_DEPCA; + depca_init_ring(dev); + LoadCSRs(dev); + dev->interrupt = UNMASK_INTERRUPTS; + dev->start = 1; + dev->tbusy = 0; + dev->trans_start = jiffies; + InitRestartDepca(dev); + } + return status; + } else if (skb->len > 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); + status = -1; + } else { + if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ + status = load_packet(dev, skb); + + if (!status) { + /* Trigger an immediate send demand. */ + outw(CSR0, DEPCA_ADDR); + outw(INEA | TDMD, DEPCA_DATA); + + dev->trans_start = jiffies; + dev_kfree_skb(skb); + } + if (TX_BUFFS_AVAIL) { + dev->tbusy = 0; + } + } else { + status = -1; + } + } + } + + return status; } /* ** The DEPCA interrupt handler. */ -static void -depca_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct device *dev = dev_id; - struct depca_private *lp; - s16 csr0, nicsr; - u_long ioaddr; - - if (dev == NULL) { - printk ("depca_interrupt(): irq %d for unknown device.\n", irq); - } else { - lp = (struct depca_private *)dev->priv; - ioaddr = dev->base_addr; - - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - dev->interrupt = MASK_INTERRUPTS; - - /* mask the DEPCA board interrupts and turn on the LED */ - nicsr = inb(DEPCA_NICSR); - nicsr |= (IM|LED); - outb(nicsr, DEPCA_NICSR); - - outw(CSR0, DEPCA_ADDR); - csr0 = inw(DEPCA_DATA); - - /* Acknowledge all of the current interrupt sources ASAP. */ - outw(csr0 & INTE, DEPCA_DATA); - - if (csr0 & RINT) /* Rx interrupt (packet arrived) */ - depca_rx(dev); - - if (csr0 & TINT) /* Tx interrupt (packet sent) */ - depca_tx(dev); - - if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */ - dev->tbusy = 0; /* clear TX busy flag */ - mark_bh(NET_BH); - } - - /* Unmask the DEPCA board interrupts and turn off the LED */ - nicsr = (nicsr & ~IM & ~LED); - outb(nicsr, DEPCA_NICSR); - - dev->interrupt = UNMASK_INTERRUPTS; - } - - return; -} - -static int -depca_rx(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - int i, entry; - s32 status; - - for (entry=lp->rx_new; - !(readl(&lp->rx_ring[entry].base) & R_OWN); - entry=lp->rx_new){ - status = readl(&lp->rx_ring[entry].base) >> 16 ; - if (status & R_STP) { /* Remember start of frame */ - lp->rx_old = entry; - } - if (status & R_ENP) { /* Valid frame status */ - if (status & R_ERR) { /* There was an error. */ - lp->stats.rx_errors++; /* Update the error stats. */ - if (status & R_FRAM) lp->stats.rx_frame_errors++; - if (status & R_OFLO) lp->stats.rx_over_errors++; - if (status & R_CRC) lp->stats.rx_crc_errors++; - if (status & R_BUFF) lp->stats.rx_fifo_errors++; - } else { - short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4; - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+2); - if (skb != NULL) { - unsigned char *buf; - skb_reserve(skb,2); /* 16 byte align the IP header */ - buf = skb_put(skb,pkt_len); - skb->dev = dev; - if (entry < lp->rx_old) { /* Wrapped buffer */ - len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; - memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], len); - memcpy_fromio(buf + len, lp->rx_memcpy[0], pkt_len-len); - } else { /* Linear buffer */ - memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len); - } - - /* - ** Notify the upper protocol layers that there is another - ** packet to handle - */ - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - - /* - ** Update stats - */ - lp->stats.rx_packets++; - for (i=1; ipktStats.bins[i]++; - i = DEPCA_PKT_STAT_SZ; - } - } - if (buf[0] & 0x01) { /* Multicast/Broadcast */ - if ((*(s16 *)&buf[0] == -1) && - (*(s16 *)&buf[2] == -1) && - (*(s16 *)&buf[4] == -1)) { - lp->pktStats.broadcast++; - } else { - lp->pktStats.multicast++; - } - } else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) && - (*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) && - (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { - lp->pktStats.unicast++; - } - - lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ - if (lp->pktStats.bins[0] == 0) { /* Reset counters */ - memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); - } + struct device *dev = dev_id; + struct depca_private *lp; + s16 csr0, nicsr; + u_long ioaddr; + + if (dev == NULL) { + printk("depca_interrupt(): irq %d for unknown device.\n", irq); } else { - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - lp->stats.rx_dropped++; /* Really, deferred. */ - break; - } - } - /* Change buffer ownership for this last frame, back to the adapter */ - for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) { - writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, - &lp->rx_ring[lp->rx_old].base); - } - writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); - } - - /* - ** Update entry information - */ - lp->rx_new = (++lp->rx_new) & lp->rxRingMask; - } + lp = (struct depca_private *) dev->priv; + ioaddr = dev->base_addr; + + if (dev->interrupt) + printk("%s: Re-entering the interrupt handler.\n", dev->name); + + dev->interrupt = MASK_INTERRUPTS; + + /* mask the DEPCA board interrupts and turn on the LED */ + nicsr = inb(DEPCA_NICSR); + nicsr |= (IM | LED); + outb(nicsr, DEPCA_NICSR); + + outw(CSR0, DEPCA_ADDR); + csr0 = inw(DEPCA_DATA); + + /* Acknowledge all of the current interrupt sources ASAP. */ + outw(csr0 & INTE, DEPCA_DATA); + + if (csr0 & RINT) /* Rx interrupt (packet arrived) */ + depca_rx(dev); + + if (csr0 & TINT) /* Tx interrupt (packet sent) */ + depca_tx(dev); + + if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */ + dev->tbusy = 0; /* clear TX busy flag */ + mark_bh(NET_BH); + } - return 0; + /* Unmask the DEPCA board interrupts and turn off the LED */ + nicsr = (nicsr & ~IM & ~LED); + outb(nicsr, DEPCA_NICSR); + + dev->interrupt = UNMASK_INTERRUPTS; + } + + return; +} + +static int depca_rx(struct device *dev) +{ + struct depca_private *lp = (struct depca_private *) dev->priv; + int i, entry; + s32 status; + + for (entry = lp->rx_new; !(readl(&lp->rx_ring[entry].base) & R_OWN); entry = lp->rx_new) { + status = readl(&lp->rx_ring[entry].base) >> 16; + if (status & R_STP) { /* Remember start of frame */ + lp->rx_old = entry; + } + if (status & R_ENP) { /* Valid frame status */ + if (status & R_ERR) { /* There was an error. */ + lp->stats.rx_errors++; /* Update the error stats. */ + if (status & R_FRAM) + lp->stats.rx_frame_errors++; + if (status & R_OFLO) + lp->stats.rx_over_errors++; + if (status & R_CRC) + lp->stats.rx_crc_errors++; + if (status & R_BUFF) + lp->stats.rx_fifo_errors++; + } else { + short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4; + struct sk_buff *skb; + + skb = dev_alloc_skb(pkt_len + 2); + if (skb != NULL) { + unsigned char *buf; + skb_reserve(skb, 2); /* 16 byte align the IP header */ + buf = skb_put(skb, pkt_len); + skb->dev = dev; + if (entry < lp->rx_old) { /* Wrapped buffer */ + len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; + memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], len); + memcpy_fromio(buf + len, lp->rx_memcpy[0], pkt_len - len); + } else { /* Linear buffer */ + memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len); + } + + /* + ** Notify the upper protocol layers that there is another + ** packet to handle + */ + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + + /* + ** Update stats + */ + lp->stats.rx_packets++; + for (i = 1; i < DEPCA_PKT_STAT_SZ - 1; i++) { + if (pkt_len < (i * DEPCA_PKT_BIN_SZ)) { + lp->pktStats.bins[i]++; + i = DEPCA_PKT_STAT_SZ; + } + } + if (buf[0] & 0x01) { /* Multicast/Broadcast */ + if ((*(s16 *) & buf[0] == -1) && (*(s16 *) & buf[2] == -1) && (*(s16 *) & buf[4] == -1)) { + lp->pktStats.broadcast++; + } else { + lp->pktStats.multicast++; + } + } else if ((*(s16 *) & buf[0] == *(s16 *) & dev->dev_addr[0]) && (*(s16 *) & buf[2] == *(s16 *) & dev->dev_addr[2]) && (*(s16 *) & buf[4] == *(s16 *) & dev->dev_addr[4])) { + lp->pktStats.unicast++; + } + + lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ + if (lp->pktStats.bins[0] == 0) { /* Reset counters */ + memset((char *) &lp->pktStats, 0, sizeof(lp->pktStats)); + } + } else { + printk("%s: Memory squeeze, deferring packet.\n", dev->name); + lp->stats.rx_dropped++; /* Really, deferred. */ + break; + } + } + /* Change buffer ownership for this last frame, back to the adapter */ + for (; lp->rx_old != entry; lp->rx_old = (++lp->rx_old) & lp->rxRingMask) { + writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base); + } + writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); + } + + /* + ** Update entry information + */ + lp->rx_new = (++lp->rx_new) & lp->rxRingMask; + } + + return 0; } /* ** Buffer sent - check for buffer errors. */ -static int -depca_tx(struct device *dev) +static int depca_tx(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - int entry; - s32 status; - u_long ioaddr = dev->base_addr; - - for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { - status = readl(&lp->tx_ring[entry].base) >> 16 ; - - if (status < 0) { /* Packet not yet sent! */ - break; - } else if (status & T_ERR) { /* An error occurred. */ - status = readl(&lp->tx_ring[entry].misc); - lp->stats.tx_errors++; - if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; - if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; - if (status & TMD3_LCOL) lp->stats.tx_window_errors++; - if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++; - if (status & (TMD3_BUFF | TMD3_UFLO)) { - /* Trigger an immediate send demand. */ - outw(CSR0, DEPCA_ADDR); - outw(INEA | TDMD, DEPCA_DATA); - } - } else if (status & (T_MORE | T_ONE)) { - lp->stats.collisions++; - } else { - lp->stats.tx_packets++; - } - - /* Update all the pointers */ - lp->tx_old = (++lp->tx_old) & lp->txRingMask; - } - - return 0; -} - -static int -depca_close(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - s16 nicsr; - u_long ioaddr = dev->base_addr; - - dev->start = 0; - dev->tbusy = 1; - - outw(CSR0, DEPCA_ADDR); - - if (depca_debug > 1) { - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inw(DEPCA_DATA)); - } - - /* - ** We stop the DEPCA here -- it occasionally polls - ** memory if we don't. - */ - outw(STOP, DEPCA_DATA); - - /* - ** Give back the ROM in case the user wants to go to DOS - */ - if (lp->adapter != DEPCA) { - nicsr = inb(DEPCA_NICSR); - nicsr &= ~SHE; - outb(nicsr, DEPCA_NICSR); - } - - /* - ** Free the associated irq - */ - free_irq(dev->irq, dev); + struct depca_private *lp = (struct depca_private *) dev->priv; + int entry; + s32 status; + u_long ioaddr = dev->base_addr; + + for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { + status = readl(&lp->tx_ring[entry].base) >> 16; + + if (status < 0) { /* Packet not yet sent! */ + break; + } else if (status & T_ERR) { /* An error occurred. */ + status = readl(&lp->tx_ring[entry].misc); + lp->stats.tx_errors++; + if (status & TMD3_RTRY) + lp->stats.tx_aborted_errors++; + if (status & TMD3_LCAR) + lp->stats.tx_carrier_errors++; + if (status & TMD3_LCOL) + lp->stats.tx_window_errors++; + if (status & TMD3_UFLO) + lp->stats.tx_fifo_errors++; + if (status & (TMD3_BUFF | TMD3_UFLO)) { + /* Trigger an immediate send demand. */ + outw(CSR0, DEPCA_ADDR); + outw(INEA | TDMD, DEPCA_DATA); + } + } else if (status & (T_MORE | T_ONE)) { + lp->stats.collisions++; + } else { + lp->stats.tx_packets++; + } - MOD_DEC_USE_COUNT; + /* Update all the pointers */ + lp->tx_old = (++lp->tx_old) & lp->txRingMask; + } - return 0; + return 0; } -static void LoadCSRs(struct device *dev) +static int depca_close(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; + struct depca_private *lp = (struct depca_private *) dev->priv; + s16 nicsr; + u_long ioaddr = dev->base_addr; + + dev->start = 0; + dev->tbusy = 1; + + outw(CSR0, DEPCA_ADDR); + + if (depca_debug > 1) { + printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inw(DEPCA_DATA)); + } - outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ - outw((u16)(lp->sh_mem & LA_MASK), DEPCA_DATA); - outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ - outw((u16)((lp->sh_mem & LA_MASK) >> 16), DEPCA_DATA); - outw(CSR3, DEPCA_ADDR); /* ALE control */ - outw(ACON, DEPCA_DATA); + /* + ** We stop the DEPCA here -- it occasionally polls + ** memory if we don't. + */ + outw(STOP, DEPCA_DATA); - outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ + /* + ** Give back the ROM in case the user wants to go to DOS + */ + if (lp->adapter != DEPCA) { + nicsr = inb(DEPCA_NICSR); + nicsr &= ~SHE; + outb(nicsr, DEPCA_NICSR); + } - return; + /* + ** Free the associated irq + */ + free_irq(dev->irq, dev); + + MOD_DEC_USE_COUNT; + + return 0; } -static int InitRestartDepca(struct device *dev) +static void LoadCSRs(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - int i, status=0; + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; - /* Copy the shadow init_block to shared memory */ - memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); + outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ + outw((u16) (lp->sh_mem & LA_MASK), DEPCA_DATA); + outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ + outw((u16) ((lp->sh_mem & LA_MASK) >> 16), DEPCA_DATA); + outw(CSR3, DEPCA_ADDR); /* ALE control */ + outw(ACON, DEPCA_DATA); - outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ - outw(INIT, DEPCA_DATA); /* initialize DEPCA */ + outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ - /* wait for lance to complete initialisation */ - for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); + return; +} - if (i!=100) { - /* clear IDON by writing a "1", enable interrupts and start lance */ - outw(IDON | INEA | STRT, DEPCA_DATA); - if (depca_debug > 2) { - printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", - dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); - } - } else { - printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", - dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); - status = -1; - } +static int InitRestartDepca(struct device *dev) +{ + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + int i, status = 0; + + /* Copy the shadow init_block to shared memory */ + memcpy_toio((char *) lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); + + outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ + outw(INIT, DEPCA_DATA); /* initialize DEPCA */ + + /* wait for lance to complete initialisation */ + for (i = 0; (i < 100) && !(inw(DEPCA_DATA) & IDON); i++); + + if (i != 100) { + /* clear IDON by writing a "1", enable interrupts and start lance */ + outw(IDON | INEA | STRT, DEPCA_DATA); + if (depca_debug > 2) { + printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); + } + } else { + printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); + status = -1; + } - return status; + return status; } -static struct net_device_stats * -depca_get_stats(struct device *dev) +static struct net_device_stats *depca_get_stats(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; + struct depca_private *lp = (struct depca_private *) dev->priv; - /* Null body since there is no framing error counter */ + /* Null body since there is no framing error counter */ - return &lp->stats; + return &lp->stats; } /* ** Set or clear the multicast filter for this adaptor. */ -static void -set_multicast_list(struct device *dev) +static void set_multicast_list(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - - if (dev) { - while(dev->tbusy) barrier(); /* Stop ring access */ - set_bit(0, (void*)&dev->tbusy); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - - if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ - lp->init_block.mode |= PROM; - } else { - SetMulticastFilter(dev); - lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ - } - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - } + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + + if (dev) { + while (dev->tbusy) + barrier(); /* Stop ring access */ + set_bit(0, (void *) &dev->tbusy); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + + if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ + lp->init_block.mode |= PROM; + } else { + SetMulticastFilter(dev); + lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ + } + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + dev->tbusy = 0; /* Unlock the TX ring */ + } } /* @@ -1203,280 +1187,284 @@ */ static void SetMulticastFilter(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - struct dev_mc_list *dmi=dev->mc_list; - char *addrs; - int i, j, bit, byte; - u16 hashcode; - s32 crc, poly = CRC_POLYNOMIAL_BE; - - if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ - for (i=0; i<(HASH_TABLE_LEN>>3); i++) { - lp->init_block.mcast_table[i] = (char)0xff; - } - } else { - for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */ - lp->init_block.mcast_table[i]=0; - } - /* Add multicast addresses */ - for (i=0;imc_count;i++) { /* for each address in the list */ - addrs=dmi->dmi_addr; - dmi=dmi->next; - if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte=0;byte>=1) { - crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0); - } - } - hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ - for (j=0;j<5;j++) { /* ... in reverse order. */ - hashcode = (hashcode << 1) | ((crc>>=1) & 1); - } - - - byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - lp->init_block.mcast_table[byte] |= bit; - } - } - } + struct depca_private *lp = (struct depca_private *) dev->priv; + struct dev_mc_list *dmi = dev->mc_list; + char *addrs; + int i, j, bit, byte; + u16 hashcode; + s32 crc, poly = CRC_POLYNOMIAL_BE; + + if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ + for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { + lp->init_block.mcast_table[i] = (char) 0xff; + } + } else { + for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { /* Clear the multicast table */ + lp->init_block.mcast_table[i] = 0; + } + /* Add multicast addresses */ + for (i = 0; i < dev->mc_count; i++) { /* for each address in the list */ + addrs = dmi->dmi_addr; + dmi = dmi->next; + if ((*addrs & 0x01) == 1) { /* multicast address? */ + crc = 0xffffffff; /* init CRC for each address */ + for (byte = 0; byte < ETH_ALEN; byte++) { /* for each address byte */ + /* process each address bit */ + for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { + crc = (crc << 1) ^ ((((crc < 0 ? 1 : 0) ^ bit) & 0x01) ? poly : 0); + } + } + hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ + for (j = 0; j < 5; j++) { /* ... in reverse order. */ + hashcode = (hashcode << 1) | ((crc >>= 1) & 1); + } + + + byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ + bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ + lp->init_block.mcast_table[byte] |= bit; + } + } + } - return; + return; } #ifdef CONFIG_MCA /* ** Microchannel bus I/O device probe */ -__initfunc(static void -mca_probe(struct device *dev, u_long ioaddr)) +__initfunc(static void mca_probe(struct device *dev, u_long ioaddr)) { - unsigned char pos[2]; - unsigned char where; - unsigned long iobase; - int irq; - int slot = 0; - - /* - ** See if we've been here before. - */ - if ((!ioaddr && autoprobed) || (ioaddr && !loading_module)) return; + unsigned char pos[2]; + unsigned char where; + unsigned long iobase; + int irq; + int slot = 0; - if (MCA_bus) { /* - ** Search for the adapter. If an address has been given, search - ** specifically for the card at that address. Otherwise find the - ** first card in the system. - */ - while ((dev!=NULL) && - ((slot=mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) { - pos[0] = mca_read_stored_pos(slot, 2); - pos[1] = mca_read_stored_pos(slot, 3); - - /* - ** IO of card is handled by bits 1 and 2 of pos0. - ** - ** bit2 bit1 IO - ** 0 0 0x2c00 - ** 0 1 0x2c10 - ** 1 0 0x2c20 - ** 1 1 0x2c30 - */ - where = (pos[0] & 6) >> 1; - iobase = 0x2c00 + (0x10 * where); - - if ((ioaddr) && (ioaddr != iobase)) { - /* - ** Card was found, but not at the right IO location. Continue - ** scanning from the next MCA slot up for another card. - */ - slot++; - continue; - } - - /* - ** Found the adapter we were looking for. Now start setting it up. - ** - ** First work on decoding the IRQ. It's stored in the lower 4 bits - ** of pos1. Bits are as follows (from the ADF file): - ** - ** Bits - ** 3 2 1 0 IRQ - ** -------------------- - ** 0 0 1 0 5 - ** 0 0 0 1 9 - ** 0 1 0 0 10 - ** 1 0 0 0 11 - **/ - where = pos[1] & 0x0f; - switch(where) { - case 1: - irq = 9; - break; - case 2: - irq = 5; - break; - case 4: - irq = 10; - break; - case 8: - irq = 11; - break; - default: - printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where); + ** See if we've been here before. + */ + if ((!ioaddr && autoprobed) || (ioaddr && !loading_module)) return; - } - - /* - ** Shared memory address of adapter is stored in bits 3-5 of pos0. - ** They are mapped as follows: - ** - ** Bit - ** 5 4 3 Memory Addresses - ** 0 0 0 C0000-CFFFF (64K) - ** 1 0 0 C8000-CFFFF (32K) - ** 0 0 1 D0000-DFFFF (64K) - ** 1 0 1 D8000-DFFFF (32K) - ** 0 1 0 E0000-EFFFF (64K) - ** 1 1 0 E8000-EFFFF (32K) - */ - where = (pos[0] & 0x18) >> 3; - mem = 0xc0000 + (where * 0x10000); - if (pos[0] & 0x20) { - mem += 0x8000; - } - - /* - ** Get everything allocated and initialized... (almost just - ** like the ISA and EISA probes) - */ - if (DevicePresent(iobase) != 0) { + + if (MCA_bus) { /* - ** If the MCA configuration says the card should be here, - ** it really should be here. - */ - printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not + ** Search for the adapter. If an address has been given, search + ** specifically for the card at that address. Otherwise find the + ** first card in the system. + */ + while ((dev != NULL) && ((slot = mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) { + pos[0] = mca_read_stored_pos(slot, 2); + pos[1] = mca_read_stored_pos(slot, 3); + + /* + ** IO of card is handled by bits 1 and 2 of pos0. + ** + ** bit2 bit1 IO + ** 0 0 0x2c00 + ** 0 1 0x2c10 + ** 1 0 0x2c20 + ** 1 1 0x2c30 + */ + where = (pos[0] & 6) >> 1; + iobase = 0x2c00 + (0x10 * where); + + if ((ioaddr) && (ioaddr != iobase)) { + /* + ** Card was found, but not at the right IO location. Continue + ** scanning from the next MCA slot up for another card. + */ + slot++; + continue; + } + + /* + ** Found the adapter we were looking for. Now start setting it up. + ** + ** First work on decoding the IRQ. It's stored in the lower 4 bits + ** of pos1. Bits are as follows (from the ADF file): + ** + ** Bits + ** 3 2 1 0 IRQ + ** -------------------- + ** 0 0 1 0 5 + ** 0 0 0 1 9 + ** 0 1 0 0 10 + ** 1 0 0 0 11 + * */ + where = pos[1] & 0x0f; + switch (where) { + case 1: + irq = 9; + break; + case 2: + irq = 5; + break; + case 4: + irq = 10; + break; + case 8: + irq = 11; + break; + default: + printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where); + return; + } + + /* + ** Shared memory address of adapter is stored in bits 3-5 of pos0. + ** They are mapped as follows: + ** + ** Bit + ** 5 4 3 Memory Addresses + ** 0 0 0 C0000-CFFFF (64K) + ** 1 0 0 C8000-CFFFF (32K) + ** 0 0 1 D0000-DFFFF (64K) + ** 1 0 1 D8000-DFFFF (32K) + ** 0 1 0 E0000-EFFFF (64K) + ** 1 1 0 E8000-EFFFF (32K) + */ + where = (pos[0] & 0x18) >> 3; + mem = 0xc0000 + (where * 0x10000); + if (pos[0] & 0x20) { + mem += 0x8000; + } + + /* + ** Get everything allocated and initialized... (almost just + ** like the ISA and EISA probes) + */ + if (DevicePresent(iobase) != 0) { + /* + ** If the MCA configuration says the card should be here, + ** it really should be here. + */ + printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase); - } - - if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - dev->irq = irq; - if (depca_hw_init(dev, iobase, slot) == 0) { + } + + if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { + if ((dev = alloc_device(dev, iobase)) != NULL) { + dev->irq = irq; + if (depca_hw_init(dev, iobase, slot) == 0) { + /* + ** Adapter initialized correctly: Name it in + ** /proc/mca. + */ + mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); + mca_mark_as_used(slot); + num_depcas++; + } + num_eth++; + } + } else if (autoprobed) { + printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); + } + + /* + ** If this is a probe by a module, return after setting up the + ** given card. + */ + if (ioaddr) + return; + /* - ** Adapter initialized correctly: Name it in - ** /proc/mca. - */ - mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); - mca_mark_as_used(slot); - num_depcas++; - } - num_eth++; - } - } else if (autoprobed) { - printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } - - /* - ** If this is a probe by a module, return after setting up the - ** given card. - */ - if (ioaddr) return; - - /* - ** Set up to check the next slot and loop. - */ - slot++; + ** Set up to check the next slot and loop. + */ + slot++; + } } - } - return; + return; } #endif /* ** ISA bus I/O device probe */ -__initfunc(static void -isa_probe(struct device *dev, u_long ioaddr)) +__initfunc(static void isa_probe(struct device *dev, u_long ioaddr)) { - int i = num_depcas, maxSlots; - s32 ports[] = DEPCA_IO_PORTS; + int i = num_depcas, maxSlots; + s32 ports[] = DEPCA_IO_PORTS; + + if (!ioaddr && autoprobed) + return; /* Been here before ! */ + if (ioaddr > 0x400) + return; /* EISA Address */ + if (i >= MAX_NUM_DEPCAS) + return; /* Too many ISA adapters */ + + if (ioaddr == 0) { /* Autoprobing */ + maxSlots = MAX_NUM_DEPCAS; + } else { /* Probe a specific location */ + ports[i] = ioaddr; + maxSlots = i + 1; + } - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if (ioaddr > 0x400) return; /* EISA Address */ - if (i >= MAX_NUM_DEPCAS) return; /* Too many ISA adapters */ - - if (ioaddr == 0) { /* Autoprobing */ - maxSlots = MAX_NUM_DEPCAS; - } else { /* Probe a specific location */ - ports[i] = ioaddr; - maxSlots = i + 1; - } - - for (; (iname, ports[i]); - } - } + for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) { + if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { + if (DevicePresent(ports[i]) == 0) { + if ((dev = alloc_device(dev, ports[i])) != NULL) { + if (depca_hw_init(dev, ports[i], -1) == 0) { + num_depcas++; + } + num_eth++; + } + } + } else if (autoprobed) { + printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); + } + } - return; + return; } /* ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually ** the motherboard. Upto 15 EISA devices are supported. */ -__initfunc(static void -eisa_probe(struct device *dev, u_long ioaddr)) +__initfunc(static void eisa_probe(struct device *dev, u_long ioaddr)) { - int i, maxSlots; - u_long iobase; - char name[DEPCA_STRLEN]; - - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if ((ioaddr < 0x400) && (ioaddr > 0)) return; /* ISA Address */ - - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; - } - if ((iobase & 0x0fff) == 0) iobase += DEPCA_EISA_IO_PORTS; - - for (; (iname, iobase); - } - } + int i, maxSlots; + u_long iobase; + char name[DEPCA_STRLEN]; + + if (!ioaddr && autoprobed) + return; /* Been here before ! */ + if ((ioaddr < 0x400) && (ioaddr > 0)) + return; /* ISA Address */ + + if (ioaddr == 0) { /* Autoprobing */ + iobase = EISA_SLOT_INC; /* Get the first slot address */ + i = 1; + maxSlots = MAX_EISA_SLOTS; + } else { /* Probe a specific location */ + iobase = ioaddr; + i = (ioaddr >> 12); + maxSlots = i + 1; + } + if ((iobase & 0x0fff) == 0) + iobase += DEPCA_EISA_IO_PORTS; - return; + for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { + if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { + if (EISA_signature(name, EISA_ID)) { + if (DevicePresent(iobase) == 0) { + if ((dev = alloc_device(dev, iobase)) != NULL) { + if (depca_hw_init(dev, iobase, -1) == 0) { + num_depcas++; + } + num_eth++; + } + } + } + } else if (autoprobed) { + printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); + } + } + + return; } /* @@ -1485,90 +1473,88 @@ ** are not available then insert a new device structure at the end of ** the current list. */ -__initfunc(static struct device * -alloc_device(struct device *dev, u_long iobase)) +__initfunc(static struct device * alloc_device(struct device *dev, u_long iobase)) { - struct device *adev = NULL; - int fixed = 0, new_dev = 0; + struct device *adev = NULL; + int fixed = 0, new_dev = 0; - num_eth = depca_dev_index(dev->name); - if (loading_module) return dev; - - while (1) { - if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr==0)) && !adev) { - adev=dev; - } else if ((dev->priv == NULL) && (dev->base_addr==iobase)) { - fixed = 1; - } else { - if (dev->next == NULL) { - new_dev = 1; - } else if (strncmp(dev->next->name, "eth", 3) != 0) { - new_dev = 1; - } - } - if ((dev->next == NULL) || new_dev || fixed) break; - dev = dev->next; - num_eth++; - } - if (adev && !fixed) { - dev = adev; num_eth = depca_dev_index(dev->name); - new_dev = 0; - } + if (loading_module) + return dev; - if (((dev->next == NULL) && - ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || - new_dev) { - num_eth++; /* New device */ - dev = insert_device(dev, iobase, depca_probe); - } - - return dev; + while (1) { + if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) && !adev) { + adev = dev; + } else if ((dev->priv == NULL) && (dev->base_addr == iobase)) { + fixed = 1; + } else { + if (dev->next == NULL) { + new_dev = 1; + } else if (strncmp(dev->next->name, "eth", 3) != 0) { + new_dev = 1; + } + } + if ((dev->next == NULL) || new_dev || fixed) + break; + dev = dev->next; + num_eth++; + } + if (adev && !fixed) { + dev = adev; + num_eth = depca_dev_index(dev->name); + new_dev = 0; + } + + if (((dev->next == NULL) && ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || new_dev) { + num_eth++; /* New device */ + dev = insert_device(dev, iobase, depca_probe); + } + + return dev; } /* ** If at end of eth device list and can't use current entry, malloc ** one up. If memory could not be allocated, print an error message. */ -__initfunc(static struct device * -insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))) +__initfunc(static struct device * insert_device(struct device *dev, u_long iobase, int (*init) (struct device *))) { - struct device *new; + struct device *new; - new = (struct device *)kmalloc(sizeof(struct device)+8, GFP_KERNEL); - if (new == NULL) { - printk("eth%d: Device not initialised, insufficient memory\n",num_eth); - return NULL; - } else { - new->next = dev->next; - dev->next = new; - dev = dev->next; /* point to the new device */ - dev->name = (char *)(dev + 1); - if (num_eth > 9999) { - sprintf(dev->name,"eth????");/* New device name */ + new = (struct device *) kmalloc(sizeof(struct device) + 8, GFP_KERNEL); + if (new == NULL) { + printk("eth%d: Device not initialised, insufficient memory\n", num_eth); + return NULL; } else { - sprintf(dev->name,"eth%d", num_eth);/* New device name */ + new->next = dev->next; + dev->next = new; + dev = dev->next; /* point to the new device */ + dev->name = (char *) (dev + 1); + if (num_eth > 9999) { + sprintf(dev->name, "eth????"); /* New device name */ + } else { + sprintf(dev->name, "eth%d", num_eth); /* New device name */ + } + dev->base_addr = iobase; /* assign the io address */ + dev->init = init; /* initialisation routine */ } - dev->base_addr = iobase; /* assign the io address */ - dev->init = init; /* initialisation routine */ - } - return dev; + return dev; } -__initfunc(static int -depca_dev_index(char *s)) +__initfunc(static int depca_dev_index(char *s)) { - int i=0, j=0; + int i = 0, j = 0; - for (;*s; s++) { - if (isdigit(*s)) { - j=1; - i = (i * 10) + (*s - '0'); - } else if (j) break; - } + for (; *s; s++) { + if (isdigit(*s)) { + j = 1; + i = (i * 10) + (*s - '0'); + } else if (j) + break; + } - return i; + return i; } /* @@ -1576,42 +1562,43 @@ ** and Boot (readb) ROM. This will also give us a clue to the network RAM ** base address. */ -__initfunc(static void -DepcaSignature(char *name, u_long paddr)) +__initfunc(static void DepcaSignature(char *name, u_long paddr)) { - u_int i,j,k; - const char *signatures[] = DEPCA_SIGNATURE; - char tmpstr[16]; - - /* Copy the first 16 bytes of ROM */ - for (i=0;i<16;i++) { - tmpstr[i] = readb(paddr+0xc000+i); - } - - /* Check if PROM contains a valid string */ - for (i=0;*signatures[i]!='\0';i++) { - for (j=0,k=0;j<16 && kbase_addr; - int i, k, tmp, status = 0; - u_short j, x, chksum; - - x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); - - for (i=0,k=0,j=0;j<3;j++) { - k <<= 1 ; - if (k > 0xffff) k-=0xffff; - - k += (u_char) (tmp = inb(DEPCA_PROM + x)); - dev->dev_addr[i++] = (u_char) tmp; - k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8); - dev->dev_addr[i++] = (u_char) tmp; + u_long ioaddr = dev->base_addr; + int i, k, tmp, status = 0; + u_short j, x, chksum; + + x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); + + for (i = 0, k = 0, j = 0; j < 3; j++) { + k <<= 1; + if (k > 0xffff) + k -= 0xffff; + + k += (u_char) (tmp = inb(DEPCA_PROM + x)); + dev->dev_addr[i++] = (u_char) tmp; + k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8); + dev->dev_addr[i++] = (u_char) tmp; - if (k > 0xffff) k-=0xffff; - } - if (k == 0xffff) k=0; + if (k > 0xffff) + k -= 0xffff; + } + if (k == 0xffff) + k = 0; - chksum = (u_char) inb(DEPCA_PROM + x); - chksum |= (u_short) (inb(DEPCA_PROM + x) << 8); - if (k != chksum) status = -1; + chksum = (u_char) inb(DEPCA_PROM + x); + chksum |= (u_short) (inb(DEPCA_PROM + x) << 8); + if (k != chksum) + status = -1; - return status; + return status; } /* @@ -1716,165 +1706,161 @@ */ static int load_packet(struct device *dev, struct sk_buff *skb) { - struct depca_private *lp = (struct depca_private *)dev->priv; - int i, entry, end, len, status = 0; + struct depca_private *lp = (struct depca_private *) dev->priv; + int i, entry, end, len, status = 0; - entry = lp->tx_new; /* Ring around buffer number. */ - end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask; - if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {/* Enough room? */ - /* - ** Caution: the write order is important here... don't set up the - ** ownership rights until all the other information is in place. - */ - if (end < entry) { /* wrapped buffer */ - len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ; - memcpy_toio(lp->tx_memcpy[entry], skb->data, len); - memcpy_toio(lp->tx_memcpy[0], skb->data + len, skb->len - len); - } else { /* linear buffer */ - memcpy_toio(lp->tx_memcpy[entry], skb->data, skb->len); - } - - /* set up the buffer descriptors */ - len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; - for (i = entry; i != end; i = (++i) & lp->txRingMask) { - /* clean out flags */ - writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); - writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ - writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */ - len -= TX_BUFF_SZ; - } - /* clean out flags */ - writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); - writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ - writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ - - /* start of packet */ - writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); - /* end of packet */ - writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base); - - for (i=end; i!=entry; --i) { - /* ownership of packet */ - writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base); - if (i == 0) i=lp->txRingMask+1; - } - writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base); - - lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */ - } else { - status = -1; - } + entry = lp->tx_new; /* Ring around buffer number. */ + end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask; + if (!(readl(&lp->tx_ring[end].base) & T_OWN)) { /* Enough room? */ + /* + ** Caution: the write order is important here... don't set up the + ** ownership rights until all the other information is in place. + */ + if (end < entry) { /* wrapped buffer */ + len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ; + memcpy_toio(lp->tx_memcpy[entry], skb->data, len); + memcpy_toio(lp->tx_memcpy[0], skb->data + len, skb->len - len); + } else { /* linear buffer */ + memcpy_toio(lp->tx_memcpy[entry], skb->data, skb->len); + } - return status; + /* set up the buffer descriptors */ + len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; + for (i = entry; i != end; i = (++i) & lp->txRingMask) { + /* clean out flags */ + writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); + writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ + writew(-TX_BUFF_SZ, &lp->tx_ring[i].length); /* packet length in buffer */ + len -= TX_BUFF_SZ; + } + /* clean out flags */ + writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); + writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ + writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ + + /* start of packet */ + writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); + /* end of packet */ + writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base); + + for (i = end; i != entry; --i) { + /* ownership of packet */ + writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base); + if (i == 0) + i = lp->txRingMask + 1; + } + writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base); + + lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */ + } else { + status = -1; + } + + return status; } /* ** Look for a particular board name in the EISA configuration space */ -__initfunc(static int -EISA_signature(char *name, s32 eisa_id)) +__initfunc(static int EISA_signature(char *name, s32 eisa_id)) { - u_int i; - const char *signatures[] = DEPCA_SIGNATURE; - char ManCode[DEPCA_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int status = 0; - - *name = '\0'; - Eisa.ID = inl(eisa_id); - - ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); - ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); - ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); - ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30); - ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); - ManCode[5]='\0'; - - for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name,ManCode); - status = 1; - } - } + u_int i; + const char *signatures[] = DEPCA_SIGNATURE; + char ManCode[DEPCA_STRLEN]; + union { + s32 ID; + char Id[4]; + } Eisa; + int status = 0; + + *name = '\0'; + Eisa.ID = inl(eisa_id); + + ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40); + ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40); + ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30); + ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30); + ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30); + ManCode[5] = '\0'; + + for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) { + if (strstr(ManCode, signatures[i]) != NULL) { + strcpy(name, ManCode); + status = 1; + } + } - return status; + return status; } static void depca_dbg_open(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - struct depca_init *p = (struct depca_init *)lp->sh_mem; - int i; - - if (depca_debug > 1){ - /* Copy the shadow init_block to shared memory */ - memcpy_toio((char *)lp->sh_mem,&lp->init_block,sizeof(struct depca_init)); - - printk("%s: depca open with irq %d\n",dev->name,dev->irq); - printk("Descriptor head addresses:\n"); - printk("\t0x%lx 0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring); - printk("Descriptor addresses:\nRX: "); - for (i=0;irxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); - printk("TX: "); - for (i=0;itxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); - printk("\nDescriptor buffers:\nRX: "); - for (i=0;irxRingMask;i++){ - if (i < 3) { - printk("0x%8.8x ", readl(&lp->rx_ring[i].base)); - } - } - printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base)); - printk("TX: "); - for (i=0;itxRingMask;i++){ - if (i < 3) { - printk("0x%8.8x ", readl(&lp->tx_ring[i].base)); - } - } - printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); - printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem); - printk("\tmode: 0x%4.4x\n",readw(&p->mode)); - printk("\tphysical address: "); - for (i=0;iphys_addr[i])); - } - printk("%2.2x\n",(u_char)readb(&p->phys_addr[i])); - printk("\tmulticast hash table: "); - for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){ - printk("%2.2x:",(u_char)readb(&p->mcast_table[i])); - } - printk("%2.2x\n",(u_char)readb(&p->mcast_table[i])); - printk("\trx_ring at: 0x%8.8x\n",readl(&p->rx_ring)); - printk("\ttx_ring at: 0x%8.8x\n",readl(&p->tx_ring)); - printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs); - printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", - (int)lp->rxRingMask + 1, - lp->rx_rlen); - printk("TX: %d Log2(txRingMask): 0x%8.8x\n", - (int)lp->txRingMask + 1, - lp->tx_rlen); - outw(CSR2,DEPCA_ADDR); - printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA)); - outw(CSR1,DEPCA_ADDR); - printk("%4.4x\n",inw(DEPCA_DATA)); - outw(CSR3,DEPCA_ADDR); - printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA)); - } + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + struct depca_init *p = (struct depca_init *) lp->sh_mem; + int i; + + if (depca_debug > 1) { + /* Copy the shadow init_block to shared memory */ + memcpy_toio((char *) lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); + + printk("%s: depca open with irq %d\n", dev->name, dev->irq); + printk("Descriptor head addresses:\n"); + printk("\t0x%lx 0x%lx\n", (u_long) lp->rx_ring, (u_long) lp->tx_ring); + printk("Descriptor addresses:\nRX: "); + for (i = 0; i < lp->rxRingMask; i++) { + if (i < 3) { + printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); + } + } + printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); + printk("TX: "); + for (i = 0; i < lp->txRingMask; i++) { + if (i < 3) { + printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); + } + } + printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); + printk("\nDescriptor buffers:\nRX: "); + for (i = 0; i < lp->rxRingMask; i++) { + if (i < 3) { + printk("0x%8.8x ", readl(&lp->rx_ring[i].base)); + } + } + printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base)); + printk("TX: "); + for (i = 0; i < lp->txRingMask; i++) { + if (i < 3) { + printk("0x%8.8x ", readl(&lp->tx_ring[i].base)); + } + } + printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); + printk("Initialisation block at 0x%8.8lx\n", lp->sh_mem); + printk("\tmode: 0x%4.4x\n", readw(&p->mode)); + printk("\tphysical address: "); + for (i = 0; i < ETH_ALEN - 1; i++) { + printk("%2.2x:", (u_char) readb(&p->phys_addr[i])); + } + printk("%2.2x\n", (u_char) readb(&p->phys_addr[i])); + printk("\tmulticast hash table: "); + for (i = 0; i < (HASH_TABLE_LEN >> 3) - 1; i++) { + printk("%2.2x:", (u_char) readb(&p->mcast_table[i])); + } + printk("%2.2x\n", (u_char) readb(&p->mcast_table[i])); + printk("\trx_ring at: 0x%8.8x\n", readl(&p->rx_ring)); + printk("\ttx_ring at: 0x%8.8x\n", readl(&p->tx_ring)); + printk("dma_buffs: 0x%8.8lx\n", lp->dma_buffs); + printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", (int) lp->rxRingMask + 1, lp->rx_rlen); + printk("TX: %d Log2(txRingMask): 0x%8.8x\n", (int) lp->txRingMask + 1, lp->tx_rlen); + outw(CSR2, DEPCA_ADDR); + printk("CSR2&1: 0x%4.4x", inw(DEPCA_DATA)); + outw(CSR1, DEPCA_ADDR); + printk("%4.4x\n", inw(DEPCA_DATA)); + outw(CSR3, DEPCA_ADDR); + printk("CSR3: 0x%4.4x\n", inw(DEPCA_DATA)); + } - return; + return; } /* @@ -1884,176 +1870,191 @@ */ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd) { - struct depca_private *lp = (struct depca_private *)dev->priv; - struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data; - int i, status = 0; - u_long ioaddr = dev->base_addr; - union { - u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; - u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; - u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; - } tmp; - - switch(ioc->cmd) { - case DEPCA_GET_HWADDR: /* Get the hardware address */ - for (i=0; idev_addr[i]; - } - ioc->len = ETH_ALEN; - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; - break; - - case DEPCA_SET_HWADDR: /* Set the hardware address */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (copy_from_user(tmp.addr,ioc->data,ETH_ALEN)) return -EFAULT; - for (i=0; idev_addr[i] = tmp.addr[i]; - } - while(dev->tbusy) barrier(); /* Stop ring access */ - test_and_set_bit(0, (void*)&dev->tbusy); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - break; - - case DEPCA_SET_PROM: /* Set Promiscuous Mode */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - while(dev->tbusy) barrier(); /* Stop ring access */ - test_and_set_bit(0, (void*)&dev->tbusy); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - lp->init_block.mode |= PROM; /* Set promiscuous mode */ - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - break; - - case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - while(dev->tbusy) barrier(); /* Stop ring access */ - test_and_set_bit(0, (void*)&dev->tbusy); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */ - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - break; - - case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */ - printk("%s: Boo!\n", dev->name); - break; - - case DEPCA_GET_MCA: /* Get the multicast address table */ - ioc->len = (HASH_TABLE_LEN >> 3); - if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) return -EFAULT; - break; - - case DEPCA_SET_MCA: /* Set a multicast address */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) return -EFAULT; - set_multicast_list(dev); - break; - - case DEPCA_CLR_MCA: /* Clear all multicast addresses */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - set_multicast_list(dev); - break; - - case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - set_multicast_list(dev); - break; - - case DEPCA_GET_STATS: /* Get the driver statistics */ - cli(); - ioc->len = sizeof(lp->pktStats); - if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) - status = -EFAULT; - sti(); - break; - - case DEPCA_CLR_STATS: /* Zero out the driver statistics */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - cli(); - memset(&lp->pktStats, 0, sizeof(lp->pktStats)); - sti(); - break; - - case DEPCA_GET_REG: /* Get the DEPCA Registers */ - i=0; - tmp.sval[i++] = inw(DEPCA_NICSR); - outw(CSR0, DEPCA_ADDR); /* status register */ - tmp.sval[i++] = inw(DEPCA_DATA); - memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); - ioc->len = i+sizeof(struct depca_init); - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; - break; - - default: - return -EOPNOTSUPP; - } + struct depca_private *lp = (struct depca_private *) dev->priv; + struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data; + int i, status = 0; + u_long ioaddr = dev->base_addr; + union { + u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; + u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; + u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; + } tmp; + + switch (ioc->cmd) { + case DEPCA_GET_HWADDR: /* Get the hardware address */ + for (i = 0; i < ETH_ALEN; i++) { + tmp.addr[i] = dev->dev_addr[i]; + } + ioc->len = ETH_ALEN; + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + return -EFAULT; + break; - return status; + case DEPCA_SET_HWADDR: /* Set the hardware address */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) + return -EFAULT; + for (i = 0; i < ETH_ALEN; i++) { + dev->dev_addr[i] = tmp.addr[i]; + } + while (dev->tbusy) + barrier(); /* Stop ring access */ + test_and_set_bit(0, (void *) &dev->tbusy); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + dev->tbusy = 0; /* Unlock the TX ring */ + break; + + case DEPCA_SET_PROM: /* Set Promiscuous Mode */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + while (dev->tbusy) + barrier(); /* Stop ring access */ + test_and_set_bit(0, (void *) &dev->tbusy); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + lp->init_block.mode |= PROM; /* Set promiscuous mode */ + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + dev->tbusy = 0; /* Unlock the TX ring */ + break; + + case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + while (dev->tbusy) + barrier(); /* Stop ring access */ + test_and_set_bit(0, (void *) &dev->tbusy); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */ + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + dev->tbusy = 0; /* Unlock the TX ring */ + break; + + case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */ + printk("%s: Boo!\n", dev->name); + break; + + case DEPCA_GET_MCA: /* Get the multicast address table */ + ioc->len = (HASH_TABLE_LEN >> 3); + if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) + return -EFAULT; + break; + + case DEPCA_SET_MCA: /* Set a multicast address */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (ioc->len > HASH_TABLE_LEN >> 3) + return -EINVAL; + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) + return -EFAULT; + set_multicast_list(dev); + break; + + case DEPCA_CLR_MCA: /* Clear all multicast addresses */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + set_multicast_list(dev); + break; + + case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + set_multicast_list(dev); + break; + + case DEPCA_GET_STATS: /* Get the driver statistics */ + cli(); + ioc->len = sizeof(lp->pktStats); + if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) + status = -EFAULT; + sti(); + break; + + case DEPCA_CLR_STATS: /* Zero out the driver statistics */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + cli(); + memset(&lp->pktStats, 0, sizeof(lp->pktStats)); + sti(); + break; + + case DEPCA_GET_REG: /* Get the DEPCA Registers */ + i = 0; + tmp.sval[i++] = inw(DEPCA_NICSR); + outw(CSR0, DEPCA_ADDR); /* status register */ + tmp.sval[i++] = inw(DEPCA_DATA); + memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); + ioc->len = i + sizeof(struct depca_init); + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + return -EFAULT; + break; + + default: + return -EOPNOTSUPP; + } + + return status; } #ifdef MODULE -static char devicename[9] = {0,}; +static char devicename[9] = { 0, }; static struct device thisDepca = { - devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x200, 7, /* I/O address, IRQ */ - 0, 0, 0, NULL, depca_probe + devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ + 0, 0, 0, 0, + 0x200, 7, /* I/O address, IRQ */ + 0, 0, 0, NULL, depca_probe }; -static int irq=7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ -static int io=0x200; /* Or use the irq= io= options to insmod */ +static int irq = 7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ +static int io = 0x200; /* Or use the irq= io= options to insmod */ MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); -/* See depca_probe() for autoprobe messages when a module */ -int -init_module(void) +/* See depca_probe() for autoprobe messages when a module */ +int init_module(void) { - thisDepca.irq=irq; - thisDepca.base_addr=io; + thisDepca.irq = irq; + thisDepca.base_addr = io; - if (register_netdev(&thisDepca) != 0) - return -EIO; + if (register_netdev(&thisDepca) != 0) + return -EIO; - return 0; + return 0; } -void -cleanup_module(void) +void cleanup_module(void) { - struct depca_private *lp = thisDepca.priv; - if (lp) { -#ifdef CONFIG_MCA - if(lp->mca_slot != -1) - mca_mark_as_unused(lp->mca_slot); -#endif - kfree(lp); - thisDepca.priv = NULL; - } - thisDepca.irq=0; + struct depca_private *lp = thisDepca.priv; + if (lp) { +#ifdef CONFIG_MCA + if (lp->mca_slot != -1) + mca_mark_as_unused(lp->mca_slot); +#endif + kfree(lp); + thisDepca.priv = NULL; + } + thisDepca.irq = 0; - unregister_netdev(&thisDepca); - release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); + unregister_netdev(&thisDepca); + release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); } -#endif /* MODULE */ - +#endif /* MODULE */ + /* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/eepro.c linux/drivers/net/eepro.c --- linux.vanilla/drivers/net/eepro.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/net/eepro.c Fri Aug 30 14:57:33 2002 @@ -23,6 +23,8 @@ This is a compatibility hardware problem. Versions: + 0.13a in memory shortage, drop packets also in board + (Michael Westermann , 07/30/2002) 0.13 irq sharing, rewrote probe function, fixed a nasty bug in hardware_send_packet and a major cleanup (aris, 11/08/2001) 0.12d tottaly isolated old code to new code (blue cards). @@ -633,37 +635,37 @@ i = inb(dev->base_addr + ID_REG); printk(KERN_DEBUG " id: %#x ",i); - printk(KERN_DEBUG " io: %#x ", (unsigned)dev->base_addr); + printk(" io: %#x ", (unsigned)dev->base_addr); switch (lp->eepro) { case LAN595FX_10ISA: - printk(KERN_INFO "%s: Intel EtherExpress 10 ISA\n at %#x,", + printk("%s: Intel EtherExpress 10 ISA\n at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595FX: - printk(KERN_INFO "%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", + printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595TX: - printk(KERN_INFO "%s: Intel EtherExpress Pro/10 ISA at %#x,", + printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595: - printk(KERN_INFO "%s: Intel 82595-based lan card at %#x,", + printk("%s: Intel 82595-based lan card at %#x,", dev->name, (unsigned)dev->base_addr); } for (i=0; i < 6; i++) - printk(KERN_INFO "%c%02x", i ? ':' : ' ', dev->dev_addr[i]); + printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]); if (net_debug > 3) printk(KERN_DEBUG ", %dK RCV buffer", (int)(lp->rcv_ram)/1024); if (dev->irq > 2) - printk(KERN_INFO ", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); + printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); else - printk(KERN_INFO ", %s.\n", ifmap[dev->if_port]); + printk(", %s.\n", ifmap[dev->if_port]); if (net_debug > 3) { i = read_eeprom(dev->base_addr, 5, dev); @@ -1548,6 +1550,10 @@ if (skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; + rcv_car = lp->rx_start + RCV_HEADER + rcv_size; + lp->rx_start = rcv_next_frame; + outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); + break; } skb->dev = dev; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- linux.vanilla/drivers/net/ewrk3.c Sun Mar 25 17:31:16 2001 +++ linux/drivers/net/ewrk3.c Fri Aug 30 14:57:33 2002 @@ -1754,6 +1754,10 @@ break; case EWRK3_SET_MCA: /* Set a multicast address */ if (capable(CAP_NET_ADMIN)) { + if (ioc->len > 1024) { + status = -EINVAL; + break; + } if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) { status = -EFAULT; break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hamradio/baycom_par.c linux/drivers/net/hamradio/baycom_par.c --- linux.vanilla/drivers/net/hamradio/baycom_par.c Sun Mar 25 17:31:17 2001 +++ linux/drivers/net/hamradio/baycom_par.c Fri Aug 30 15:21:05 2002 @@ -83,53 +83,8 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 #include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern __inline__ int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern __inline__ int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 #include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif /* --------------------------------------------------------------------- */ @@ -581,8 +536,6 @@ static const char *mode[NR_PORTS] = { "picpar", }; static int iobase[NR_PORTS] = { 0x378, }; -#if LINUX_VERSION_CODE >= 0x20115 - MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar"); MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); @@ -591,8 +544,6 @@ MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver"); -#endif - __initfunc(int init_module(void)) { int i; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hamradio/soundmodem/sm_sbc.c linux/drivers/net/hamradio/soundmodem/sm_sbc.c --- linux.vanilla/drivers/net/hamradio/soundmodem/sm_sbc.c Sun Mar 25 17:31:18 2001 +++ linux/drivers/net/hamradio/soundmodem/sm_sbc.c Fri Aug 30 15:21:05 2002 @@ -38,45 +38,7 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 #include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif /* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hamradio/soundmodem/sm_wss.c linux/drivers/net/hamradio/soundmodem/sm_wss.c --- linux.vanilla/drivers/net/hamradio/soundmodem/sm_wss.c Fri Nov 2 16:39:07 2001 +++ linux/drivers/net/hamradio/soundmodem/sm_wss.c Fri Aug 30 15:21:05 2002 @@ -52,12 +52,6 @@ #include #include -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - extern inline int copy_from_user(void *to, const void *from, unsigned long n) { int i = verify_area(VERIFY_READ, from, n); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hamradio/yam.c linux/drivers/net/hamradio/yam.c --- linux.vanilla/drivers/net/hamradio/yam.c Sun Mar 25 17:31:18 2001 +++ linux/drivers/net/hamradio/yam.c Fri Aug 30 15:21:05 2002 @@ -76,63 +76,8 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 #include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE < 0x20115 -extern __inline__ void dev_init_buffers(struct device *dev) -{ - int i; - for (i = 0; i < DEV_NUMBUFFS; i++) { - skb_queue_head_init(&dev->buffs[i]); - } -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 #include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif /* --------------------------------------------------------------------- */ @@ -178,11 +123,7 @@ /* Stats section */ -#if LINUX_VERSION_CODE < 0x20119 - struct enet_statistics stats; -#else struct net_device_stats stats; -#endif int nb_rxint; int nb_mdint; @@ -919,13 +860,8 @@ /* --------------------------------------------------------------------- */ -#if LINUX_VERSION_CODE >= 0x20119 static struct net_device_stats * yam_get_stats(struct device *dev) -#else -static struct enet_statistics * - yam_get_stats(struct device *dev) -#endif { struct yam_port *yp; @@ -1266,13 +1202,9 @@ * command line settable parameters */ -#if LINUX_VERSION_CODE >= 0x20115 - MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr"); MODULE_DESCRIPTION("Yam amateur radio modem driver"); -#endif - __initfunc(int init_module(void)) { int ret = yam_init(NULL); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hdlc.c linux/drivers/net/hdlc.c --- linux.vanilla/drivers/net/hdlc.c Sun Mar 25 17:31:22 2001 +++ linux/drivers/net/hdlc.c Mon Sep 16 16:15:30 2002 @@ -19,6 +19,13 @@ * * Use sethdlc utility to set line parameters, protocol and PVCs */ + /* + Patched by Pavel Selivanov. 08 Aug. 2001 + If we are using dev_queue_xmit, and we have a listeners, + we should set skb->nh.raw. If no, we'll get a lot of warnings in + /var/log/debug + Look at core/net/dev.c dev_queue_xmit_nit +*/ #include #include @@ -103,6 +110,7 @@ skb_put(skb, sizeof(cisco_packet)); skb->priority=TC_PRIO_CONTROL; skb->dev = hdlc_to_dev(hdlc); + skb->nh.raw = skb->data; dev_queue_xmit(skb); } @@ -384,7 +392,8 @@ skb_put(skb, i); skb->priority=TC_PRIO_CONTROL; skb->dev = hdlc_to_dev(hdlc); - + skb->nh.raw = skb->data; + dev_queue_xmit(skb); } @@ -820,6 +829,7 @@ { pvc_device *pvc=dev_to_pvc(dev); + skb->nh.raw = skb->data; if (pvc->state & PVC_STATE_ACTIVE) { skb->dev = hdlc_to_dev(pvc->master); pvc->stats.tx_bytes+=skb->len; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sdla_fr.c linux/drivers/net/sdla_fr.c --- linux.vanilla/drivers/net/sdla_fr.c Fri Nov 2 16:39:07 2001 +++ linux/drivers/net/sdla_fr.c Fri Aug 30 15:21:15 2002 @@ -884,6 +884,7 @@ if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) return -EFAULT; + /* XXX: should check cmd.length against size allocated for mbox->data */ /* execute command */ do diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sdla_ppp.c linux/drivers/net/sdla_ppp.c --- linux.vanilla/drivers/net/sdla_ppp.c Sun Mar 25 17:31:19 2001 +++ linux/drivers/net/sdla_ppp.c Fri Aug 30 15:21:15 2002 @@ -533,6 +533,7 @@ if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) return -EFAULT; + /* XXX: should check cmd.length against size allocated for mbox->data */ len = mbox->cmd.length; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sdla_x25.c linux/drivers/net/sdla_x25.c --- linux.vanilla/drivers/net/sdla_x25.c Sun Mar 25 17:31:19 2001 +++ linux/drivers/net/sdla_x25.c Fri Aug 30 15:21:22 2002 @@ -495,6 +495,7 @@ if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) return -EFAULT; + /* XXX: should check cmd.length against size allocated for mbox->data */ /* execute command */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sdlamain.c linux/drivers/net/sdlamain.c --- linux.vanilla/drivers/net/sdlamain.c Sun Mar 25 17:31:19 2001 +++ linux/drivers/net/sdlamain.c Fri Aug 30 15:21:22 2002 @@ -589,6 +589,9 @@ sdla_t* card; int err; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + /* sanity checks */ if ((wandev == NULL) || (wandev->private == NULL)) return -EFAULT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/syncppp.c linux/drivers/net/syncppp.c --- linux.vanilla/drivers/net/syncppp.c Fri Nov 2 16:39:07 2001 +++ linux/drivers/net/syncppp.c Mon Sep 16 16:15:30 2002 @@ -16,7 +16,14 @@ * * Port for Linux-2.1 by Jan "Yenya" Kasprzak */ - + /* + Patched by Pavel Selivanov. 08 Aug. 2001 + If we are using dev_queue_xmit, and we have a listeners, + we should set skb->nh.raw. If no, we'll get a lot of warnings in + /var/log/debug + Look at core/net/dev.c dev_queue_xmit_nit +*/ + /* * Synchronous PPP/Cisco link level subroutines. * Keepalive protocol implemented in both Cisco and PPP modes. @@ -781,6 +788,8 @@ /* Control is high priority so it doesnt get queued behind data */ skb->priority=TC_PRIO_CONTROL; skb->dev = dev; + skb->nh.raw = skb->data; + dev_queue_xmit(skb); } @@ -823,6 +832,8 @@ sp->obytes += skb->len; skb->priority=TC_PRIO_CONTROL; skb->dev = dev; + skb->nh.raw = skb->data; + dev_queue_xmit(skb); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/wanxl.c linux/drivers/net/wanxl.c --- linux.vanilla/drivers/net/wanxl.c Sun Mar 25 17:31:22 2001 +++ linux/drivers/net/wanxl.c Fri Aug 30 15:21:28 2002 @@ -552,6 +552,9 @@ if (copy_from_user(&length, ifr->ifr_data, 4)!=0) return -EFAULT; + if (length > INT_MAX) + return -EINVAL; + switch(cmd) { case HDLCRUN: if (port->card->first_port != port) /* Not initial port */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/zlib.c linux/drivers/net/zlib.c --- linux.vanilla/drivers/net/zlib.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/net/zlib.c Fri Aug 30 14:57:33 2002 @@ -3938,7 +3938,6 @@ r = t; LEAVE } - ZFREE(z, s->sub.trees.blens); Tracev((stderr, "inflate: trees ok, %d * %d bytes used\n", inflate_hufts, sizeof(inflate_huft))); if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c --- linux.vanilla/drivers/s390/block/dasd.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/s390/block/dasd.c Fri Aug 30 15:21:37 2002 @@ -2883,8 +2883,12 @@ static ssize_t dasd_devices_write ( struct file *file, const char* user_buf, size_t user_len, loff_t* offset ) { - char * buffer = vmalloc(user_len); + char *buffer; + if (user_len > PAGE_SIZE) + return -EINVAL; + + buffer = vmalloc(user_len + 1); if ( buffer == NULL) return -ENOMEM; copy_from_user ( buffer, user_buf, user_len); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c --- linux.vanilla/drivers/sbus/char/openprom.c Sun Mar 25 17:31:39 2001 +++ linux/drivers/sbus/char/openprom.c Fri Sep 13 14:32:13 2002 @@ -68,7 +68,7 @@ */ static int copyin(struct openpromio *info, struct openpromio **opp_p) { - int bufsize; + unsigned int bufsize; if (!info || !opp_p) return -EFAULT; @@ -331,6 +331,8 @@ { char *tmp; + if (len + 1 < len) + return -EINVAL; tmp = kmalloc(len + 1, GFP_KERNEL); if (!tmp) return -ENOMEM; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c --- linux.vanilla/drivers/sbus/char/sunkbd.c Sun Mar 25 17:31:38 2001 +++ linux/drivers/sbus/char/sunkbd.c Fri Aug 30 15:21:48 2002 @@ -1309,9 +1309,9 @@ copy_to_user_ret((Firm_event *)p, &kbd_queue [kbd_tail], sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); p += sizeof(Firm_event)-sizeof(struct timeval); - __put_user_ret(kbd_queue[kbd_tail].time.tv_sec, (u32 *)p, -EFAULT); + put_user_ret(kbd_queue[kbd_tail].time.tv_sec, (u32 *)p, -EFAULT); p += sizeof(u32); - __put_user_ret(kbd_queue[kbd_tail].time.tv_usec, (u32 *)p, -EFAULT); + put_user_ret(kbd_queue[kbd_tail].time.tv_usec, (u32 *)p, -EFAULT); p += sizeof(u32); } else #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c --- linux.vanilla/drivers/sbus/char/sunmouse.c Sun Mar 25 17:31:39 2001 +++ linux/drivers/sbus/char/sunmouse.c Fri Aug 30 15:21:48 2002 @@ -444,9 +444,9 @@ sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); p += sizeof(Firm_event)-sizeof(struct timeval); - __put_user_ret(q->time.tv_sec, (u32 *)p, -EFAULT); + put_user_ret(q->time.tv_sec, (u32 *)p, -EFAULT); p += sizeof(u32); - __put_user_ret(q->time.tv_usec, (u32 *)p, -EFAULT); + put_user_ret(q->time.tv_usec, (u32 *)p, -EFAULT); p += sizeof(u32); } else #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c --- linux.vanilla/drivers/scsi/3w-xxxx.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/scsi/3w-xxxx.c Fri Sep 13 14:21:57 2002 @@ -132,12 +132,28 @@ Empty stale responses before draining aen queue. Fix tw_scsi_eh_abort() to not reset on every io abort. Set can_queue in SHT to 255 to prevent hang from AEN. + 1.02.00.020 - Fix possible null pointer dereference in tw_scsi_release(). + 1.02.00.021 - Fix bug in tw_aen_drain_queue() where unit # was always zero. + 1.02.00.022 - Add severity levels to AEN strings. + 1.02.00.023 - Fix command interrupt spurious error messages. + 1.02.00.024 - Fix bug in raw command post with data ioctl method. + Fix bug where rollcall sometimes failed with cable errors. + 1.02.00.025 - Print unit # on all command timeouts. + 1.02.00.026 - Fix possible infinite retry bug with power glitch induced + drive timeouts. + Cleanup some AEN severity levels. + 1.02.00.027 - Add drive not supported AEN code for SATA controllers. + Remove spurious unknown ioctl error message. */ #include MODULE_AUTHOR ("3ware Inc."); +#ifdef __SMP__ +MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver (SMP)"); +#else MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver"); +#endif #include #include @@ -183,7 +199,7 @@ }; /* Globals */ -char *tw_driver_version="1.02.00.019"; +char *tw_driver_version="1.02.00.027"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; @@ -194,7 +210,7 @@ { TW_Param *param; unsigned short aen; - int error = 0; + int error = 0, table_max = 0; if (tw_dev->alignment_virtual_address[request_id] == NULL) { printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n"); @@ -206,9 +222,10 @@ /* Print some useful info when certain aen codes come out */ if (aen == 0x0ff) { - printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: AEN queue overflow.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no); } else { - if ((aen & 0x0ff) < TW_AEN_STRING_MAX) { + table_max = sizeof(tw_aen_string)/sizeof(char *); + if ((aen & 0x0ff) < table_max) { if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8); } else { @@ -270,7 +287,7 @@ int first_reset = 0; int queue = 0; int imax, i; - int found = 0; + int found = 0, table_max = 0; dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n"); @@ -278,7 +295,7 @@ status_reg_addr = tw_dev->registers.status_reg_addr; response_que_addr = tw_dev->registers.response_que_addr; - if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 30)) { + if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) { dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_device_extension_count); return 1; } @@ -388,9 +405,10 @@ break; default: if (aen == 0x0ff) { - printk(KERN_WARNING "3w-xxxx: AEN: AEN queue overflow.\n"); + printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n"); } else { - if ((aen & 0x0ff) < TW_AEN_STRING_MAX) { + table_max = sizeof(tw_aen_string)/sizeof(char *); + if ((aen & 0x0ff) < table_max) { if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8); } else { @@ -405,7 +423,7 @@ /* Now put the aen on the aen_queue */ if (queue == 1) { - tw_dev->aen_queue[tw_dev->aen_tail] = aen_code; + tw_dev->aen_queue[tw_dev->aen_tail] = aen; if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { tw_dev->aen_tail = TW_Q_START; } else { @@ -974,7 +992,7 @@ } } if (numcards == 0) - printk(KERN_WARNING "3w-xxxx: tw_findcards(): No cards found.\n"); + printk(KERN_WARNING "3w-xxxx: No cards with valid units found.\n"); else register_reboot_notifier(&tw_notifier); @@ -1433,7 +1451,7 @@ } tw_dev->pending_request_count--; } else { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error posting pending commands.\n", tw_dev->host->host_no); + /* If we get here, we will continue re-posting on the next command interrupt */ break; } } @@ -1464,8 +1482,13 @@ /* Check for correct state */ if (tw_dev->state[request_id] != TW_S_POSTED) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode); - error = 1; + /* Handle timed out ioctl's */ + if (tw_dev->srb[request_id] != 0) { + if (tw_dev->srb[request_id]->cmnd[0] != TW_IOCTL) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode); + error = 1; + } + } } dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id); @@ -1511,7 +1534,8 @@ /* If error, command failed */ if (error == 1) { - tw_dev->srb[request_id]->result = (DID_RESET << 16); + /* Ask for a host reset */ + tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } /* Now complete the io */ @@ -1555,7 +1579,8 @@ TW_Passthru *passthru = NULL; int tw_aen_code, i, use_sg; char *data_ptr; - int total_bytes = 0; + int total_bytes = 0, posted = 0; + struct timeval before, timeout; ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer; if (ioctl == NULL) { @@ -1706,7 +1731,7 @@ if ((u32 *)command_packet->byte8.param.sgl[i].address != NULL) { error = copy_from_user(data_ptr, (u32 *)command_packet->byte8.param.sgl[i].address, command_packet->byte8.param.sgl[i].length); if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } } else { @@ -1736,7 +1761,7 @@ if ((u32 *)command_packet->byte8.io.sgl[i].address != NULL) { error = copy_from_user(data_ptr, (u32 *)command_packet->byte8.io.sgl[i].address, command_packet->byte8.io.sgl[i].length); if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } } else { @@ -1752,15 +1777,31 @@ command_packet->byte8.io.sgl[0].length = total_bytes; } + spin_unlock(&tw_dev->tw_lock); spin_unlock_irq(&io_request_lock); - spin_unlock_irq(&tw_dev->tw_lock); + + set_bit(TW_IN_IOCTL, &tw_dev->flags); /* Finally post the command packet */ tw_post_command_packet(tw_dev, request_id); + posted = 1; + do_gettimeofday(&before); + tw_ioctl_retry: mdelay(TW_IOCTL_WAIT_TIME); - spin_lock_irq(&tw_dev->tw_lock); + if (test_bit(TW_IN_IOCTL, &tw_dev->flags)) { + do_gettimeofday(&timeout); + if (before.tv_sec + TW_IOCTL_TIMEOUT < timeout.tv_sec) { + spin_lock_irq(&io_request_lock); + spin_lock(&tw_dev->tw_lock); + goto tw_ioctl_bail; + } else { + goto tw_ioctl_retry; + } + } + spin_lock_irq(&io_request_lock); + spin_lock(&tw_dev->tw_lock); if (signal_pending(current)) { dprintk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().\n", tw_dev->host->host_no); @@ -1778,7 +1819,7 @@ if ((u32 *)command_save->byte8.param.sgl[i].address != NULL) { error = copy_to_user((u32 *)command_save->byte8.param.sgl[i].address, data_ptr, command_save->byte8.param.sgl[i].length); if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.param.sgl[i].length, current->pid); @@ -1798,7 +1839,7 @@ if ((u32 *)command_save->byte8.io.sgl[i].address != NULL) { error = copy_to_user((u32 *)command_save->byte8.io.sgl[i].address, data_ptr, command_save->byte8.io.sgl[i].length); if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.io.sgl[i].length, current->pid); @@ -1823,7 +1864,8 @@ /* Now complete the io */ tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); - tw_dev->posted_request_count--; + if (posted) + tw_dev->posted_request_count--; tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); return 0; @@ -1832,7 +1874,7 @@ return 1; } default: - printk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode); + dprintk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode); tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); tw_dev->srb[request_id]->result = (DID_OK << 16); @@ -1900,6 +1942,7 @@ break; case TW_CMD_PACKET_WITH_DATA: dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n"); + clear_bit(TW_IN_IOCTL, &tw_dev->flags); return TW_ISR_DONT_COMPLETE; /* Special case for isr to not complete io */ default: memset(buff, 0, tw_dev->srb[request_id]->request_bufflen); @@ -2170,14 +2213,14 @@ for (i=0;isrb[i] == SCpnt) { if (tw_dev->state[i] == TW_S_STARTED) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt); + printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->target, (u32)SCpnt); tw_dev->state[i] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, i); spin_unlock(&tw_dev->tw_lock); return (SUCCESS); } if (tw_dev->state[i] == TW_S_PENDING) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt); + printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->target, (u32)SCpnt); if (tw_dev->pending_head == TW_Q_LENGTH-1) { tw_dev->pending_head = TW_Q_START; } else { @@ -2191,7 +2234,7 @@ } if (tw_dev->state[i] == TW_S_POSTED) { /* If the command has already been posted, we have to reset the card */ - printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt); + printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->target, (u32)SCpnt); /* We have to let AEN requests through before the reset */ spin_unlock(&tw_dev->tw_lock); spin_unlock_irq(&io_request_lock); @@ -2410,6 +2453,11 @@ dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_release()\n"); + /* Fake like we just shut down, so notify the card that + * we "shut down cleanly". + */ + tw_halt(0, 0, 0); // parameters aren't actually used + /* Free up the IO region */ release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE); @@ -2422,11 +2470,6 @@ /* Tell kernel scsi-layer we are gone */ scsi_unregister(tw_host); - /* Fake like we just shut down, so notify the card that - * we "shut down cleanly". - */ - tw_halt(0, 0, 0); // parameters aren't actually used - return 0; } /* End tw_scsi_release() */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/3w-xxxx.h linux/drivers/scsi/3w-xxxx.h --- linux.vanilla/drivers/scsi/3w-xxxx.h Fri Aug 30 14:49:10 2002 +++ linux/drivers/scsi/3w-xxxx.h Mon Sep 16 16:19:00 2002 @@ -60,44 +60,44 @@ /* AEN strings */ static char *tw_aen_string[] = { - "AEN queue empty", // 0x000 - "Soft reset occurred", // 0x001 - "Unit degraded: Unit #", // 0x002 - "Controller error", // 0x003 - "Rebuild failed: Unit #", // 0x004 - "Rebuild complete: Unit #", // 0x005 - "Incomplete unit detected: Unit #", // 0x006 - "Initialization complete: Unit #", // 0x007 - "Unclean shutdown detected: Unit #", // 0x008 - "ATA port timeout: Port #", // 0x009 - "Drive error: Port #", // 0x00A - "Rebuild started: Unit #", // 0x00B - "Initialization started: Unit #", // 0x00C - "Logical unit deleted: Unit #", // 0x00D - NULL, // 0x00E unused - "SMART threshold exceeded: Port #", // 0x00F + "INFO: AEN queue empty", // 0x000 + "INFO: Soft reset occurred", // 0x001 + "ERROR: Unit degraded: Unit #", // 0x002 + "ERROR: Controller error", // 0x003 + "ERROR: Rebuild failed: Unit #", // 0x004 + "INFO: Rebuild complete: Unit #", // 0x005 + "ERROR: Incomplete unit detected: Unit #", // 0x006 + "INFO: Initialization complete: Unit #", // 0x007 + "WARNING: Unclean shutdown detected: Unit #", // 0x008 + "WARNING: ATA port timeout: Port #", // 0x009 + "ERROR: Drive error: Port #", // 0x00A + "INFO: Rebuild started: Unit #", // 0x00B + "INFO: Initialization started: Unit #", // 0x00C + "ERROR: Logical unit deleted: Unit #", // 0x00D + NULL, // 0x00E unused + "WARNING: SMART threshold exceeded: Port #", // 0x00F NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, // 0x010-0x020 unused - "ATA UDMA downgrade: Port #", // 0x021 - "ATA UDMA upgrade: Port #", // 0x022 - "Sector repair occurred: Port #", // 0x023 - "SBUF integrity check failure", // 0x024 - "Lost cached write: Port #", // 0x025 - "Drive ECC error detected: Port #", // 0x026 - "DCB checksum error: Port #", // 0x027 - "DCB unsupported version: Port #", // 0x028 - "Verify started: Unit #", // 0x029 - "Verify failed: Port #", // 0x02A - "Verify complete: Unit #", // 0x02B - "Overwrote bad sector during rebuild: Port #", //0x2C - "Encountered bad sector during rebuild: Port #", //0x2D - "Replacement drive is too small: Port #" //0x2E + NULL, NULL, // 0x010-0x020 unused + "WARNING: ATA UDMA downgrade: Port #", // 0x021 + "WARNING: ATA UDMA upgrade: Port #", // 0x022 + "WARNING: Sector repair occurred: Port #", // 0x023 + "ERROR: SBUF integrity check failure", // 0x024 + "ERROR: Lost cached write: Port #", // 0x025 + "ERROR: Drive ECC error detected: Port #", // 0x026 + "ERROR: DCB checksum error: Port #", // 0x027 + "ERROR: DCB unsupported version: Port #", // 0x028 + "INFO: Verify started: Unit #", // 0x029 + "ERROR: Verify failed: Port #", // 0x02A + "INFO: Verify complete: Unit #", // 0x02B + "WARNING: Overwrote bad sector during rebuild: Port #", //0x02C + "ERROR: Encountered bad sector during rebuild: Port #", //0x02D + "ERROR: Replacement drive is too small: Port #", //0x02E + "WARNING: Verify error: Unit not previously initialized: Unit #", //0x02F + "ERROR: Drive not supported: Port #" // 0x030 }; -#define TW_AEN_STRING_MAX 0x02F - /* Sense key lookup table Format: ESDC/flags,SenseKey,AdditionalSenseCode,AdditionalSenseCodeQualifier @@ -226,11 +226,13 @@ #define TW_MAX_AEN_TRIES 100 #define TW_UNIT_ONLINE 1 #define TW_IN_INTR 1 +#define TW_IN_IOCTL 2 #define TW_MAX_SECTORS 128 #define TW_AEN_WAIT_TIME 1000 #define TW_IOCTL_WAIT_TIME (1 * HZ) /* 1 second */ #define TW_ISR_DONT_COMPLETE 2 #define TW_ISR_DONT_RESULT 3 +#define TW_IOCTL_TIMEOUT 25 /* 25 seconds */ /* Macros */ #define TW_STATUS_ERRORS(x) \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/ips.h linux/drivers/scsi/ips.h --- linux.vanilla/drivers/scsi/ips.h Sun Mar 25 17:31:34 2001 +++ linux/drivers/scsi/ips.h Fri Aug 30 15:33:16 2002 @@ -105,10 +105,6 @@ #define PUT_USER put_user #endif - #ifndef __PUT_USER - #define __PUT_USER __put_user - #endif - #ifndef PUT_USER_RET #define PUT_USER_RET put_user_ret #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/st.c linux/drivers/scsi/st.c --- linux.vanilla/drivers/scsi/st.c Fri Nov 2 16:39:08 2001 +++ linux/drivers/scsi/st.c Fri Aug 30 14:57:33 2002 @@ -1463,7 +1463,7 @@ if (transfer < 0) { if (STps->drv_block >= 0) STps->drv_block += 1; - return (-ENOMEM); + return (-EIO); } (STp->buffer)->buffer_bytes = bytes - transfer; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c --- linux.vanilla/drivers/usb/mdc800.c Fri Nov 2 16:39:08 2001 +++ linux/drivers/usb/mdc800.c Fri Sep 13 14:31:45 2002 @@ -634,7 +634,7 @@ */ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos) { - int left=len, sts=len; /* single transfer size */ + size_t left=len, sts=len; /* single transfer size */ char* ptr=buf; spin_lock (&mdc800->io_lock); @@ -719,7 +719,7 @@ */ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos) { - int i=0; + size_t i=0; spin_lock (&mdc800->io_lock); if (mdc800->state != READY) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- linux.vanilla/drivers/usb/ov511.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/usb/ov511.c Fri Aug 30 15:28:07 2002 @@ -54,8 +54,8 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.28" -#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach & Orion Sky Lawlor & Kevin Moore & Charl P. Botha & Claudio Matsuoka " +#define DRIVER_VERSION "v1.28a for Linux 2.2" +#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach & Orion Sky Lawlor & Kevin Moore & Charl P. Botha & Claudio Matsuoka " #define DRIVER_DESC "OV511 USB Camera Driver" #define OV511_I2C_RETRIES 3 @@ -99,9 +99,6 @@ * programs that expect RGB data (e.g. gqcam) to work with this driver. */ static int force_rgb = 0; -/* Number of seconds before inactive buffers are deallocated */ -static int buf_timeout = 5; - /* Number of cameras to stream from simultaneously */ static int cams = 1; @@ -138,8 +135,6 @@ MODULE_PARM_DESC(aperture, "Read the OV7610/7620 specs"); MODULE_PARM(force_rgb, "i"); MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR"); -MODULE_PARM(buf_timeout, "i"); -MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation"); MODULE_PARM(cams, "i"); MODULE_PARM_DESC(cams, "Number of simultaneous cameras"); MODULE_PARM(retry_sync, "i"); @@ -2037,11 +2032,6 @@ PDEBUG(4, "entered"); down(&ov511->buf_lock); - if (ov511->buf_state == BUF_PEND_DEALLOC) { - ov511->buf_state = BUF_ALLOCATED; - del_timer(&ov511->buf_timer); - } - if (ov511->buf_state == BUF_ALLOCATED) goto out; @@ -2106,42 +2096,11 @@ PDEBUG(4, "leaving"); } -static void ov511_buf_callback(unsigned long data) -{ - struct usb_ov511 *ov511 = (struct usb_ov511 *)data; - PDEBUG(4, "entered"); - down(&ov511->buf_lock); - - if (ov511->buf_state == BUF_PEND_DEALLOC) - ov511_do_dealloc(ov511); - - up(&ov511->buf_lock); - PDEBUG(4, "leaving"); -} - -static void ov511_dealloc(struct usb_ov511 *ov511, int now) +static void ov511_dealloc(struct usb_ov511 *ov511) { - struct timer_list *bt = &(ov511->buf_timer); PDEBUG(4, "entered"); down(&ov511->buf_lock); - - PDEBUG(4, "deallocating buffer memory %s", now ? "now" : "later"); - - if (ov511->buf_state == BUF_PEND_DEALLOC) { - ov511->buf_state = BUF_ALLOCATED; - del_timer(bt); - } - - if (now) - ov511_do_dealloc(ov511); - else { - ov511->buf_state = BUF_PEND_DEALLOC; - init_timer(bt); - bt->function = ov511_buf_callback; - bt->data = (unsigned long)ov511; - bt->expires = jiffies + buf_timeout * HZ; - add_timer(bt); - } + ov511_do_dealloc(ov511); up(&ov511->buf_lock); PDEBUG(4, "leaving"); } @@ -2173,7 +2132,7 @@ err = ov511_init_isoc(ov511); if (err) { - ov511_dealloc(ov511, 0); + ov511_dealloc(ov511); goto out; } @@ -2200,12 +2159,12 @@ ov511_stop_isoc(ov511); if (ov511->dev) - ov511_dealloc(ov511, 0); + ov511_dealloc(ov511); up(&ov511->lock); if (!ov511->dev) { - ov511_dealloc(ov511, 1); + ov511_dealloc(ov511); video_unregister_device(&ov511->vdev); kfree(ov511); ov511 = NULL; @@ -3410,7 +3369,7 @@ /* Free the memory */ if (ov511 && !ov511->user) { - ov511_dealloc(ov511, 1); + ov511_dealloc(ov511); kfree(ov511); ov511 = NULL; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/ov511.h linux/drivers/usb/ov511.h --- linux.vanilla/drivers/usb/ov511.h Sun Mar 25 17:31:42 2001 +++ linux/drivers/usb/ov511.h Mon Sep 16 16:28:24 2002 @@ -219,7 +219,6 @@ enum { BUF_NOT_ALLOCATED, BUF_ALLOCATED, - BUF_PEND_DEALLOC, /* ov511->buf_timer is set */ }; struct usb_device; @@ -341,7 +340,6 @@ /* Framebuffer/sbuf management */ int buf_state; struct semaphore buf_lock; - struct timer_list buf_timer; }; struct cam_list { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/printer.c linux/drivers/usb/printer.c --- linux.vanilla/drivers/usb/printer.c Fri Nov 2 16:39:08 2001 +++ linux/drivers/usb/printer.c Fri Sep 13 14:31:22 2002 @@ -324,14 +324,15 @@ static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct usblp *usblp = file->private_data; - int timeout, err = 0, writecount = 0; + int timeout, err = 0; + size_t writecount = 0; while (writecount < count) { if (usblp->writeurb.status == -EINPROGRESS) { if (file->f_flags & O_NONBLOCK) - return -EAGAIN; + return writecount ? writecount : -EAGAIN; timeout = USBLP_WRITE_TIMEOUT; while (timeout && usblp->writeurb.status == -EINPROGRESS) { @@ -370,7 +371,9 @@ (count - writecount) : USBLP_BUF_SIZE; if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount, - usblp->writeurb.transfer_buffer_length)) return -EFAULT; + usblp->writeurb.transfer_buffer_length)) { + return writecount ? writecount : -EFAULT; + } usblp->writeurb.dev = usblp->dev; usb_submit_urb(&usblp->writeurb); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/rio500.c linux/drivers/usb/rio500.c --- linux.vanilla/drivers/usb/rio500.c Fri Nov 2 16:39:08 2001 +++ linux/drivers/usb/rio500.c Fri Aug 30 15:22:08 2002 @@ -132,7 +132,7 @@ retval = -EFAULT; goto err_out; } - if (rio_cmd.length > PAGE_SIZE) { + if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { retval = -EINVAL; goto err_out; } @@ -201,7 +201,7 @@ break; if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) return -EFAULT; - if (rio_cmd.length > PAGE_SIZE) + if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) return -EINVAL; buffer = (unsigned char *) __get_free_page(GFP_KERNEL); if (buffer == NULL) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- linux.vanilla/drivers/usb/serial/usbserial.c Fri Aug 30 14:49:10 2002 +++ linux/drivers/usb/serial/usbserial.c Fri Aug 30 15:22:08 2002 @@ -840,8 +840,8 @@ dbg(__FUNCTION__ " - port %d", port->number); - if (count == 0) { - dbg(__FUNCTION__ " - write request of 0 bytes"); + if (count <= 0) { + dbg(__FUNCTION__ " - write request of %d bytes", count); return (0); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/cgfourteenfb.c linux/drivers/video/cgfourteenfb.c --- linux.vanilla/drivers/video/cgfourteenfb.c Fri Nov 2 16:39:08 2001 +++ linux/drivers/video/cgfourteenfb.c Fri Aug 30 15:22:15 2002 @@ -283,11 +283,11 @@ case MDI_GET_CFGINFO: mdii = (struct mdi_cfginfo *)arg; put_user_ret(FBTYPE_MDICOLOR, &mdii->mdi_type, -EFAULT); - __put_user_ret(fb->type.fb_height, &mdii->mdi_height, -EFAULT); - __put_user_ret(fb->type.fb_width, &mdii->mdi_width, -EFAULT); - __put_user_ret(fb->s.cg14.mode, &mdii->mdi_mode, -EFAULT); - __put_user_ret(72, &mdii->mdi_pixfreq, -EFAULT); /* FIXME */ - __put_user_ret(fb->s.cg14.ramsize, &mdii->mdi_size, -EFAULT); + put_user_ret(fb->type.fb_height, &mdii->mdi_height, -EFAULT); + put_user_ret(fb->type.fb_width, &mdii->mdi_width, -EFAULT); + put_user_ret(fb->s.cg14.mode, &mdii->mdi_mode, -EFAULT); + put_user_ret(72, &mdii->mdi_pixfreq, -EFAULT); /* FIXME */ + put_user_ret(fb->s.cg14.ramsize, &mdii->mdi_size, -EFAULT); break; case MDI_SET_PIXELMODE: get_user_ret(mode, (int *)arg, -EFAULT); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- linux.vanilla/fs/binfmt_elf.c Fri Nov 2 16:39:08 2001 +++ linux/fs/binfmt_elf.c Fri Aug 30 14:57:33 2002 @@ -1164,7 +1164,7 @@ set_fs(fs); len = current->mm->arg_end - current->mm->arg_start; - if (len >= ELF_PRARGSZ) + if (len < 0 /* overflow */ || len >= ELF_PRARGSZ) len = ELF_PRARGSZ-1; copy_from_user(&psinfo.pr_psargs, (const char *)current->mm->arg_start, len); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/dcache.c linux/fs/dcache.c --- linux.vanilla/fs/dcache.c Fri Nov 2 16:39:08 2001 +++ linux/fs/dcache.c Fri Aug 30 15:22:37 2002 @@ -68,7 +68,7 @@ } /* - * Release the dentry's inode, using the fileystem + * Release the dentry's inode, using the filesystem * d_iput() operation if defined. */ static inline int dentry_iput(struct dentry * dentry) @@ -764,12 +764,15 @@ /* * "buflen" should be PAGE_SIZE or more. */ -char * d_path(struct dentry *dentry, char *buffer, int buflen) +static char * d_path_error(struct dentry *dentry, + char *buffer, int buflen, int *error) { char * end = buffer+buflen; char * retval; struct dentry * root = current->fs->root; + *error = 0; + *--end = '\0'; buflen--; if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) { @@ -794,8 +797,10 @@ break; namelen = dentry->d_name.len; buflen -= namelen + 1; - if (buflen < 0) + if (buflen < 0) { + *error = -ENAMETOOLONG; break; + } end -= namelen; memcpy(end, dentry->d_name.name, namelen); *--end = '/'; @@ -805,6 +810,13 @@ return retval; } +char * d_path(struct dentry *dentry, char *buffer, int buflen) +{ + int error; + + return d_path_error(dentry, buffer, buflen, &error); +} + /* * NOTE! The user-level library version returns a * character pointer. The kernel system call just @@ -835,14 +847,17 @@ error = -ENOMEM; if (page) { unsigned long len; - char * cwd = d_path(pwd, page, PAGE_SIZE); + char * cwd; - error = -ERANGE; - len = PAGE_SIZE + page - cwd; - if (len <= size) { - error = len; - if (copy_to_user(buf, cwd, len)) - error = -EFAULT; + cwd = d_path_error(pwd, page, PAGE_SIZE, &error); + if (!error) { + error = -ERANGE; + len = PAGE_SIZE + page - cwd; + if (len <= size) { + error = len; + if (copy_to_user(buf, cwd, len)) + error = -EFAULT; + } } free_page((unsigned long) page); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/file.c linux/fs/ext2/file.c --- linux.vanilla/fs/ext2/file.c Sun Mar 25 17:30:58 2001 +++ linux/fs/ext2/file.c Fri Sep 13 14:34:08 2002 @@ -164,15 +164,15 @@ int err; int i,buffercount,write_error, new_buffer; unsigned long limit; - + /* POSIX: mtime/ctime may not change for 0 count */ if (!count) return 0; /* This makes the bounds-checking arithmetic later on much more * sane. */ - if (((signed) count) < 0) + if (((ssize_t) count) < 0) return -EINVAL; - + write_error = buffercount = 0; if (!inode) { printk("ext2_file_write: inode = NULL\n"); @@ -206,15 +206,15 @@ /* If the fd's pos is already greater than or equal to the file * descriptor's offset maximum, then we need to return EFBIG for * any non-zero count (and we already tested for zero above). */ - if (((unsigned) pos) >= 0x7FFFFFFFUL) + if (((unsigned long) pos) >= 0x7FFFFFFFUL) return -EFBIG; /* If we are about to overflow the maximum file size, we also * need to return the error, but only if no bytes can be written * successfully. */ - if (((unsigned) pos + count) > 0x7FFFFFFFUL) { + if (((unsigned long) pos + count) > 0x7FFFFFFFUL) { count = 0x7FFFFFFFL - pos; - if (((signed) count) < 0) + if (((ssize_t) count) < 0) return -EFBIG; } #else @@ -246,9 +246,9 @@ limit = current->rlim[RLIMIT_FSIZE].rlim_cur; if (limit < RLIM_INFINITY) { - if (((unsigned) pos+count) >= limit) { + if (((unsigned long) pos + count) >= limit) { count = limit - pos; - if (((signed) count) <= 0) { + if (((ssize_t) count) <= 0) { send_sig(SIGXFSZ, current, 0); return -EFBIG; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/fat/misc.c linux/fs/fat/misc.c --- linux.vanilla/fs/fat/misc.c Fri Aug 30 14:49:10 2002 +++ linux/fs/fat/misc.c Fri Aug 30 15:23:54 2002 @@ -554,7 +554,8 @@ int fat_parent_ino(struct inode *dir,int locked) { static int zero = 0; - int error,curr,prev,nr; + int error,curr,prev; + loff_t nr; PRINTK(("fat_parent_ino: Debug 0\n")); if (!S_ISDIR(dir->i_mode)) panic("Non-directory fed to m_p_i"); @@ -585,7 +586,7 @@ if (!locked) fat_unlock_creation(); return error; } - PRINTK(("fat_parent_ino: Debug 6 nr=%d\n", nr)); + PRINTK(("fat_parent_ino: Debug 6 nr=%ld\n", (long)nr)); } if (!locked) fat_unlock_creation(); return nr; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/isofs/inode.c linux/fs/isofs/inode.c --- linux.vanilla/fs/isofs/inode.c Sun Mar 25 17:37:38 2001 +++ linux/fs/isofs/inode.c Fri Aug 30 14:59:10 2002 @@ -430,10 +430,11 @@ /* If a minor device was explicitly opened, set session to the * minor number. For instance, if /dev/hdc1 is mounted, session * 1 on the CD-ROM is selected. CD_PART_MAX gives access to - * a max of 64 sessions on IDE. SCSI drives must still use - * the session option to mount. + * a max of 64 sessions on IDE. For SCSI drives or loop devices + * you must still use the session option to mount. */ - if ((MINOR(dev) % CD_PART_MAX) && (MAJOR(dev) != SCSI_CDROM_MAJOR)) + if ((MINOR(dev) % CD_PART_MAX) && (MAJOR(dev) != SCSI_CDROM_MAJOR) + && (MAJOR(dev) != LOOP_MAJOR)) session = MINOR(dev) % CD_PART_MAX; if (session > 0 && session <= CD_PART_MAX) { struct cdrom_tocentry entry; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfs/read.c linux/fs/nfs/read.c --- linux.vanilla/fs/nfs/read.c Fri Aug 30 14:49:10 2002 +++ linux/fs/nfs/read.c Fri Sep 13 14:31:45 2002 @@ -432,7 +432,7 @@ nfs_list_remove_request(req); if (task->tk_status >= 0) { - char *p = page_address(page); + char *p = (char *)page_address(page); if (count < PAGE_CACHE_SIZE) { memset(p + count, 0, PAGE_CACHE_SIZE - count); count = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/generic.c linux/fs/proc/generic.c --- linux.vanilla/fs/proc/generic.c Sun Mar 25 17:30:58 2001 +++ linux/fs/proc/generic.c Fri Aug 30 15:24:19 2002 @@ -194,24 +194,42 @@ static long long -proc_file_lseek(struct file * file, long long offset, int orig) +proc_file_lseek(struct file * file, long long offset, int origin) { - switch (orig) { - case 0: + struct inode *inode = file->f_dentry->d_inode; + if (offset < 0) - return -EINVAL; - file->f_pos = offset; - return(file->f_pos); - case 1: - if (offset + file->f_pos < 0) - return -EINVAL; - file->f_pos += offset; - return(file->f_pos); - case 2: - return(-EINVAL); - default: - return(-EINVAL); - } + return -EINVAL; + + switch (origin) { + case 2: + /* + * XXX: We don't always have a size, but older 2.2.x + * kernels didn't support SEEK_END with procfs at all + * so this should be OK for 2.2.x. + */ + if (!inode->i_size) + return -EINVAL; + offset += inode->i_size; + break; + + case 1: + offset += file->f_pos; + } + + /* + * No reason to seek beyond end of file for what we have on procfs. + * XXX: Assume that files for which we don't have a size are small. + */ + if (offset < 0 || offset > (inode->i_size ?: 0x10000000)) + return -EINVAL; + + if (offset != file->f_pos) { + file->f_pos = offset; + file->f_reada = 0; + } + + return offset; } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/omirr.c linux/fs/proc/omirr.c --- linux.vanilla/fs/proc/omirr.c Sun Mar 25 17:30:58 2001 +++ linux/fs/proc/omirr.c Fri Aug 30 15:24:31 2002 @@ -112,7 +112,7 @@ if(!count) goto done; error = -EINVAL; - if(!buf || count < 0) + if(!buf || count > INT_MAX) goto done; error = verify_area(VERIFY_WRITE, buf, count); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c --- linux.vanilla/fs/proc/openpromfs.c Sun Mar 25 17:30:58 2001 +++ linux/fs/proc/openpromfs.c Fri Sep 13 14:33:02 2002 @@ -67,7 +67,7 @@ { struct inode *inode = file->f_dentry->d_inode; char buffer[10]; - + if (count < 0 || !inode->u.generic_ip) return -EINVAL; sprintf (buffer, "%8.8x\n", (u32)(long)(inode->u.generic_ip)); @@ -75,7 +75,7 @@ return 0; if (count > 9 - file->f_pos) count = 9 - file->f_pos; - copy_to_user(buf, buffer + file->f_pos, count); + copy_to_user_ret(buf, buffer + file->f_pos, count, -EFAULT); file->f_pos += count; return count; } @@ -90,8 +90,8 @@ u32 *q; openprom_property *op; char buffer[64]; - - if (filp->f_pos >= 0xffffff) + + if (filp->f_pos >= 0xffffff || count >= 0xffffff) return -EINVAL; if (!filp->private_data) { node = nodes[(u16)((long)inode->u.generic_ip)].node; @@ -182,7 +182,7 @@ if (count > i - k) count = i - k; if (op->flag & OPP_STRING) { if (!k) { - __put_user('\'', buf); + put_user_ret('\'', buf, -EFAULT); k++; count--; } @@ -193,16 +193,16 @@ j = count; if (j >= 0) { - copy_to_user(buf + k - filp->f_pos, - op->value + k - 1, j); + copy_to_user_ret(buf + k - filp->f_pos, + op->value + k - 1, j, -EFAULT); count -= j; k += j; } if (count) - __put_user('\'', &buf [k++ - filp->f_pos]); + put_user_ret('\'', &buf [k++ - filp->f_pos], -EFAULT); if (count > 1) - __put_user('\n', &buf [k++ - filp->f_pos]); + put_user_ret('\n', &buf [k++ - filp->f_pos], -EFAULT); } else if (op->flag & OPP_STRINGLIST) { char *tmp; @@ -223,7 +223,7 @@ } strcpy(s, "'\n"); - copy_to_user(buf, tmp + k, count); + copy_to_user_ret(buf, tmp + k, count, -EFAULT); kfree(tmp); k += count; @@ -241,53 +241,63 @@ if (first == last) { sprintf (buffer, "%08x.", *first); - copy_to_user (buf, buffer + first_off, last_cnt - first_off); + copy_to_user_ret (buf, buffer + first_off, + last_cnt - first_off, -EFAULT); buf += last_cnt - first_off; } else { for (q = first; q <= last; q++) { sprintf (buffer, "%08x.", *q); if (q == first) { - copy_to_user (buf, buffer + first_off, - 9 - first_off); + copy_to_user_ret (buf, + buffer + first_off, + 9 - first_off, -EFAULT); buf += 9 - first_off; } else if (q == last) { - copy_to_user (buf, buffer, last_cnt); + copy_to_user_ret (buf, buffer, + last_cnt, -EFAULT); buf += last_cnt; } else { - copy_to_user (buf, buffer, 9); + copy_to_user_ret (buf, buffer, + 9, -EFAULT); buf += 9; } } } if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9) - __put_user('\n', (buf - 1)); + put_user_ret('\n', (buf - 1), -EFAULT); k += count; } else if (op->flag & OPP_HEXSTRING) { - char buffer[2]; + char buffer[3]; if ((k < i - 1) && (k & 1)) { - sprintf (buffer, "%02x", *(op->value + (k >> 1))); - __put_user(buffer[1], &buf[k++ - filp->f_pos]); + sprintf (buffer, "%02x", + (unsigned char)*(op->value + (k >> 1)) & 0xff); + put_user_ret(buffer[1], &buf[k++ - filp->f_pos], + -EFAULT); count--; } for (; (count > 1) && (k < i - 1); k += 2) { - sprintf (buffer, "%02x", *(op->value + (k >> 1))); - copy_to_user (buf + k - filp->f_pos, buffer, 2); + sprintf (buffer, "%02x", + (unsigned char)*(op->value + (k >> 1)) & 0xff); + copy_to_user_ret (buf + k - filp->f_pos, buffer, 2, + -EFAULT); count -= 2; } if (count && (k < i - 1)) { - sprintf (buffer, "%02x", *(op->value + (k >> 1))); - __put_user(buffer[0], &buf[k++ - filp->f_pos]); + sprintf (buffer, "%02x", + (unsigned char)*(op->value + (k >> 1)) & 0xff); + put_user_ret(buffer[0], &buf[k++ - filp->f_pos], + -EFAULT); count--; } if (count) - __put_user('\n', &buf [k++ - filp->f_pos]); + put_user_ret('\n', &buf [k++ - filp->f_pos], -EFAULT); } count = k - filp->f_pos; filp->f_pos = k; @@ -302,8 +312,8 @@ u32 *q; void *b; openprom_property *op; - - if (filp->f_pos >= 0xffffff) + + if (filp->f_pos >= 0xffffff || count >= 0xffffff) return -EINVAL; if (!filp->private_data) { i = property_read (filp, NULL, 0, 0); @@ -324,7 +334,7 @@ if (j == 9) j = 0; if (!j) { char ctmp; - __get_user(ctmp, &buf[i]); + get_user_ret(ctmp, &buf[i], -EFAULT); if (ctmp != '.') { if (ctmp != '\n') { if (op->flag & OPP_BINARY) @@ -339,7 +349,7 @@ } } else { char ctmp; - __get_user(ctmp, &buf[i]); + get_user_ret(ctmp, &buf[i], -EFAULT); if (ctmp < '0' || (ctmp > '9' && ctmp < 'A') || (ctmp > 'F' && ctmp < 'a') || @@ -377,8 +387,9 @@ last_cnt = (k + count) % 9; if (first + 1 == last) { memset (tmp, '0', 8); - copy_from_user (tmp + first_off, buf, - (count + first_off > 8) ? 8 - first_off : count); + copy_from_user_ret (tmp + first_off, buf, + (count + first_off > 8) ? 8 - first_off : count, + -EFAULT); mask = 0xffffffff; mask2 = 0xffffffff; for (j = 0; j < first_off; j++) @@ -397,8 +408,9 @@ if (q == first) { if (first_off < 8) { memset (tmp, '0', 8); - copy_from_user (tmp + first_off, buf, - 8 - first_off); + copy_from_user_ret ( + tmp + first_off, buf, + 8 - first_off, -EFAULT); mask = 0xffffffff; for (j = 0; j < first_off; j++) mask >>= 1; @@ -409,7 +421,8 @@ } else if ((q == last - 1) && last_cnt && (last_cnt < 8)) { memset (tmp, '0', 8); - copy_from_user (tmp, buf, last_cnt); + copy_from_user_ret (tmp, buf, last_cnt, + -EFAULT); mask = 0xffffffff; for (j = 0; j < 8 - last_cnt; j++) mask <<= 1; @@ -419,7 +432,8 @@ } else { char tchars[17]; /* XXX yuck... */ - copy_from_user(tchars, buf, 16); + copy_from_user_ret(tchars, buf, 16, + -EFAULT); *q = simple_strtoul (tchars, 0, 16); buf += 9; } @@ -442,7 +456,7 @@ */ if (k > 0) return -EINVAL; - __get_user(ctmp, buf); + get_user_ret(ctmp, buf, -EFAULT); if (ctmp == '\'') { op->flag |= OPP_QUOTED; buf++; @@ -474,7 +488,7 @@ kfree (b); } p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0); - copy_from_user (p, buf, count); + copy_from_user_ret (p, buf, count, -EFAULT); op->flag |= OPP_DIRTY; for (i = 0; i < count; i++, p++) if (*p == '\n') { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/proc_tty.c linux/fs/proc/proc_tty.c --- linux.vanilla/fs/proc/proc_tty.c Sun Mar 25 17:30:58 2001 +++ linux/fs/proc/proc_tty.c Fri Aug 30 15:24:46 2002 @@ -36,10 +36,15 @@ { int len = 0; off_t begin = 0; + off_t end; struct tty_driver *p; char range[20], deftype[20]; char *type; + end = off + count; /* XXX: undefined on overflow per ISO C99 */ + if (end < off) + return -EINVAL; + for (p = tty_drivers; p; p = p->next) { if (p->num > 1) sprintf(range, "%d-%d", p->minor_start, @@ -82,7 +87,7 @@ len += sprintf(page+len, "%-20s /dev/%-8s %3d %7s %s\n", p->driver_name ? p->driver_name : "unknown", p->name, p->major, range, type); - if (len+begin > off+count) + if (len+begin > end) break; if (len+begin < off) { begin += len; @@ -106,13 +111,18 @@ int i; int len = 0; off_t begin = 0; + off_t end; + + end = off + count; /* XXX: undefined on overflow per ISO C99 */ + if (end < off) + return -EINVAL; for (i=0; i < NR_LDISCS; i++) { if (!(ldiscs[i].flags & LDISC_FLAG_DEFINED)) continue; len += sprintf(page+len, "%-10s %2d\n", ldiscs[i].name ? ldiscs[i].name : "???", i); - if (len+begin > off+count) + if (len+begin > end) break; if (len+begin < off) { begin += len; @@ -178,7 +188,14 @@ if (!ent) return; proc_tty_ldisc = create_proc_entry("tty/ldisc", S_IFDIR, 0); - proc_tty_driver = create_proc_entry("tty/driver", S_IFDIR, 0); + /* + * /proc/tty/driver/serial reveals the exact character counts for + * serial links which is just too easy to abuse for inferring + * password lengths and inter-keystroke timings during password + * entry. + */ + proc_tty_driver = create_proc_entry("tty/driver", + S_IFDIR | S_IRUSR | S_IXUSR, 0); ent = create_proc_entry("tty/ldiscs", 0, 0); ent->read_proc = tty_ldiscs_read_proc; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/select.c linux/fs/select.c --- linux.vanilla/fs/select.c Sun Mar 25 17:30:58 2001 +++ linux/fs/select.c Fri Aug 30 14:57:33 2002 @@ -412,7 +412,7 @@ lock_kernel(); /* Do a sanity check on nfds ... */ err = -EINVAL; - if (nfds > current->files->max_fds) + if (nfds > current->files->max_fds || nfds > 0x100000) goto out; if (timeout) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/ioctls.h linux/include/asm-i386/ioctls.h --- linux.vanilla/include/asm-i386/ioctls.h Sun Mar 25 17:31:05 2001 +++ linux/include/asm-i386/ioctls.h Fri Aug 30 14:57:33 2002 @@ -6,7 +6,7 @@ /* 0x54 is just a magic number to make these relatively unique ('T') */ #define TCGETS 0x5401 -#define TCSETS 0x5402 +#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */ #define TCSETSW 0x5403 #define TCSETSF 0x5404 #define TCGETA 0x5405 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/stat.h linux/include/linux/stat.h --- linux.vanilla/include/linux/stat.h Sun Mar 25 17:31:03 2001 +++ linux/include/linux/stat.h Fri Aug 30 15:25:28 2002 @@ -52,6 +52,7 @@ #define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) #define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) #define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) +#define S_IRXUG (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP) #endif #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/module.c linux/kernel/module.c --- linux.vanilla/kernel/module.c Fri Nov 2 16:39:16 2001 +++ linux/kernel/module.c Fri Aug 30 15:25:48 2002 @@ -937,6 +937,11 @@ int len = 0; /* code from net/ipv4/proc.c */ off_t pos = 0; off_t begin = 0; + off_t end; + + end = offset + length; /* XXX: undefined on overflow per ISO C99 */ + if (end < offset) + return -EINVAL; for (mod = module_list; mod; mod = mod->next) { unsigned i; @@ -963,7 +968,7 @@ begin = pos; } pos = begin + len; - if (pos > offset+length) + if (pos > end) goto leave_the_loop; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/printk.c linux/kernel/printk.c --- linux.vanilla/kernel/printk.c Sun Mar 25 17:31:02 2001 +++ linux/kernel/printk.c Fri Aug 30 14:57:33 2002 @@ -260,7 +260,7 @@ spin_lock_irqsave(&console_lock, flags); va_start(args, fmt); - i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */ + i = _vsnprintf(buf + 3, sizeof(buf) - sizeof(buf) / 8 - 3, fmt, args); buf_end = buf + 3 + i; va_end(args); for (p = buf + 3; p < buf_end; p++) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/sys.c linux/kernel/sys.c --- linux.vanilla/kernel/sys.c Sun Mar 25 17:37:40 2001 +++ linux/kernel/sys.c Fri Aug 30 15:26:01 2002 @@ -507,8 +507,8 @@ if (euid != current->euid) current->dumpable = 0; current->euid = euid; - current->fsuid = euid; } + current->fsuid = current->euid; if (suid != (uid_t) -1) current->suid = suid; @@ -554,8 +554,8 @@ if (egid != current->egid) current->dumpable = 0; current->egid = egid; - current->fsgid = egid; } + current->fsgid = current->egid; if (sgid != (gid_t) -1) current->sgid = sgid; return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/sysctl.c linux/kernel/sysctl.c --- linux.vanilla/kernel/sysctl.c Sun Mar 25 17:37:40 2001 +++ linux/kernel/sysctl.c Fri Aug 30 14:57:33 2002 @@ -338,8 +338,11 @@ size_t old_len; if (!oldlenp) return -EFAULT; - if(get_user(old_len, oldlenp)) + if (get_user(old_len, oldlenp)) return -EFAULT; + /* XXX: insufficient for SMP, but should be redundant anyway */ + if ((ssize_t)old_len < 0) + return -EINVAL; } tmp = &root_table_header; do { @@ -459,7 +462,8 @@ * zero, proceed with automatic r/w */ if (table->data && table->maxlen) { if (oldval && oldlenp) { - get_user(len, oldlenp); + if (get_user(len, oldlenp)) + return -EFAULT; if (len) { if (len > table->maxlen) len = table->maxlen; @@ -853,7 +857,7 @@ vleft = table->maxlen / sizeof(int); left = *lenp; - for (; left && vleft--; i++, first=0) { + for (; left && vleft--; i++, min++, max++, first=0) { if (write) { while (left) { char c; @@ -889,9 +893,7 @@ buffer += len; left -= len; - if (min && val < *min++) - continue; - if (max && val > *max++) + if ((min && val < *min) || (max && val > *max)) continue; *i = val; } else { @@ -1047,7 +1049,8 @@ for (i = 0; i < length; i++) { int value; - get_user(value, vec + i); + if (get_user(value, vec + i)) + return -EFAULT; if (min && value < min[i]) return -EINVAL; if (max && value > max[i]) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/lib/vsprintf.c linux/lib/vsprintf.c --- linux.vanilla/lib/vsprintf.c Sun Mar 25 17:31:02 2001 +++ linux/lib/vsprintf.c Fri Sep 13 14:23:57 2002 @@ -142,7 +142,7 @@ /* Forward decl. needed for IP address printing stuff... */ int sprintf(char * buf, const char *fmt, ...); -int vsprintf(char *buf, const char *fmt, va_list args) +int _vsnprintf(char *buf, int n, const char *fmt, va_list args) { int len; unsigned long num; @@ -157,7 +157,7 @@ number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ - for (str=buf ; *fmt ; ++fmt) { + for (str = buf; *fmt && (n == -1 || str - buf < n); ++fmt) { if (*fmt != '%') { *str++ = *fmt; continue; @@ -231,6 +231,12 @@ len = strnlen(s, precision); + if (n != -1 && len >= n - (str - buf)) { + len = n - 1 - (str - buf); + if (len <= 0) break; + if (len < field_width) field_width = len; + } + if (!(flags & LEFT)) while (len < field_width--) *str++ = ' '; @@ -306,6 +312,11 @@ return str-buf; } +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return _vsnprintf(buf, -1, fmt, args); +} + int sprintf(char * buf, const char *fmt, ...) { va_list args; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/vmalloc.c linux/mm/vmalloc.c --- linux.vanilla/mm/vmalloc.c Fri Aug 30 14:49:10 2002 +++ linux/mm/vmalloc.c Fri Sep 13 14:31:22 2002 @@ -160,6 +160,10 @@ if (!area) return NULL; size += PAGE_SIZE; + if (!size) { + kfree(area); + return NULL; + } addr = VMALLOC_START; for (p = &vmlist; (tmp = *p) ; p = &tmp->next) { if ((size + addr) < addr) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/core/neighbour.c linux/net/core/neighbour.c --- linux.vanilla/net/core/neighbour.c Sun Mar 25 17:31:12 2001 +++ linux/net/core/neighbour.c Fri Aug 30 14:57:33 2002 @@ -621,11 +621,11 @@ if (skb) { if (skb_queue_len(&neigh->arp_queue) >= neigh->parms->queue_len) { struct sk_buff *buff; - buff = neigh->arp_queue.prev; + buff = neigh->arp_queue.next; __skb_unlink(buff, &neigh->arp_queue); kfree_skb(buff); } - __skb_queue_head(&neigh->arp_queue, skb); + __skb_queue_tail(&neigh->arp_queue, skb); } end_bh_atomic(); return 1; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/core/skbuff.c linux/net/core/skbuff.c --- linux.vanilla/net/core/skbuff.c Sun Mar 25 17:31:12 2001 +++ linux/net/core/skbuff.c Fri Aug 30 15:26:31 2002 @@ -136,6 +136,8 @@ goto nohead; /* Get the DATA. Size must match skb_add_mtu(). */ + if (size > 131072 - 32) + goto nodata; size = ((size + 15) & ~15); data = kmalloc(size + sizeof(atomic_t), gfp_mask); if (data == NULL) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- linux.vanilla/net/ipv4/ip_fw.c Sun Mar 25 17:31:12 2001 +++ linux/net/ipv4/ip_fw.c Fri Aug 30 15:26:38 2002 @@ -747,6 +747,7 @@ src_port, dst_port, count, tcpsyn)) { ret = FW_BLOCK; + cleanup(chain, 0, slot); goto out; } break; @@ -1132,8 +1133,13 @@ unsigned int i; struct ip_chain *label = kmalloc(SIZEOF_STRUCT_IP_CHAIN, GFP_KERNEL); - if (label == NULL) - panic("Can't kmalloc for firewall chains.\n"); + if (label == NULL) { + /* Only pre-defined chains are created with a non-zero ref */ + if (ref) + panic("Can't kmalloc for firewall chains.\n"); + else + return NULL; + } strcpy(label->label,name); label->next = NULL; label->chain = NULL; @@ -1171,7 +1177,7 @@ * user defined chain * * and therefore can be * deleted */ - return 0; + return tmp->next ? 0 : ENOMEM; } /* This function simply changes the policy on one of the built in diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c --- linux.vanilla/net/ipv4/ip_masq.c Sun Mar 25 17:37:41 2001 +++ linux/net/ipv4/ip_masq.c Fri Aug 30 15:26:46 2002 @@ -2450,7 +2450,7 @@ struct ip_masq_ctl masq_ctl; int ret = -EINVAL; - if(optlen>sizeof(masq_ctl)) + if(optlen < 0 || optlen > sizeof(masq_ctl)) return -EINVAL; if(copy_from_user(&masq_ctl,optval,optlen)) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/route.c linux/net/ipv4/route.c --- linux.vanilla/net/ipv4/route.c Fri Nov 2 16:39:16 2001 +++ linux/net/ipv4/route.c Fri Aug 30 15:26:46 2002 @@ -1998,15 +1998,23 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data) { - *start=buffer; + *start = buffer; - if (offset + length > sizeof(ip_rt_acct)) { + if (offset < 0 || length < 0) + return 0; + + if (offset >= sizeof(ip_rt_acct) || length >= sizeof(ip_rt_acct)) { + *eof = 1; + return 0; + } + + if (offset + length >= sizeof(ip_rt_acct)) { length = sizeof(ip_rt_acct) - offset; *eof = 1; } if (length > 0) { start_bh_atomic(); - memcpy(buffer, ((u8*)&ip_rt_acct)+offset, length); + memcpy(buffer, ((u8*)&ip_rt_acct) + offset, length); end_bh_atomic(); return length; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- linux.vanilla/net/ipv4/tcp.c Fri Nov 2 16:39:16 2001 +++ linux/net/ipv4/tcp.c Fri Aug 30 15:00:30 2002 @@ -940,6 +940,7 @@ if (!err) tcp_push_pending_frames(sk, tp); wait_for_tcp_memory(sk, err); + err = 0; /* If SACK's were formed or PMTU events happened, * we must find out about it. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- linux.vanilla/net/ipv4/tcp_input.c Fri Nov 2 16:39:16 2001 +++ linux/net/ipv4/tcp_input.c Fri Aug 30 15:00:30 2002 @@ -296,7 +296,7 @@ } sk->shutdown = SHUTDOWN_MASK; if (!sk->dead) - sk->state_change(sk); + sk->error_report(sk); } /* This tags the retransmission queue when SACKs arrive. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/socket.c linux/net/socket.c --- linux.vanilla/net/socket.c Sun Mar 25 17:37:41 2001 +++ linux/net/socket.c Fri Aug 30 15:26:46 2002 @@ -1073,11 +1073,19 @@ asmlinkage int sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen) { int err; + int len; struct socket *sock; lock_kernel(); if ((sock = sockfd_lookup(fd, &err))!=NULL) { + /* XXX: insufficient for SMP, but should be redundant anyway */ + if (get_user(len, optlen)) + err = -EFAULT; + else + if (len < 0) + err = -EINVAL; + else if (level == SOL_SOCKET) err=sock_getsockopt(sock,level,optname,optval,optlen); else diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c --- linux.vanilla/net/sunrpc/svcsock.c Sun Mar 25 17:37:42 2001 +++ linux/net/sunrpc/svcsock.c Fri Sep 13 14:31:22 2002 @@ -266,10 +266,10 @@ set_fs(oldfs); #endif - dprintk("svc: socket %p sendto([%p %d... ], %d, %d) = %d\n", - rqstp->rq_sock, - iov[0].iov_base, iov[0].iov_len, nr, - buflen, len); + dprintk("svc: socket %p sendto([%p %lu... ], %d, %d) = %d\n", + rqstp->rq_sock, + iov[0].iov_base, (unsigned long)iov[0].iov_len, nr, + buflen, len); return len; } @@ -326,8 +326,9 @@ set_fs(oldfs); #endif - dprintk("svc: socket %p recvfrom(%p, %d) = %d\n", rqstp->rq_sock, - iov[0].iov_base, iov[0].iov_len, len); + dprintk("svc: socket %p recvfrom(%p, %lu) = %d\n", rqstp->rq_sock, + iov[0].iov_base, (unsigned long)iov[0].iov_len, + len); return len; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/unix/af_unix.c linux/net/unix/af_unix.c --- linux.vanilla/net/unix/af_unix.c Fri Aug 30 14:49:10 2002 +++ linux/net/unix/af_unix.c Fri Aug 30 15:26:54 2002 @@ -540,6 +540,8 @@ return NULL; } u=unix_find_socket_byinode(dentry->d_inode); + if (u && u->type == type) + UPDATE_ATIME(dentry->d_inode); dput(dentry); if (u && u->type != type) { @@ -549,7 +551,16 @@ } } else + { u=unix_find_socket_byname(sunname, len, type, hash); + if (u) + { + struct dentry *dentry; + dentry = u->protinfo.af_unix.dentry; + if (dentry) + UPDATE_ATIME(dentry->d_inode); + } + } if (u==NULL) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/scripts/Menuconfig linux/scripts/Menuconfig --- linux.vanilla/scripts/Menuconfig Sun Mar 25 17:31:56 2001 +++ linux/scripts/Menuconfig Fri Aug 30 14:57:33 2002 @@ -54,7 +54,7 @@ # Change a lot of places to call set_x_info uniformly. # Take out message about preparing version (old sound driver cruft). # -# 13 Dec 1998, Riley H Williams +# 13 Dec 1998, Riley H Williams # When an error occurs, actually display the error message as well as # our comments thereon. #