diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 231897509a3..1155eaa8370 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -841,11 +841,7 @@ SYSCTL_PROC(_machdep, OID_AUTO, idle, CTLTYPE_STRING | CTLFLAG_RW, 0, 0, * Reset registers to default values on exec. */ void -exec_setregs(td, entry, stack, ps_strings) - struct thread *td; - u_long entry; - u_long stack; - u_long ps_strings; +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *regs = td->td_frame; struct pcb *pcb = td->td_pcb; @@ -863,7 +859,7 @@ exec_setregs(td, entry, stack, ps_strings) pcb->pcb_full_iret = 1; bzero((char *)regs, sizeof(struct trapframe)); - regs->tf_rip = entry; + regs->tf_rip = imgp->entry_addr; regs->tf_rsp = ((stack - 8) & ~0xFul) + 8; regs->tf_rdi = stack; /* argv */ regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index d6cddb01441..4b3f0413191 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -880,9 +880,12 @@ pmap_update_pde_invalidate(vm_offset_t va, pd_entry_t newpde) load_cr4(cr4 & ~CR4_PGE); /* * Although preemption at this point could be detrimental to - * performance, it would not lead to an error. + * performance, it would not lead to an error. PG_G is simply + * ignored if CR4.PGE is clear. Moreover, in case this block + * is re-entered, the load_cr4() either above or below will + * modify CR4.PGE flushing the TLB. */ - load_cr4(cr4); + load_cr4(cr4 | CR4_PGE); } } #ifdef SMP diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c index 10ec641bc61..a4293c89a3b 100644 --- a/sys/amd64/ia32/ia32_signal.c +++ b/sys/amd64/ia32/ia32_signal.c @@ -701,11 +701,7 @@ freebsd32_sigreturn(td, uap) * Clear registers on exec */ void -ia32_setregs(td, entry, stack, ps_strings) - struct thread *td; - u_long entry; - u_long stack; - u_long ps_strings; +ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *regs = td->td_frame; struct pcb *pcb = td->td_pcb; @@ -721,12 +717,12 @@ ia32_setregs(td, entry, stack, ps_strings) pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__; bzero((char *)regs, sizeof(struct trapframe)); - regs->tf_rip = entry; + regs->tf_rip = imgp->entry_addr; regs->tf_rsp = stack; regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); regs->tf_ss = _udatasel; regs->tf_cs = _ucode32sel; - regs->tf_rbx = ps_strings; + regs->tf_rbx = imgp->ps_strings; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _ufssel; diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h index 350e773144a..239412cdf96 100644 --- a/sys/amd64/linux32/linux.h +++ b/sys/amd64/linux32/linux.h @@ -203,9 +203,9 @@ struct l_newstat { l_ulong st_size; l_ulong st_blksize; l_ulong st_blocks; - struct l_timespec st_atimespec; - struct l_timespec st_mtimespec; - struct l_timespec st_ctimespec; + struct l_timespec st_atim; + struct l_timespec st_mtim; + struct l_timespec st_ctim; l_ulong __unused4; l_ulong __unused5; } __packed; @@ -219,9 +219,9 @@ struct l_stat { l_ushort st_gid; l_ushort st_rdev; l_long st_size; - struct l_timespec st_atimespec; - struct l_timespec st_mtimespec; - struct l_timespec st_ctimespec; + struct l_timespec st_atim; + struct l_timespec st_mtim; + struct l_timespec st_ctim; l_long st_blksize; l_long st_blocks; l_ulong st_flags; @@ -242,9 +242,9 @@ struct l_stat64 { l_ulong st_blksize; l_ulong st_blocks; l_ulong __pad4; - struct l_timespec st_atimespec; - struct l_timespec st_mtimespec; - struct l_timespec st_ctimespec; + struct l_timespec st_atim; + struct l_timespec st_mtim; + struct l_timespec st_ctim; l_ulonglong st_ino; } __packed; diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index d967ad70113..06f1e979e33 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -124,8 +124,8 @@ static register_t *linux_copyout_strings(struct image_params *imgp); static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params); static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); -static void exec_linux_setregs(struct thread *td, u_long entry, - u_long stack, u_long ps_strings); +static void exec_linux_setregs(struct thread *td, + struct image_params *imgp, u_long stack); static void linux32_fixlimit(struct rlimit *rl, int which); static boolean_t linux32_trans_osrel(const Elf_Note *note, int32_t *osrel); @@ -828,11 +828,7 @@ exec_linux_imgact_try(struct image_params *imgp) * XXX copied from ia32_signal.c. */ static void -exec_linux_setregs(td, entry, stack, ps_strings) - struct thread *td; - u_long entry; - u_long stack; - u_long ps_strings; +exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *regs = td->td_frame; struct pcb *pcb = td->td_pcb; @@ -852,7 +848,7 @@ exec_linux_setregs(td, entry, stack, ps_strings) pcb->pcb_initial_fpucw = __LINUX_NPXCW__; bzero((char *)regs, sizeof(struct trapframe)); - regs->tf_rip = entry; + regs->tf_rip = imgp->entry_addr; regs->tf_rsp = stack; regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); regs->tf_gs = _ugssel; @@ -862,7 +858,7 @@ exec_linux_setregs(td, entry, stack, ps_strings) regs->tf_ss = _udatasel; regs->tf_flags = TF_HASSEGS; regs->tf_cs = _ucode32sel; - regs->tf_rbx = ps_strings; + regs->tf_rbx = imgp->ps_strings; td->td_pcb->pcb_full_iret = 1; load_cr0(rcr0() | CR0_MP | CR0_TS); fpstate_drop(td); diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 49af8e2cdf4..088d2257cee 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -516,15 +516,15 @@ spinlock_exit(void) * Clear registers on exec */ void -exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *tf = td->td_frame; memset(tf, 0, sizeof(*tf)); tf->tf_usr_sp = stack; - tf->tf_usr_lr = entry; + tf->tf_usr_lr = imgp->entry_addr; tf->tf_svc_lr = 0x77777777; - tf->tf_pc = entry; + tf->tf_pc = imgp->entry_addr; tf->tf_spsr = PSR_USR32_MODE; } diff --git a/sys/arm/xscale/ixp425/cambria_fled.c b/sys/arm/xscale/ixp425/cambria_fled.c index 7f678c89896..c2f214d9837 100644 --- a/sys/arm/xscale/ixp425/cambria_fled.c +++ b/sys/arm/xscale/ixp425/cambria_fled.c @@ -74,7 +74,7 @@ fled_attach(device_t dev) sc->sc_led = led_create(fled_cb, dev, "front"); - fled_cb(sc, 1); /* Turn on LED */ + fled_cb(dev, 1); /* Turn on LED */ return 0; } diff --git a/sys/boot/i386/boot2/boot2.c b/sys/boot/i386/boot2/boot2.c index 58f217515df..f521fd7e071 100644 --- a/sys/boot/i386/boot2/boot2.c +++ b/sys/boot/i386/boot2/boot2.c @@ -283,7 +283,7 @@ main(void) for (;;) { if (!autoboot || !OPT_CHECK(RBX_QUIET)) - printf("\nFreeBSD/i386 boot\n" + printf("\nFreeBSD/x86 boot\n" "Default: %u:%s(%u,%c)%s\n" "boot: ", dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, diff --git a/sys/boot/i386/gptboot/gptboot.c b/sys/boot/i386/gptboot/gptboot.c index 96efea6a1d5..6939556eb0d 100644 --- a/sys/boot/i386/gptboot/gptboot.c +++ b/sys/boot/i386/gptboot/gptboot.c @@ -281,7 +281,7 @@ main(void) for (;;) { if (!autoboot || !OPT_CHECK(RBX_QUIET)) - printf("\nFreeBSD/i386 boot\n" + printf("\nFreeBSD/x86 boot\n" "Default: %u:%s(%up%u)%s\n" "boot: ", dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, diff --git a/sys/boot/i386/zfsboot/zfsboot.c b/sys/boot/i386/zfsboot/zfsboot.c index 07ade3ac61d..d312b2a7246 100644 --- a/sys/boot/i386/zfsboot/zfsboot.c +++ b/sys/boot/i386/zfsboot/zfsboot.c @@ -730,7 +730,7 @@ main(void) for (;;) { if (!autoboot || !OPT_CHECK(RBX_QUIET)) - printf("\nFreeBSD/i386 boot\n" + printf("\nFreeBSD/x86 boot\n" "Default: %s:%s\n" "boot: ", spa->spa_name, kname); diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h index b68f8fbbc03..e74da64ecf1 100644 --- a/sys/compat/freebsd32/freebsd32.h +++ b/sys/compat/freebsd32/freebsd32.h @@ -143,15 +143,15 @@ struct stat32 { uid_t st_uid; gid_t st_gid; dev_t st_rdev; - struct timespec32 st_atimespec; - struct timespec32 st_mtimespec; - struct timespec32 st_ctimespec; + struct timespec32 st_atim; + struct timespec32 st_mtim; + struct timespec32 st_ctim; off_t st_size; int64_t st_blocks; u_int32_t st_blksize; u_int32_t st_flags; u_int32_t st_gen; - struct timespec32 st_birthtimespec; + struct timespec32 st_birthtim; unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); }; diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 1284e386cdd..7cc27be5ff3 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -1634,9 +1634,9 @@ copy_stat( struct stat *in, struct stat32 *out) CP(*in, *out, st_uid); CP(*in, *out, st_gid); CP(*in, *out, st_rdev); - TS_CP(*in, *out, st_atimespec); - TS_CP(*in, *out, st_mtimespec); - TS_CP(*in, *out, st_ctimespec); + TS_CP(*in, *out, st_atim); + TS_CP(*in, *out, st_mtim); + TS_CP(*in, *out, st_ctim); CP(*in, *out, st_size); CP(*in, *out, st_blocks); CP(*in, *out, st_blksize); diff --git a/sys/compat/ia32/ia32_signal.h b/sys/compat/ia32/ia32_signal.h index 6ebb0defc63..9daa8d52293 100644 --- a/sys/compat/ia32/ia32_signal.h +++ b/sys/compat/ia32/ia32_signal.h @@ -185,5 +185,5 @@ extern char freebsd4_ia32_sigcode[]; extern int sz_ia32_sigcode; extern int sz_freebsd4_ia32_sigcode; extern void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *); -extern void ia32_setregs(struct thread *td, u_long entry, u_long stack, - u_long ps_strings); +extern void ia32_setregs(struct thread *td, struct image_params *imgp, + u_long stack); diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index ba08fd22162..c095012e0d9 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -1227,6 +1227,24 @@ linprocfs_docmdline(PFS_FILL_ARGS) return (0); } +/* + * Filler function for proc/filesystems + */ +static int +linprocfs_dofilesystems(PFS_FILL_ARGS) +{ + struct vfsconf *vfsp; + + mtx_lock(&Giant); + TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { + if (vfsp->vfc_flags & VFCF_SYNTHETIC) + sbuf_printf(sb, "nodev"); + sbuf_printf(sb, "\t%s\n", vfsp->vfc_name); + } + mtx_unlock(&Giant); + return(0); +} + #if 0 /* * Filler function for proc/modules @@ -1276,6 +1294,8 @@ linprocfs_init(PFS_INIT_ARGS) NULL, NULL, NULL, PFS_RD); pfs_create_file(root, "devices", &linprocfs_dodevices, NULL, NULL, NULL, PFS_RD); + pfs_create_file(root, "filesystems", &linprocfs_dofilesystems, + NULL, NULL, NULL, PFS_RD); pfs_create_file(root, "loadavg", &linprocfs_doloadavg, NULL, NULL, NULL, PFS_RD); pfs_create_file(root, "meminfo", &linprocfs_domeminfo, diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index c457d12a2e9..66009763404 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -2711,7 +2711,7 @@ linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc) /* XXX: If there can be no concurrency: s/M_NOWAIT/M_WAITOK/ */ if ((*ppvc = malloc(sizeof(**ppvc), M_LINUX, M_NOWAIT)) == NULL) return (ENOMEM); /* XXX: linux has no ENOMEM here */ - memcpy(&vclip, *ppvc, sizeof(vclip)); + memcpy(*ppvc, &vclip, sizeof(vclip)); (*ppvc)->next = NULL; return (0); } @@ -2726,6 +2726,8 @@ linux_v4l_cliplist_free(struct video_window *vw) ppvc_next = &((*ppvc)->next); free(*ppvc, M_LINUX); } + vw->clips = NULL; + return (0); } diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c index 8e8936ce016..907d2014c1e 100644 --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -173,9 +173,12 @@ newstat_copyout(struct stat *buf, void *ubuf) tbuf.st_gid = buf->st_gid; tbuf.st_rdev = buf->st_rdev; tbuf.st_size = buf->st_size; - tbuf.st_atime = buf->st_atime; - tbuf.st_mtime = buf->st_mtime; - tbuf.st_ctime = buf->st_ctime; + tbuf.st_atim.tv_sec = buf->st_atim.tv_sec; + tbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; + tbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec; + tbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec; + tbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec; + tbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec; tbuf.st_blksize = buf->st_blksize; tbuf.st_blocks = buf->st_blocks; @@ -260,9 +263,12 @@ stat_copyout(struct stat *buf, void *ubuf) lbuf.st_size = buf->st_size; else lbuf.st_size = -2; - lbuf.st_atime = buf->st_atime; - lbuf.st_mtime = buf->st_mtime; - lbuf.st_ctime = buf->st_ctime; + lbuf.st_atim.tv_sec = buf->st_atim.tv_sec; + lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; + lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec; + lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec; + lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec; + lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec; lbuf.st_blksize = buf->st_blksize; lbuf.st_blocks = buf->st_blocks; lbuf.st_flags = buf->st_flags; @@ -498,9 +504,12 @@ stat64_copyout(struct stat *buf, void *ubuf) lbuf.st_gid = buf->st_gid; lbuf.st_rdev = buf->st_rdev; lbuf.st_size = buf->st_size; - lbuf.st_atime = buf->st_atime; - lbuf.st_mtime = buf->st_mtime; - lbuf.st_ctime = buf->st_ctime; + lbuf.st_atim.tv_sec = buf->st_atim.tv_sec; + lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; + lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec; + lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec; + lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec; + lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec; lbuf.st_blksize = buf->st_blksize; lbuf.st_blocks = buf->st_blocks; diff --git a/sys/compat/svr4/svr4_stat.c b/sys/compat/svr4/svr4_stat.c index cfb8276cee4..cc84396a999 100644 --- a/sys/compat/svr4/svr4_stat.c +++ b/sys/compat/svr4/svr4_stat.c @@ -106,9 +106,9 @@ bsd_to_svr4_stat(st, st4) st4->st_gid = st->st_gid; st4->st_rdev = bsd_to_svr4_odev_t(st->st_rdev); st4->st_size = st->st_size; - st4->st_atim = st->st_atimespec.tv_sec; - st4->st_mtim = st->st_mtimespec.tv_sec; - st4->st_ctim = st->st_ctimespec.tv_sec; + st4->st_atim = st->st_atim.tv_sec; + st4->st_mtim = st->st_mtim.tv_sec; + st4->st_ctim = st->st_ctim.tv_sec; } #endif @@ -127,9 +127,9 @@ bsd_to_svr4_xstat(st, st4) st4->st_gid = st->st_gid; st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev); st4->st_size = st->st_size; - st4->st_atim = st->st_atimespec; - st4->st_mtim = st->st_mtimespec; - st4->st_ctim = st->st_ctimespec; + st4->st_atim = st->st_atim; + st4->st_mtim = st->st_mtim; + st4->st_ctim = st->st_ctim; st4->st_blksize = st->st_blksize; st4->st_blocks = st->st_blocks; strcpy(st4->st_fstype, "unknown"); @@ -150,9 +150,9 @@ bsd_to_svr4_stat64(st, st4) st4->st_gid = st->st_gid; st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev); st4->st_size = st->st_size; - st4->st_atim = st->st_atimespec; - st4->st_mtim = st->st_mtimespec; - st4->st_ctim = st->st_ctimespec; + st4->st_atim = st->st_atim; + st4->st_mtim = st->st_mtim; + st4->st_ctim = st->st_ctim; st4->st_blksize = st->st_blksize; st4->st_blocks = st->st_blocks; strcpy(st4->st_fstype, "unknown"); diff --git a/sys/compat/x86bios/x86bios.c b/sys/compat/x86bios/x86bios.c index 088f073e659..d5512fc43f3 100644 --- a/sys/compat/x86bios/x86bios.c +++ b/sys/compat/x86bios/x86bios.c @@ -56,8 +56,7 @@ __FBSDID("$FreeBSD$"); #define X86BIOS_IVT_SIZE 0x00000500 /* 1K + 256 (BDA) */ #define X86BIOS_SEG_SIZE 0x00010000 /* 64K */ -#define X86BIOS_MEM_SIZE (0x00100000 + X86BIOS_SEG_SIZE) - /* 1M + 64K (high memory) */ +#define X86BIOS_MEM_SIZE 0x00100000 /* 1M */ #define X86BIOS_IVT_BASE 0x00000000 #define X86BIOS_RAM_BASE 0x00001000 @@ -69,7 +68,6 @@ __FBSDID("$FreeBSD$"); #define X86BIOS_R_DS _pad1 #define X86BIOS_R_SS _pad2 -#define X86BIOS_R_SP _pad3.I16_reg.x_reg static struct x86emu x86bios_emu; @@ -113,15 +111,16 @@ x86bios_set_fault(struct x86emu *emu, uint32_t addr) static void * x86bios_get_pages(uint32_t offset, size_t size) { - int i; + vm_offset_t page; - if (offset + size > X86BIOS_MEM_SIZE) + if (offset + size > X86BIOS_MEM_SIZE + X86BIOS_IVT_SIZE) return (NULL); - i = offset / X86BIOS_PAGE_SIZE; - if (x86bios_map[i] != 0) - return ((void *)(x86bios_map[i] + offset - - i * X86BIOS_PAGE_SIZE)); + if (offset >= X86BIOS_MEM_SIZE) + offset -= X86BIOS_MEM_SIZE; + page = x86bios_map[offset / X86BIOS_PAGE_SIZE]; + if (page != 0) + return ((void *)(page + offset % X86BIOS_PAGE_SIZE)); return (NULL); } @@ -306,8 +305,8 @@ x86bios_emu_get_intr(struct x86emu *emu, int intno) sp[2] = htole16(emu->x86.R_FLG); iv = x86bios_get_intr(intno); - emu->x86.R_IP = iv & 0x000f; - emu->x86.R_CS = (iv >> 12) & 0xffff; + emu->x86.R_IP = iv & 0xffff; + emu->x86.R_CS = (iv >> 16) & 0xffff; emu->x86.R_FLG &= ~(F_IF | F_TF); } @@ -354,7 +353,6 @@ x86bios_init_regs(struct x86regs *regs) bzero(regs, sizeof(*regs)); regs->X86BIOS_R_DS = 0x40; regs->X86BIOS_R_SS = x86bios_seg_phys >> 4; - regs->X86BIOS_R_SP = 0xfffe; } void @@ -526,13 +524,6 @@ x86bios_map_mem(void) return (1); } #endif - /* Change attribute for high memory. */ - if (pmap_change_attr((vm_offset_t)x86bios_rom + X86BIOS_ROM_SIZE - - X86BIOS_SEG_SIZE, X86BIOS_SEG_SIZE, PAT_WRITE_BACK) != 0) { - pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); - pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE); - return (1); - } x86bios_seg = contigmalloc(X86BIOS_SEG_SIZE, M_DEVBUF, M_WAITOK, X86BIOS_RAM_BASE, x86bios_rom_phys, X86BIOS_PAGE_SIZE, 0); @@ -556,10 +547,6 @@ x86bios_map_mem(void) X86BIOS_ROM_BASE, X86BIOS_MEM_SIZE - X86BIOS_SEG_SIZE - 1, (void *)((vm_offset_t)x86bios_rom + X86BIOS_ROM_BASE - (vm_offset_t)x86bios_rom_phys)); - printf("x86bios: HIMEM 0x%06x-0x%06x at %p\n", - X86BIOS_MEM_SIZE - X86BIOS_SEG_SIZE, X86BIOS_MEM_SIZE - 1, - (void *)((vm_offset_t)x86bios_rom + X86BIOS_ROM_SIZE - - X86BIOS_SEG_SIZE)); } return (0); diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk index ed565686391..f808c953b0f 100644 --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -15,6 +15,10 @@ MKMODULESENV+= DESTDIR="${DESTDIR}" SYSDIR?= ${S:C;^[^/];${.CURDIR}/&;} MKMODULESENV+= KERNBUILDDIR="${.CURDIR}" SYSDIR="${SYSDIR}" +.if defined(CONF_CFLAGS) +MKMODULESENV+= CONF_CFLAGS="${CONF_CFLAGS}" +.endif + .MAIN: all .for target in all clean cleandepend cleandir clobber depend install \ diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index f9fa59135e7..fd93443a58a 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -328,6 +328,9 @@ ${_src}: .endfor .endif +# Respect configuration-specific C flags. +CFLAGS+= ${CONF_CFLAGS} + MFILES?= dev/acpica/acpi_if.m dev/acpi_support/acpi_wmi_if.m \ dev/agp/agp_if.m dev/ata/ata_if.m dev/eisa/eisa_if.m \ dev/iicbus/iicbb_if.m dev/iicbus/iicbus_if.m \ diff --git a/sys/conf/options b/sys/conf/options index 7869add7a85..fabc0bf772f 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -437,6 +437,7 @@ SCTP_MBCNT_LOGGING opt_sctp.h # Log to KTR mbcnt activity SCTP_PACKET_LOGGING opt_sctp.h # Log to a packet buffer last N packets SCTP_LTRACE_CHUNKS opt_sctp.h # Log to KTR chunks processed SCTP_LTRACE_ERRORS opt_sctp.h # Log to KTR error returns. +SCTP_USE_PERCPU_STAT opt_sctp.h # Use per cpu stats. # # # diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c index a3b1e78a78b..98336786583 100644 --- a/sys/dev/ata/ata-raid.c +++ b/sys/dev/ata/ata-raid.c @@ -2568,8 +2568,15 @@ ata_raid_intel_read_meta(device_t dev, struct ar_softc **raidp) if (meta->generation >= raid->generation) { for (disk = 0; disk < raid->total_disks; disk++) { struct ata_device *atadev = device_get_softc(parent); + int len; - if (!strncmp(raid->disks[disk].serial, atadev->param.serial, + for (len = 0; len < sizeof(atadev->param.serial); len++) { + if (atadev->param.serial[len] < 0x20) + break; + } + len = (len > sizeof(raid->disks[disk].serial)) ? + len - sizeof(raid->disks[disk].serial) : 0; + if (!strncmp(raid->disks[disk].serial, atadev->param.serial + len, sizeof(raid->disks[disk].serial))) { raid->disks[disk].dev = parent; raid->disks[disk].flags |= (AR_DF_PRESENT | AR_DF_ONLINE); @@ -2639,8 +2646,15 @@ ata_raid_intel_write_meta(struct ar_softc *rdp) device_get_softc(device_get_parent(rdp->disks[disk].dev)); struct ata_device *atadev = device_get_softc(rdp->disks[disk].dev); + int len; - bcopy(atadev->param.serial, meta->disk[disk].serial, + for (len = 0; len < sizeof(atadev->param.serial); len++) { + if (atadev->param.serial[len] < 0x20) + break; + } + len = (len > sizeof(rdp->disks[disk].serial)) ? + len - sizeof(rdp->disks[disk].serial) : 0; + bcopy(atadev->param.serial + len, meta->disk[disk].serial, sizeof(rdp->disks[disk].serial)); meta->disk[disk].sectors = rdp->disks[disk].sectors; meta->disk[disk].id = (ch->unit << 16) | atadev->unit; diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index b21fd72c235..4333f2044b7 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -421,7 +421,6 @@ static uint32_t bge_readreg_ind(struct bge_softc *, int); #endif static void bge_writemem_direct(struct bge_softc *, int, int); static void bge_writereg_ind(struct bge_softc *, int, int); -static void bge_set_max_readrq(struct bge_softc *); static int bge_miibus_readreg(device_t, int, int); static int bge_miibus_writereg(device_t, int, int, int); @@ -561,32 +560,6 @@ bge_writemem_ind(struct bge_softc *sc, int off, int val) pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); } -/* - * PCI Express only - */ -static void -bge_set_max_readrq(struct bge_softc *sc) -{ - device_t dev; - uint16_t val; - - dev = sc->bge_dev; - - val = pci_read_config(dev, sc->bge_expcap + PCIR_EXPRESS_DEVICE_CTL, 2); - if ((val & PCIM_EXP_CTL_MAX_READ_REQUEST) != - BGE_PCIE_DEVCTL_MAX_READRQ_4096) { - if (bootverbose) - device_printf(dev, "adjust device control 0x%04x ", - val); - val &= ~PCIM_EXP_CTL_MAX_READ_REQUEST; - val |= BGE_PCIE_DEVCTL_MAX_READRQ_4096; - pci_write_config(dev, sc->bge_expcap + PCIR_EXPRESS_DEVICE_CTL, - val, 2); - if (bootverbose) - printf("-> 0x%04x\n", val); - } -} - #ifdef notdef static uint32_t bge_readreg_ind(struct bge_softc *sc, int off) @@ -2695,7 +2668,8 @@ bge_attach(device_t dev) */ sc->bge_flags |= BGE_FLAG_PCIE; sc->bge_expcap = reg; - bge_set_max_readrq(sc); + if (pci_get_max_read_req(dev) != 4096) + pci_set_max_read_req(dev, 4096); } else { /* * Check if the device is in PCI-X Mode. diff --git a/sys/dev/bktr/ioctl_bt848.h b/sys/dev/bktr/ioctl_bt848.h index 3731e7d2b34..6e50b615deb 100644 --- a/sys/dev/bktr/ioctl_bt848.h +++ b/sys/dev/bktr/ioctl_bt848.h @@ -89,9 +89,9 @@ * EEProm stuff */ struct eeProm { - short offset; - short count; - u_char bytes[ 256 ]; + short offset; + short count; + unsigned char bytes[ 256 ]; }; @@ -147,7 +147,7 @@ struct eeProm { * b23-b16: i2c addr (write) * b31-b24: 1 = write, 0 = read */ -#define BT848_I2CWR _IOWR('x', 57, u_long) /* i2c read-write */ +#define BT848_I2CWR _IOWR('x', 57, unsigned long) /* i2c read-write */ struct bktr_msp_control { unsigned char function; @@ -192,10 +192,10 @@ typedef enum { METEOR_PIXTYPE_RGB, METEOR_PIXTYPE_YUV, struct meteor_pixfmt { - u_int index; /* Index in supported pixfmt list */ + unsigned int index; /* Index in supported pixfmt list */ METEOR_PIXTYPE type; /* What's the board gonna feed us */ - u_int Bpp; /* Bytes per pixel */ - u_long masks[3]; /* R,G,B or Y,U,V masks, respectively */ + unsigned int Bpp; /* Bytes per pixel */ + unsigned long masks[3]; /* R,G,B or Y,U,V masks, respectively */ unsigned swap_bytes :1; /* Bytes swapped within shorts */ unsigned swap_shorts:1; /* Shorts swapped within longs */ }; diff --git a/sys/dev/bktr/ioctl_meteor.h b/sys/dev/bktr/ioctl_meteor.h index 681990aa03c..8e769ecbe92 100644 --- a/sys/dev/bktr/ioctl_meteor.h +++ b/sys/dev/bktr/ioctl_meteor.h @@ -50,27 +50,27 @@ struct meteor_capframe { /* structure for METEOR[GS]ETGEO - get/set geometry */ struct meteor_geomet { - u_short rows; - u_short columns; - u_short frames; - u_long oformat; + unsigned short rows; + unsigned short columns; + unsigned short frames; + unsigned long oformat; } ; /* structure for METEORGCOUNT-get count of frames, fifo errors and dma errors */ struct meteor_counts { - u_long fifo_errors; /* count of fifo errors since open */ - u_long dma_errors; /* count of dma errors since open */ - u_long frames_captured; /* count of frames captured since open */ - u_long even_fields_captured; /* count of even fields captured */ - u_long odd_fields_captured; /* count of odd fields captured */ + unsigned long fifo_errors; /* count of fifo errors since open */ + unsigned long dma_errors; /* count of dma errors since open */ + unsigned long frames_captured; /* count of frames captured since open */ + unsigned long even_fields_captured; /* count of even fields captured */ + unsigned long odd_fields_captured; /* count of odd fields captured */ } ; /* structure for getting and setting direct transfers to vram */ struct meteor_video { - u_long addr; /* Address of location to dma to */ - u_long width; /* Width of memory area */ - u_long banksize; /* Size of Vram bank */ - u_long ramsize; /* Size of Vram */ + unsigned long addr; /* Address of location to dma to */ + unsigned long width; /* Width of memory area */ + unsigned long banksize; /* Size of Vram bank */ + unsigned long ramsize; /* Size of Vram */ }; #define METEORCAPTUR _IOW('x', 1, int) /* capture a frame */ diff --git a/sys/dev/fb/vesa.c b/sys/dev/fb/vesa.c index 26024402d7b..e89ba4b3918 100644 --- a/sys/dev/fb/vesa.c +++ b/sys/dev/fb/vesa.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 1998 Kazutaka YOKOTA and Michael Smith + * Copyright (c) 2009-2010 Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -188,7 +189,7 @@ static int vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, #define STATE_ALL (STATE_HW | STATE_DATA | STATE_DAC | STATE_REG) static ssize_t vesa_bios_state_buf_size(void); static int vesa_bios_save_restore(int code, void *p, size_t size); -#if 0 +#ifdef MODE_TABLE_BROKEN static int vesa_bios_get_line_length(void); #endif static int vesa_bios_set_line_length(int pixel, int *bytes, int *lines); @@ -199,6 +200,7 @@ static int vesa_bios_set_start(int x, int y); static int vesa_map_gen_mode_num(int type, int color, int mode); static int vesa_translate_flags(u_int16_t vflags); static int vesa_translate_mmodel(u_int8_t vmodel); +static int vesa_get_bpscanline(struct vesa_mode *vmode); static int vesa_bios_init(void); static void vesa_clear_modes(video_info_t *info, int color); @@ -558,7 +560,7 @@ vesa_bios_save_restore(int code, void *p, size_t size) return (regs.R_AX != 0x004f); } -#if 0 +#ifdef MODE_TABLE_BROKEN static int vesa_bios_get_line_length(void) { @@ -709,6 +711,43 @@ vesa_translate_mmodel(u_int8_t vmodel) return (V_INFO_MM_OTHER); } +static int +vesa_get_bpscanline(struct vesa_mode *vmode) +{ + int bpsl; + + if ((vmode->v_modeattr & V_MODEGRAPHICS) != 0) { + /* Find the minimum length. */ + switch (vmode->v_bpp / vmode->v_planes) { + case 1: + bpsl = vmode->v_width / 8; + break; + case 2: + bpsl = vmode->v_width / 4; + break; + case 4: + bpsl = vmode->v_width / 2; + break; + default: + bpsl = vmode->v_width * ((vmode->v_bpp + 7) / 8); + bpsl /= vmode->v_planes; + break; + } + + /* Use VBE 3.0 information if it looks sane. */ + if ((vmode->v_modeattr & V_MODELFB) != 0 && + vesa_adp_info->v_version >= 0x0300 && + vmode->v_linbpscanline > bpsl) + return (vmode->v_linbpscanline); + + /* Return the minimum if the mode table looks absurd. */ + if (vmode->v_bpscanline < bpsl) + return (bpsl); + } + + return (vmode->v_bpscanline); +} + #define VESA_MAXSTR 256 #define VESA_STRCPY(dst, src) do { \ @@ -733,7 +772,6 @@ vesa_bios_init(void) void *vmbuf; uint32_t offs; uint16_t vers; - int bpsl; int is_via_cle266; int modes; int i; @@ -858,9 +896,7 @@ vesa_bios_init(void) } #endif - bpsl = (vmode.v_modeattr & V_MODELFB) != 0 && vers >= 0x0300 ? - vmode.v_linbpscanline : vmode.v_bpscanline; - bsize = bpsl * vmode.v_height; + bsize = vesa_get_bpscanline(&vmode) * vmode.v_height; if ((vmode.v_modeattr & V_MODEGRAPHICS) != 0) bsize *= vmode.v_planes; @@ -1209,7 +1245,7 @@ vesa_set_mode(video_adapter_t *adp, int mode) int10_set_mode(adp->va_initial_bios_mode); if (adp->va_info.vi_flags & V_INFO_LINEAR) pmap_unmapdev(adp->va_buffer, - adp->va_buffer_size); + vesa_adp_info->v_memsize * 64 * 1024); /* * Once (*prevvidsw->get_info)() succeeded, * (*prevvidsw->set_mode)() below won't fail... @@ -1241,12 +1277,12 @@ vesa_set_mode(video_adapter_t *adp, int mode) if ((vesa_adp_info->v_flags & V_DAC8) != 0 && (info.vi_flags & V_INFO_GRAPHICS) != 0 && - (info.vi_flags & V_INFO_NONVGA) != 0 && vesa_bios_set_dac(8) > 6) adp->va_flags |= V_ADP_DAC8; if (adp->va_info.vi_flags & V_INFO_LINEAR) - pmap_unmapdev(adp->va_buffer, adp->va_buffer_size); + pmap_unmapdev(adp->va_buffer, + vesa_adp_info->v_memsize * 64 * 1024); #if VESA_DEBUG > 0 printf("VESA: mode set!\n"); @@ -1257,13 +1293,31 @@ vesa_set_mode(video_adapter_t *adp, int mode) (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; vesa_adp->va_crtc_addr = (vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; + + vesa_adp->va_line_width = info.vi_buffer_size / info.vi_height; + if ((info.vi_flags & V_INFO_GRAPHICS) != 0) + vesa_adp->va_line_width /= info.vi_planes; + +#ifdef MODE_TABLE_BROKEN + /* If VBE function returns bigger bytes per scan line, use it. */ + { + int bpsl = vesa_bios_get_line_length(); + if (bpsl > vesa_adp->va_line_width) { + vesa_adp->va_line_width = bpsl; + info.vi_buffer_size = bpsl * info.vi_height; + if ((info.vi_flags & V_INFO_GRAPHICS) != 0) + info.vi_buffer_size *= info.vi_planes; + } + } +#endif + if (info.vi_flags & V_INFO_LINEAR) { #if VESA_DEBUG > 1 printf("VESA: setting up LFB\n"); #endif vesa_adp->va_buffer = (vm_offset_t)pmap_mapdev_attr(info.vi_buffer, - info.vi_buffer_size, PAT_WRITE_COMBINING); + vesa_adp_info->v_memsize * 64 * 1024, PAT_WRITE_COMBINING); vesa_adp->va_window = vesa_adp->va_buffer; vesa_adp->va_window_size = info.vi_buffer_size / info.vi_planes; vesa_adp->va_window_gran = info.vi_buffer_size / info.vi_planes; @@ -1275,9 +1329,6 @@ vesa_set_mode(video_adapter_t *adp, int mode) } vesa_adp->va_buffer_size = info.vi_buffer_size; vesa_adp->va_window_orig = 0; - vesa_adp->va_line_width = info.vi_buffer_size / info.vi_height; - if ((info.vi_flags & V_INFO_GRAPHICS) != 0) - vesa_adp->va_line_width /= info.vi_planes; vesa_adp->va_disp_start.x = 0; vesa_adp->va_disp_start.y = 0; #if VESA_DEBUG > 0 @@ -1322,10 +1373,10 @@ vesa_save_palette(video_adapter_t *adp, u_char *palette) { int bits; - if (adp == vesa_adp && VESA_MODE(adp->va_mode) && - (adp->va_info.vi_flags & V_INFO_NONVGA) != 0) { + if (adp == vesa_adp && VESA_MODE(adp->va_mode)) { bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 8 : 6; - return (vesa_bios_save_palette(0, 256, palette, bits)); + if (vesa_bios_save_palette(0, 256, palette, bits) == 0) + return (0); } return ((*prevvidsw->save_palette)(adp, palette)); @@ -1336,10 +1387,10 @@ vesa_load_palette(video_adapter_t *adp, u_char *palette) { int bits; - if (adp == vesa_adp && VESA_MODE(adp->va_mode) && - (adp->va_info.vi_flags & V_INFO_NONVGA) != 0) { + if (adp == vesa_adp && VESA_MODE(adp->va_mode)) { bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 8 : 6; - return (vesa_bios_load_palette(0, 256, palette, bits)); + if (vesa_bios_load_palette(0, 256, palette, bits) == 0) + return (0); } return ((*prevvidsw->load_palette)(adp, palette)); @@ -1544,8 +1595,6 @@ get_palette(video_adapter_t *adp, int base, int count, return (1); if (!VESA_MODE(adp->va_mode)) return (1); - if ((adp->va_info.vi_flags & V_INFO_NONVGA) == 0) - return (1); bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 8 : 6; r = malloc(count * 3, M_DEVBUF, M_WAITOK); @@ -1582,8 +1631,6 @@ set_palette(video_adapter_t *adp, int base, int count, return (1); if (!VESA_MODE(adp->va_mode)) return (1); - if ((adp->va_info.vi_flags & V_INFO_NONVGA) == 0) - return (1); bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 8 : 6; r = malloc(count * 3, M_DEVBUF, M_WAITOK); diff --git a/sys/dev/fb/vga.c b/sys/dev/fb/vga.c index 7d702ad2b8e..1bcf9350755 100644 --- a/sys/dev/fb/vga.c +++ b/sys/dev/fb/vga.c @@ -1979,6 +1979,7 @@ vga_show_font(video_adapter_t *adp, int page) static int vga_save_palette(video_adapter_t *adp, u_char *palette) { + int bits; int i; prologue(adp, V_ADP_PALETTE, ENODEV); @@ -1988,8 +1989,9 @@ vga_save_palette(video_adapter_t *adp, u_char *palette) * VGA has 6 bit DAC . */ outb(PALRADR, 0x00); + bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2; for (i = 0; i < 256*3; ++i) - palette[i] = inb(PALDATA) << 2; + palette[i] = inb(PALDATA) << bits; inb(adp->va_crtc_addr + 6); /* reset flip/flop */ return 0; } @@ -1998,15 +2000,17 @@ static int vga_save_palette2(video_adapter_t *adp, int base, int count, u_char *r, u_char *g, u_char *b) { + int bits; int i; prologue(adp, V_ADP_PALETTE, ENODEV); outb(PALRADR, base); + bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2; for (i = 0; i < count; ++i) { - r[i] = inb(PALDATA) << 2; - g[i] = inb(PALDATA) << 2; - b[i] = inb(PALDATA) << 2; + r[i] = inb(PALDATA) << bits; + g[i] = inb(PALDATA) << bits; + b[i] = inb(PALDATA) << bits; } inb(adp->va_crtc_addr + 6); /* reset flip/flop */ return 0; @@ -2021,14 +2025,16 @@ vga_save_palette2(video_adapter_t *adp, int base, int count, static int vga_load_palette(video_adapter_t *adp, u_char *palette) { + int bits; int i; prologue(adp, V_ADP_PALETTE, ENODEV); outb(PIXMASK, 0xff); /* no pixelmask */ outb(PALWADR, 0x00); + bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2; for (i = 0; i < 256*3; ++i) - outb(PALDATA, palette[i] >> 2); + outb(PALDATA, palette[i] >> bits); inb(adp->va_crtc_addr + 6); /* reset flip/flop */ outb(ATC, 0x20); /* enable palette */ return 0; @@ -2038,16 +2044,18 @@ static int vga_load_palette2(video_adapter_t *adp, int base, int count, u_char *r, u_char *g, u_char *b) { + int bits; int i; prologue(adp, V_ADP_PALETTE, ENODEV); outb(PIXMASK, 0xff); /* no pixelmask */ outb(PALWADR, base); + bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2; for (i = 0; i < count; ++i) { - outb(PALDATA, r[i] >> 2); - outb(PALDATA, g[i] >> 2); - outb(PALDATA, b[i] >> 2); + outb(PALDATA, r[i] >> bits); + outb(PALDATA, g[i] >> bits); + outb(PALDATA, b[i] >> bits); } inb(adp->va_crtc_addr + 6); /* reset flip/flop */ outb(ATC, 0x20); /* enable palette */ diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c index 055433da4b3..633c6f953b6 100644 --- a/sys/dev/hwpmc/hwpmc_logging.c +++ b/sys/dev/hwpmc/hwpmc_logging.c @@ -298,7 +298,6 @@ pmclog_loop(void *arg) mtx_unlock(&pmc_kthread_mtx); -sigpipe_retry: /* process the request */ PMCDBG(LOG,WRI,2, "po=%p base=%p ptr=%p", po, lb->plb_base, lb->plb_ptr); @@ -322,9 +321,6 @@ sigpipe_retry: if (error) { /* XXX some errors are recoverable */ - if (error == EPIPE) - goto sigpipe_retry; - /* send a SIGIO to the owner and exit */ PROC_LOCK(p); psignal(p, SIGIO); diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 65e5d864986..a03573a6587 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -74,14 +74,9 @@ __FBSDID("$FreeBSD$"); */ static const char fconf[] = "Chan %d PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)"; static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d"; -static const char xact1[] = "HBA attempted queued transaction with disconnect not set for %d.%d.%d"; -static const char xact2[] = "HBA attempted queued transaction to target routine %d on target %d bus %d"; -static const char xact3[] = "HBA attempted queued cmd for %d.%d.%d when queueing disabled"; -static const char pskip[] = "SCSI phase skipped for target %d.%d.%d"; static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x N-Port Handle %d, Connection '%s'"; -static const char finmsg[] = "%d.%d.%d: FIN dl%d resid %ld STS 0x%x SKEY %c XS_ERR=0x%x"; static const char sc4[] = "NVRAM"; -static const char bun[] = "bad underrun for %d.%d (count %d, resid %d, status %s)"; +static const char bun[] = "bad underrun (count %d, resid %d, status %s)"; static const char lipd[] = "Chan %d LIP destroyed %d active commands"; static const char sacq[] = "unable to acquire scratch area"; @@ -107,6 +102,7 @@ static const uint8_t alpa_map[] = { /* * Local function prototypes. */ +static void isp_prt_endcmd(ispsoftc_t *, XS_T *); static int isp_parse_async(ispsoftc_t *, uint16_t); static int isp_parse_async_fc(ispsoftc_t *, uint16_t); static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t *); @@ -1431,10 +1427,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int chan) (sdp->isp_devparam[tgt].goal_offset << 8) | (sdp->isp_devparam[tgt].goal_period); } - isp_prt(isp, ISP_LOGDEBUG0, - "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x", - chan, tgt, mbs.param[2], mbs.param[3] >> 8, - mbs.param[3] & 0xff); + isp_prt(isp, ISP_LOGDEBUG0, "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x", + chan, tgt, mbs.param[2], mbs.param[3] >> 8, mbs.param[3] & 0xff); isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { sdf = DPARM_SAFE_DFLT; @@ -1705,8 +1699,7 @@ isp_fibre_init(ispsoftc_t *isp) isp_prt(isp, ISP_LOGERR, sacq); return; } - isp_prt(isp, ISP_LOGDEBUG0, - "isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x", + isp_prt(isp, ISP_LOGDEBUG0, "isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x", icbp->icb_fwoptions, icbp->icb_xfwoptions, icbp->icb_zfwoptions); isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch); @@ -4435,7 +4428,7 @@ isp_start(XS_T *xs) */ return (dmaresult); } - isp_prt(isp, ISP_LOGDEBUG0, "START cmd for %d.%d.%d cmd 0x%x datalen %ld", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0], (long) XS_XFRLEN(xs)); + isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs)); isp->isp_nactive++; return (CMD_QUEUED); } @@ -5248,7 +5241,7 @@ again: } else { ptr = rnames[resp[FCP_RSPNS_CODE_OFFSET]]; } - isp_prt(isp, ISP_LOGWARN, "%d.%d.%d FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), rlen, ptr, XS_CDBP(xs)[0] & 0xff); + isp_xs_prt(isp, xs, ISP_LOGWARN, "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x", rlen, ptr, XS_CDBP(xs)[0] & 0xff); if (resp[FCP_RSPNS_CODE_OFFSET] != 0) { XS_SETERR(xs, HBA_BOTCH); } @@ -5325,25 +5318,9 @@ again: isp_destroy_handle(isp, sp->req_handle); if (((isp->isp_dblev & (ISP_LOGDEBUG1|ISP_LOGDEBUG2|ISP_LOGDEBUG3))) || - ((isp->isp_dblev & ISP_LOGDEBUG0) && ((!XS_NOERR(xs)) || - (*XS_STSP(xs) != SCSI_GOOD)))) { - char skey; - if (req_state_flags & RQSF_GOT_SENSE) { - skey = XS_SNSKEY(xs) & 0xf; - if (skey < 10) - skey += '0'; - else - skey += 'a' - 10; - } else if (*XS_STSP(xs) == SCSI_CHECK) { - skey = '?'; - } else { - skey = '.'; - } - isp_prt(isp, ISP_LOGALL, finmsg, XS_CHANNEL(xs), - XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs), (long) XS_GET_RESID(xs), - *XS_STSP(xs), skey, XS_ERR(xs)); + ((isp->isp_dblev & (ISP_LOGDEBUG0|ISP_LOG_CWARN) && ((!XS_NOERR(xs)) || (*XS_STSP(xs) != SCSI_GOOD))))) { + isp_prt_endcmd(isp, xs); } - if (isp->isp_nactive > 0) { isp->isp_nactive--; } @@ -5393,6 +5370,25 @@ out: * Support routines. */ +static void +isp_prt_endcmd(ispsoftc_t *isp, XS_T *xs) +{ + char cdbstr[16 * 5 + 1]; + int i, lim; + + lim = XS_CDBLEN(xs) > 16? 16 : XS_CDBLEN(xs); + ISP_SNPRINTF(cdbstr, sizeof (cdbstr), "0x%02x ", XS_CDBP(xs)[0]); + for (i = 1; i < lim; i++) { + ISP_SNPRINTF(cdbstr, sizeof (cdbstr), "%s0x%02x ", cdbstr, XS_CDBP(xs)[i]); + } + if (XS_SENSE_VALID(xs)) { + isp_xs_prt(isp, xs, ISP_LOGALL, "FIN dl%d resid %ld CDB=%s KEY/ASC/ASCQ=0x%02x/0x%02x/0x%02x", + XS_XFRLEN(xs), (long) XS_GET_RESID(xs), cdbstr, XS_SNSKEY(xs), XS_SNSASC(xs), XS_SNSASCQ(xs)); + } else { + isp_xs_prt(isp, xs, ISP_LOGALL, "FIN dl%d resid %ld CDB=%s STS 0x%x XS_ERR=0x%x", XS_XFRLEN(xs), (long) XS_GET_RESID(xs), cdbstr, *XS_STSP(xs), XS_ERR(xs)); + } +} + /* * Parse an ASYNC mailbox complete * @@ -5937,8 +5933,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox) */ static int -isp_handle_other_response(ispsoftc_t *isp, int type, - isphdr_t *hp, uint32_t *optrp) +isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *optrp) { switch (type) { case RQSTYPE_STATUS_CONT: @@ -6010,24 +6005,18 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) case RQCS_INCOMPLETE: if ((sp->req_state_flags & RQSF_GOT_TARGET) == 0) { - isp_prt(isp, ISP_LOGDEBUG1, - "Selection Timeout for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGDEBUG1, "Selection Timeout"); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_SELTIMEOUT); *rp = XS_XFRLEN(xs); } return; } - isp_prt(isp, ISP_LOGERR, - "command incomplete for %d.%d.%d, state 0x%x", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), - sp->req_state_flags); + isp_xs_prt(isp, xs, ISP_LOGERR, "Command Incomplete, state 0x%x", sp->req_state_flags); break; case RQCS_DMA_ERROR: - isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "DMA Error"); *rp = XS_XFRLEN(xs); break; @@ -6081,18 +6070,14 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) if (sp->req_status_flags & RQSTF_NEGOTIATION) { ISP_SNPRINTF(buf, sizeof (buf), "%s Negotiation", buf); } - isp_prt(isp, ISP_LOGERR, "%s", buf); - isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d:\n%s", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), buf); + isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error: %s", buf); *rp = XS_XFRLEN(xs); break; } case RQCS_RESET_OCCURRED: { int chan; - isp_prt(isp, ISP_LOGWARN, - "bus reset destroyed command for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGWARN, "Bus Reset destroyed command"); for (chan = 0; chan < isp->isp_nchan; chan++) { FCPARAM(isp, chan)->sendmarker = 1; } @@ -6103,8 +6088,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) return; } case RQCS_ABORTED: - isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted"); ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_ABORTED); @@ -6112,8 +6096,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) return; case RQCS_TIMEOUT: - isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGWARN, "Command timed out"); /* * XXX: Check to see if we logged out of the device. */ @@ -6124,83 +6107,62 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) case RQCS_DATA_OVERRUN: XS_SET_RESID(xs, sp->req_resid); - isp_prt(isp, ISP_LOGERR, "data overrun (%ld) for command on %d.%d.%d", - (long) XS_GET_RESID(xs), XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "data overrun (%ld)", (long) XS_GET_RESID(xs)); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_DATAOVR); } return; case RQCS_COMMAND_OVERRUN: - isp_prt(isp, ISP_LOGERR, - "command overrun for command on %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "command overrun"); break; case RQCS_STATUS_OVERRUN: - isp_prt(isp, ISP_LOGERR, - "status overrun for command on %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "status overrun"); break; case RQCS_BAD_MESSAGE: - isp_prt(isp, ISP_LOGERR, - "msg not COMMAND COMPLETE after status %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "msg not COMMAND COMPLETE after status"); break; case RQCS_NO_MESSAGE_OUT: - isp_prt(isp, ISP_LOGERR, - "No MESSAGE OUT phase after selection on %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "No MESSAGE OUT phase after selection"); break; case RQCS_EXT_ID_FAILED: - isp_prt(isp, ISP_LOGERR, "EXTENDED IDENTIFY failed %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "EXTENDED IDENTIFY failed"); break; case RQCS_IDE_MSG_FAILED: - isp_prt(isp, ISP_LOGERR, - "INITIATOR DETECTED ERROR rejected by %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "INITIATOR DETECTED ERROR rejected"); break; case RQCS_ABORT_MSG_FAILED: - isp_prt(isp, ISP_LOGERR, "ABORT OPERATION rejected by %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "ABORT OPERATION rejected"); break; case RQCS_REJECT_MSG_FAILED: - isp_prt(isp, ISP_LOGERR, "MESSAGE REJECT rejected by %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "MESSAGE REJECT rejected"); break; case RQCS_NOP_MSG_FAILED: - isp_prt(isp, ISP_LOGERR, "NOP rejected by %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "NOP rejected"); break; case RQCS_PARITY_ERROR_MSG_FAILED: - isp_prt(isp, ISP_LOGERR, - "MESSAGE PARITY ERROR rejected by %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "MESSAGE PARITY ERROR rejected"); break; case RQCS_DEVICE_RESET_MSG_FAILED: - isp_prt(isp, ISP_LOGWARN, - "BUS DEVICE RESET rejected by %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGWARN, "BUS DEVICE RESET rejected"); break; case RQCS_ID_MSG_FAILED: - isp_prt(isp, ISP_LOGERR, "IDENTIFY rejected by %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "IDENTIFY rejected"); break; case RQCS_UNEXP_BUS_FREE: - isp_prt(isp, ISP_LOGERR, "%d.%d.%d had an unexpected bus free", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "Unexpected Bus Free"); break; case RQCS_DATA_UNDERRUN: @@ -6208,9 +6170,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) if (IS_FC(isp)) { int ru_marked = (sp->req_scsi_status & RQCS_RU) != 0; if (!ru_marked || sp->req_resid > XS_XFRLEN(xs)) { - isp_prt(isp, ISP_LOGWARN, bun, XS_TGT(xs), - XS_LUN(xs), XS_XFRLEN(xs), sp->req_resid, - (ru_marked)? "marked" : "not marked"); + isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked"); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BOTCH); } @@ -6225,18 +6185,15 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) } case RQCS_XACT_ERR1: - isp_prt(isp, ISP_LOGERR, xact1, XS_CHANNEL(xs), - XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "HBA attempted queued transaction with disconnect not set"); break; case RQCS_XACT_ERR2: - isp_prt(isp, ISP_LOGERR, xact2, - XS_LUN(xs), XS_TGT(xs), XS_CHANNEL(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "HBA attempted queued transaction to target routine %d", XS_LUN(xs)); break; case RQCS_XACT_ERR3: - isp_prt(isp, ISP_LOGERR, xact3, - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "HBA attempted queued cmd when queueing disabled"); break; case RQCS_BAD_ENTRY: @@ -6244,9 +6201,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) break; case RQCS_QUEUE_FULL: - isp_prt(isp, ISP_LOGDEBUG0, - "internal queues full for %d.%d.%d status 0x%x", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), *XS_STSP(xs)); + isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "internal queues full status 0x%x", *XS_STSP(xs)); /* * If QFULL or some other status byte is set, then this @@ -6270,23 +6225,18 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) return; case RQCS_PHASE_SKIPPED: - isp_prt(isp, ISP_LOGERR, pskip, XS_CHANNEL(xs), - XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "SCSI phase skipped"); break; case RQCS_ARQS_FAILED: - isp_prt(isp, ISP_LOGERR, - "Auto Request Sense failed for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "Auto Request Sense Failed"); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_ARQFAIL); } return; case RQCS_WIDE_FAILED: - isp_prt(isp, ISP_LOGERR, - "Wide Negotiation failed for %d.%d.%d", - XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "Wide Negotiation Failed"); if (IS_SCSI(isp)) { sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs)); sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_WIDE; @@ -6299,9 +6249,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) return; case RQCS_SYNCXFER_FAILED: - isp_prt(isp, ISP_LOGERR, - "SDTR Message failed for target %d.%d.%d", - XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "SDTR Message Failed"); if (IS_SCSI(isp)) { sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs)); sdp += XS_CHANNEL(xs); @@ -6312,9 +6260,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) break; case RQCS_LVD_BUSERR: - isp_prt(isp, ISP_LOGERR, - "Bad LVD condition while talking to %d.%d.%d", - XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "Bad LVD condition"); break; case RQCS_PORT_UNAVAILABLE: @@ -6384,8 +6330,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) } static void -isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, - XS_T *xs, long *rp) +isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs, long *rp) { int ru_marked, sv_marked; int chan = XS_CHANNEL(xs); @@ -6398,19 +6343,15 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, return; case RQCS_DMA_ERROR: - isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error"); break; case RQCS_TRANSPORT_ERROR: - isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error"); break; case RQCS_RESET_OCCURRED: - isp_prt(isp, ISP_LOGWARN, - "reset destroyed command for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command"); FCPARAM(isp, chan)->sendmarker = 1; if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BUSRESET); @@ -6418,8 +6359,7 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, return; case RQCS_ABORTED: - isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted"); FCPARAM(isp, chan)->sendmarker = 1; if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_ABORTED); @@ -6427,8 +6367,7 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, return; case RQCS_TIMEOUT: - isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out"); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_CMDTIMEOUT); } @@ -6436,9 +6375,7 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, case RQCS_DATA_OVERRUN: XS_SET_RESID(xs, sp->req_resid); - isp_prt(isp, ISP_LOGERR, - "data overrun for command on %d.%d.%d", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun"); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_DATAOVR); } @@ -6471,19 +6408,14 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0; if ((ru_marked == 0 && sv_marked == 0) || (sp->req_resid > XS_XFRLEN(xs))) { - isp_prt(isp, ISP_LOGWARN, bun, XS_TGT(xs), - XS_LUN(xs), XS_XFRLEN(xs), sp->req_resid, - (ru_marked)? "marked" : "not marked"); + isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked"); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BOTCH); } return; } XS_SET_RESID(xs, sp->req_resid); - isp_prt(isp, ISP_LOGDEBUG0, - "%d.%d.%d data underrun (%d) for command 0x%x", - XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), - sp->req_resid, XS_CDBP(xs)[0] & 0xff); + isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_NOERROR); } @@ -7384,8 +7316,7 @@ isp_spi_update(ispsoftc_t *isp, int chan) if (sdp->isp_devparam[tgt].dev_enable == 0) { sdp->isp_devparam[tgt].dev_update = 0; sdp->isp_devparam[tgt].dev_refresh = 0; - isp_prt(isp, ISP_LOGDEBUG0, - "skipping target %d bus %d update", tgt, chan); + isp_prt(isp, ISP_LOGDEBUG0, "skipping target %d bus %d update", tgt, chan); continue; } /* @@ -7441,10 +7372,8 @@ isp_spi_update(ispsoftc_t *isp, int chan) sdp->isp_devparam[tgt].actv_flags &= ~DPARM_TQING; sdp->isp_devparam[tgt].actv_flags |= (sdp->isp_devparam[tgt].goal_flags & DPARM_TQING); - isp_prt(isp, ISP_LOGDEBUG0, - "bus %d set tgt %d flags 0x%x off 0x%x period 0x%x", - chan, tgt, mbs.param[2], mbs.param[3] >> 8, - mbs.param[3] & 0xff); + isp_prt(isp, ISP_LOGDEBUG0, "bus %d set tgt %d flags 0x%x off 0x%x period 0x%x", + chan, tgt, mbs.param[2], mbs.param[3] >> 8, mbs.param[3] & 0xff); get = 0; } else { continue; @@ -7778,8 +7707,7 @@ isp_read_nvram(ispsoftc_t *isp, int bus) nvram_data[2] != 'P') { if (isp->isp_bustype != ISP_BT_SBUS) { isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header"); - isp_prt(isp, ISP_LOGDEBUG0, "%x %x %x", - nvram_data[0], nvram_data[1], nvram_data[2]); + isp_prt(isp, ISP_LOGDEBUG0, "%x %x %x", nvram_data[0], nvram_data[1], nvram_data[2]); } retval = -1; goto out; @@ -8294,8 +8222,7 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data) ISP2100_NVRAM_TOV(nvram_data)); fcp->isp_xfwoptions = ISP2100_XFW_OPTIONS(nvram_data); fcp->isp_zfwoptions = ISP2100_ZFW_OPTIONS(nvram_data); - isp_prt(isp, ISP_LOGDEBUG0, - "xfwoptions 0x%x zfw options 0x%x", + isp_prt(isp, ISP_LOGDEBUG0, "xfwoptions 0x%x zfw options 0x%x", ISP2100_XFW_OPTIONS(nvram_data), ISP2100_ZFW_OPTIONS(nvram_data)); } diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index ca459f36564..5f64bcd176c 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -5432,6 +5432,20 @@ isp_prt(ispsoftc_t *isp, int level, const char *fmt, ...) printf("\n"); } +void +isp_xs_prt(ispsoftc_t *isp, XS_T *xs, int level, const char *fmt, ...) +{ + va_list ap; + if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) { + return; + } + xpt_print_path(xs->ccb_h.path); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); +} + uint64_t isp_nanotime_sub(struct timespec *b, struct timespec *a) { diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index dea6266b71d..44c8bdf1ca5 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -424,6 +424,8 @@ default: \ imin((sizeof((ccb)->sense_data)), ccb->sense_len) #define XS_SNSKEY(ccb) ((ccb)->sense_data.flags & 0xf) +#define XS_SNSASC(ccb) ((ccb)->sense_data.add_sense_code) +#define XS_SNSASCQ(ccb) ((ccb)->sense_data.add_sense_code_qual) #define XS_TAG_P(ccb) \ (((ccb)->ccb_h.flags & CAM_TAG_ACTION_VALID) && \ (ccb)->tag_action != CAM_TAG_ACTION_NONE) @@ -461,7 +463,7 @@ default: \ (xs)->ccb_h.status |= CAM_AUTOSNS_VALID; \ memcpy(&(xs)->sense_data, sense_ptr, imin(XS_SNSLEN(xs), sense_len)) -#define XS_SET_STATE_STAT(a, b, c) +#define XS_SENSE_VALID(xs) (((xs)->ccb_h.status & CAM_AUTOSNS_VALID) != 0) #define DEFAULT_FRAMESIZE(isp) isp->isp_osinfo.framesize #define DEFAULT_EXEC_THROTTLE(isp) isp->isp_osinfo.exec_throttle @@ -593,6 +595,7 @@ extern int isp_autoconfig; * Platform Library Functions */ void isp_prt(ispsoftc_t *, int level, const char *, ...) __printflike(3, 4); +void isp_xs_prt(ispsoftc_t *, XS_T *, int level, const char *, ...) __printflike(4, 5); uint64_t isp_nanotime_sub(struct timespec *, struct timespec *); int isp_mbox_acquire(ispsoftc_t *); void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *); diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index 43c161d2782..020193394d9 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -294,10 +294,10 @@ uint32_t isp_handle_index(ispsoftc_t *isp, uint32_t handle) { if (!ISP_VALID_HANDLE(isp, handle)) { - return (handle & ISP_HANDLE_CMD_MASK); - } else { isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle); return (ISP_BAD_HANDLE_INDEX); + } else { + return (handle & ISP_HANDLE_CMD_MASK); } } diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 5c8508c87c4..e4bf8698670 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -954,12 +954,13 @@ void isp_async(ispsoftc_t *, ispasync_t, ...); /* * Platform Dependent Error and Debug Printout * - * Generally this is: + * Two required functions for each platform must be provided: * * void isp_prt(ispsoftc_t *, int level, const char *, ...) + * void isp_xs_prt(ispsoftc_t *, XS_T *, int level, const char *, ...) * * but due to compiler differences on different platforms this won't be - * formally done here. Instead, it goes in each platform definition file. + * formally defined here. Instead, they go in each platform definition file. */ #define ISP_LOGALL 0x0 /* log always */ @@ -972,6 +973,7 @@ void isp_async(ispsoftc_t *, ispasync_t, ...); #define ISP_LOGDEBUG2 0x40 /* log most debug messages */ #define ISP_LOGDEBUG3 0x80 /* log high frequency debug messages */ #define ISP_LOGSANCFG 0x100 /* log SAN configuration */ +#define ISP_LOG_CWARN 0x200 /* log SCSI command "warnings" (e.g., check conditions) */ #define ISP_LOGTINFO 0x1000 /* log informational messages (target mode) */ #define ISP_LOGTDEBUG0 0x2000 /* log simple debug messages (target mode) */ #define ISP_LOGTDEBUG1 0x4000 /* log intermediate debug messages (target) */ @@ -1045,6 +1047,8 @@ void isp_async(ispsoftc_t *, ispasync_t, ...); * XS_SNSP(xs) gets a pointer to the associate sense data * XS_SNSLEN(xs) gets the length of sense data storage * XS_SNSKEY(xs) dereferences XS_SNSP to get the current stored Sense Key + * XS_SNSASC(xs) dereferences XS_SNSP to get the current stored Additional Sense Code + * XS_SNSASCQ(xs) dereferences XS_SNSP to get the current stored Additional Sense Code Qualifier * XS_TAG_P(xs) predicate of whether this command should be tagged * XS_TAG_TYPE(xs) which type of tag to use * XS_SETERR(xs) set error state @@ -1065,6 +1069,8 @@ void isp_async(ispsoftc_t *, ispasync_t, ...); * * XS_SAVE_SENSE(xs, sp, len) save sense data * + * XS_SENSE_VALID(xs) indicates whether sense is valid + * * DEFAULT_FRAMESIZE(ispsoftc_t *) Default Frame Size * DEFAULT_EXEC_THROTTLE(ispsoftc_t *) Default Execution Throttle * diff --git a/sys/dev/ixgbe/LICENSE b/sys/dev/ixgbe/LICENSE index 39264e087be..0cf44c8581e 100644 --- a/sys/dev/ixgbe/LICENSE +++ b/sys/dev/ixgbe/LICENSE @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c index f66443ae77f..2c303d95ade 100644 --- a/sys/dev/ixgbe/ixgbe.c +++ b/sys/dev/ixgbe/ixgbe.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -46,7 +46,7 @@ int ixgbe_display_debug_stats = 0; /********************************************************************* * Driver version *********************************************************************/ -char ixgbe_driver_version[] = "2.0.7"; +char ixgbe_driver_version[] = "2.1.6"; /********************************************************************* * PCI Device ID Table @@ -76,6 +76,7 @@ static ixgbe_vendor_info_t ixgbe_vendor_info_array[] = {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0}, /* required last entry */ {0, 0, 0, 0, 0} @@ -136,12 +137,11 @@ static void ixgbe_free_receive_structures(struct adapter *); static void ixgbe_free_receive_buffers(struct rx_ring *); static void ixgbe_setup_hw_rsc(struct rx_ring *); -static void ixgbe_init_moderation(struct adapter *); static void ixgbe_enable_intr(struct adapter *); static void ixgbe_disable_intr(struct adapter *); static void ixgbe_update_stats_counters(struct adapter *); static bool ixgbe_txeof(struct tx_ring *); -static bool ixgbe_rxeof(struct rx_ring *, int); +static bool ixgbe_rxeof(struct ix_queue *, int); static void ixgbe_rx_checksum(u32, struct mbuf *); static void ixgbe_set_promisc(struct adapter *); static void ixgbe_disable_promisc(struct adapter *); @@ -149,7 +149,7 @@ static void ixgbe_set_multi(struct adapter *); static void ixgbe_print_hw_stats(struct adapter *); static void ixgbe_print_debug_info(struct adapter *); static void ixgbe_update_link_status(struct adapter *); -static int ixgbe_get_buf(struct rx_ring *, int, int); +static void ixgbe_refresh_mbufs(struct rx_ring *, int); static int ixgbe_xmit(struct tx_ring *, struct mbuf **); static int ixgbe_sysctl_stats(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS); @@ -169,7 +169,9 @@ static void ixgbe_setup_vlan_hw_support(struct adapter *); static void ixgbe_register_vlan(void *, struct ifnet *, u16); static void ixgbe_unregister_vlan(void *, struct ifnet *, u16); -static void ixgbe_update_aim(struct rx_ring *); +static __inline void ixgbe_rx_discard(struct rx_ring *, int); +static __inline void ixgbe_rx_input(struct rx_ring *, struct ifnet *, + struct mbuf *, u32); /* Support for pluggable optic modules */ static bool ixgbe_sfp_probe(struct adapter *); @@ -178,13 +180,11 @@ static bool ixgbe_sfp_probe(struct adapter *); static void ixgbe_legacy_irq(void *); /* The MSI/X Interrupt handlers */ -static void ixgbe_msix_tx(void *); -static void ixgbe_msix_rx(void *); +static void ixgbe_msix_que(void *); static void ixgbe_msix_link(void *); /* Deferred interrupt tasklets */ -static void ixgbe_handle_tx(void *, int); -static void ixgbe_handle_rx(void *, int); +static void ixgbe_handle_que(void *, int); static void ixgbe_handle_link(void *, int); static void ixgbe_handle_msf(void *, int); static void ixgbe_handle_mod(void *, int); @@ -222,23 +222,16 @@ MODULE_DEPEND(ixgbe, ether, 1, 1, 1); */ /* -** These parameters are used in Adaptive -** Interrupt Moderation. The value is set -** into EITR and controls the interrupt -** frequency. They can be modified but -** be careful in tuning them. +** AIM: Adaptive Interrupt Moderation +** which means that the interrupt rate +** is varied over time based on the +** traffic for that interrupt vector */ static int ixgbe_enable_aim = TRUE; TUNABLE_INT("hw.ixgbe.enable_aim", &ixgbe_enable_aim); -static int ixgbe_low_latency = IXGBE_LOW_LATENCY; -TUNABLE_INT("hw.ixgbe.low_latency", &ixgbe_low_latency); -static int ixgbe_ave_latency = IXGBE_AVE_LATENCY; -TUNABLE_INT("hw.ixgbe.ave_latency", &ixgbe_ave_latency); -static int ixgbe_bulk_latency = IXGBE_BULK_LATENCY; -TUNABLE_INT("hw.ixgbe.bulk_latency", &ixgbe_bulk_latency); /* How many packets rxeof tries to clean at a time */ -static int ixgbe_rx_process_limit = 100; +static int ixgbe_rx_process_limit = 128; TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit); /* Flow control setting, default to full */ @@ -271,20 +264,24 @@ static bool ixgbe_header_split = TRUE; TUNABLE_INT("hw.ixgbe.hdr_split", &ixgbe_header_split); /* - * Number of Queues, should normally - * be left at 0, it then autoconfigures to - * the number of cpus. Each queue is a pair - * of RX and TX rings with a dedicated interrupt + * Number of Queues, can be set to 0, + * it then autoconfigures based on the + * number of cpus. Each queue is a pair + * of RX and TX rings with a msix vector */ static int ixgbe_num_queues = 0; TUNABLE_INT("hw.ixgbe.num_queues", &ixgbe_num_queues); -/* Number of TX descriptors per ring */ -static int ixgbe_txd = DEFAULT_TXD; +/* +** Number of TX descriptors per ring, +** setting higher than RX as this seems +** the better performing choice. +*/ +static int ixgbe_txd = PERFORM_TXD; TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd); /* Number of RX descriptors per ring */ -static int ixgbe_rxd = DEFAULT_RXD; +static int ixgbe_rxd = PERFORM_RXD; TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd); /* Keep running tab on them for sanity check */ @@ -420,9 +417,11 @@ ixgbe_attach(device_t dev) case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM : case IXGBE_DEV_ID_82598EB_SFP_LOM : case IXGBE_DEV_ID_82598AT : - case IXGBE_DEV_ID_82598AT2 : adapter->optics = IFM_10G_SR; break; + case IXGBE_DEV_ID_82598AT2 : + adapter->optics = IFM_10G_T; + break; case IXGBE_DEV_ID_82598EB_XF_LR : adapter->optics = IFM_10G_LR; break; @@ -439,6 +438,10 @@ ixgbe_attach(device_t dev) case IXGBE_DEV_ID_82599_XAUI_LOM : case IXGBE_DEV_ID_82599_COMBO_BACKPLANE : ixgbe_num_segs = IXGBE_82599_SCATTER; + break; + case IXGBE_DEV_ID_82599_T3_LOM: + ixgbe_num_segs = IXGBE_82599_SCATTER; + adapter->optics = IFM_10G_T; default: break; } @@ -464,21 +467,6 @@ ixgbe_attach(device_t dev) OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW, &ixgbe_enable_aim, 1, "Interrupt Moderation"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "low_latency", CTLTYPE_INT|CTLFLAG_RW, - &ixgbe_low_latency, 1, "Low Latency"); - - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "ave_latency", CTLTYPE_INT|CTLFLAG_RW, - &ixgbe_ave_latency, 1, "Average Latency"); - - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "bulk_latency", CTLTYPE_INT|CTLFLAG_RW, - &ixgbe_bulk_latency, 1, "Bulk Latency"); - /* Set up the timer callout */ callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); @@ -592,22 +580,6 @@ ixgbe_attach(device_t dev) /* Setup OS specific network interface */ ixgbe_setup_interface(dev, adapter); -#ifdef IXGBE_IEEE1588 - /* - ** Setup the timer: IEEE 1588 support - */ - adapter->cycles.read = ixgbe_read_clock; - adapter->cycles.mask = (u64)-1; - adapter->cycles.mult = 1; - adapter->cycles.shift = IXGBE_TSYNC_SHIFT; - IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, (1<<24) | - IXGBE_TSYNC_CYCLE_TIME * IXGBE_TSYNC_SHIFT); - IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000); - IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0xFF800000); - - // JFV - this is not complete yet -#endif - /* Sysctl for limiting the amount of work done in the taskqueue */ ixgbe_add_rx_process_limit(adapter, "rx_processing_limit", "max number of rx packets to process", &adapter->rx_process_limit, @@ -632,12 +604,13 @@ ixgbe_attach(device_t dev) (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" : ("Unknown")); - if (hw->bus.width <= ixgbe_bus_width_pcie_x4) { + if ((hw->bus.width <= ixgbe_bus_width_pcie_x4) && + (hw->bus.speed == ixgbe_bus_speed_2500)) { device_printf(dev, "PCI-Express bandwidth available" " for this card\n is not sufficient for" " optimal performance.\n"); device_printf(dev, "For optimal performance a x8 " - "PCI-Express slot is required.\n"); + "PCIE, or x4 PCIE 2 slot is required.\n"); } /* let hardware know driver is loaded */ @@ -670,8 +643,7 @@ static int ixgbe_detach(device_t dev) { struct adapter *adapter = device_get_softc(dev); - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct ix_queue *que = adapter->queues; u32 ctrl_ext; INIT_DEBUGOUT("ixgbe_detach: begin"); @@ -686,17 +658,10 @@ ixgbe_detach(device_t dev) ixgbe_stop(adapter); IXGBE_CORE_UNLOCK(adapter); - for (int i = 0; i < adapter->num_queues; i++, txr++) { - if (txr->tq) { - taskqueue_drain(txr->tq, &txr->tx_task); - taskqueue_free(txr->tq); - } - } - - for (int i = 0; i < adapter->num_queues; i++, rxr++) { - if (rxr->tq) { - taskqueue_drain(rxr->tq, &rxr->rx_task); - taskqueue_free(rxr->tq); + for (int i = 0; i < adapter->num_queues; i++, que++) { + if (que->tq) { + taskqueue_drain(que->tq, &que->que_task); + taskqueue_free(que->tq); } } @@ -833,6 +798,9 @@ ixgbe_mq_start(struct ifnet *ifp, struct mbuf *m) /* Which queue to use */ if ((m->m_flags & M_FLOWID) != 0) i = m->m_pkthdr.flowid % adapter->num_queues; + else /* use the cpu we're on */ + i = curcpu % adapter->num_queues; + txr = &adapter->tx_rings[i]; if (IXGBE_TX_TRYLOCK(txr)) { @@ -849,59 +817,43 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) { struct adapter *adapter = txr->adapter; struct mbuf *next; - int err = 0; + int enqueued, err = 0; - if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) || - (!adapter->link_active)) { - err = drbr_enqueue(ifp, txr->br, m); + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING || adapter->link_active == 0) { + if (m != NULL) + err = drbr_enqueue(ifp, txr->br, m); return (err); } - if (m == NULL) /* Called by tasklet */ - goto process; - - /* If nothing queued go right to xmit */ - if (!drbr_needs_enqueue(ifp, txr->br)) { - if ((err = ixgbe_xmit(txr, &m)) != 0) { - if (m != NULL) - err = drbr_enqueue(ifp, txr->br, m); - return (err); - } else { - /* Success, update stats */ - drbr_stats_update(ifp, m->m_pkthdr.len, m->m_flags); - /* Send a copy of the frame to the BPF listener */ - ETHER_BPF_MTAP(ifp, m); - /* Set the watchdog */ - txr->watchdog_check = TRUE; - } - - } else if ((err = drbr_enqueue(ifp, txr->br, m)) != 0) - return (err); - -process: - if (drbr_empty(ifp, txr->br)) - return (err); + enqueued = 0; + if (m == NULL) + next = drbr_dequeue(ifp, txr->br); + else + next = m; /* Process the queue */ - while (TRUE) { - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - break; - next = drbr_dequeue(ifp, txr->br); - if (next == NULL) - break; + while (next != NULL) { if ((err = ixgbe_xmit(txr, &next)) != 0) { if (next != NULL) err = drbr_enqueue(ifp, txr->br, next); break; } + enqueued++; drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags); + /* Send a copy of the frame to the BPF listener */ ETHER_BPF_MTAP(ifp, next); - /* Set the watchdog */ - txr->watchdog_check = TRUE; + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + break; + if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + break; + } + next = drbr_dequeue(ifp, txr->br); } - - if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + + if (enqueued > 0) + txr->watchdog_check = TRUE; return (err); } @@ -938,8 +890,8 @@ ixgbe_qflush(struct ifnet *ifp) static int ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) { - struct adapter *adapter = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *) data; + struct adapter *adapter = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *) data; int error = 0; switch (command) { @@ -999,8 +951,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) ifp->if_capenable ^= IFCAP_HWCSUM; if (mask & IFCAP_TSO4) ifp->if_capenable ^= IFCAP_TSO4; - /* Only allow changing when using header split */ - if ((mask & IFCAP_LRO) && (ixgbe_header_split)) + if (mask & IFCAP_LRO) ifp->if_capenable ^= IFCAP_LRO; if (mask & IFCAP_VLAN_HWTAGGING) ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; @@ -1010,15 +961,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) break; } -#ifdef IXGBE_IEEE1588 - /* - ** IOCTL support for Precision Time (IEEE 1588) Support - */ - case SIOCSHWTSTAMP: - error = ixgbe_hwtstamp_ioctl(adapter, ifp); - break; -#endif - default: IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command); error = ether_ioctl(ifp, command, data); @@ -1045,15 +987,20 @@ ixgbe_init_locked(struct adapter *adapter) { struct ifnet *ifp = adapter->ifp; device_t dev = adapter->dev; - struct ixgbe_hw *hw; + struct ixgbe_hw *hw = &adapter->hw; u32 k, txdctl, mhadd, gpie; u32 rxdctl, rxctrl; int err; - INIT_DEBUGOUT("ixgbe_init: begin"); - - hw = &adapter->hw; mtx_assert(&adapter->core_mtx, MA_OWNED); + INIT_DEBUGOUT("ixgbe_init: begin"); + ixgbe_reset_hw(hw); + hw->adapter_stopped = FALSE; + ixgbe_stop_adapter(hw); + callout_stop(&adapter->timer); + + /* reprogram the RAR[0] in case user changed it. */ + ixgbe_set_rar(hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); /* Get the latest mac address, User can use a LAA */ bcopy(IF_LLADDR(adapter->ifp), hw->mac.addr, @@ -1061,9 +1008,6 @@ ixgbe_init_locked(struct adapter *adapter) ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1); hw->addr_ctrl.rar_used_count = 1; - /* Do a warm reset */ - ixgbe_reset_hw(hw); - /* Prepare transmit descriptors and buffers */ if (ixgbe_setup_transmit_structures(adapter)) { device_printf(dev,"Could not setup transmit structures\n"); @@ -1071,6 +1015,7 @@ ixgbe_init_locked(struct adapter *adapter) return; } + ixgbe_init_hw(hw); ixgbe_initialize_transmit_units(adapter); /* Setup Multicast table */ @@ -1095,9 +1040,6 @@ ixgbe_init_locked(struct adapter *adapter) /* Configure RX settings */ ixgbe_initialize_receive_units(adapter); - /* Configure Interrupt Moderation */ - ixgbe_init_moderation(adapter); - gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE); if (hw->mac.type == ixgbe_mac_82599EB) { @@ -1174,7 +1116,7 @@ ixgbe_init_locked(struct adapter *adapter) if (hw->mac.type == ixgbe_mac_82598EB) rxctrl |= IXGBE_RXCTRL_DMBYPS; rxctrl |= IXGBE_RXCTRL_RXEN; - IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); + ixgbe_enable_rx_dma(hw, rxctrl); callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); @@ -1291,34 +1233,22 @@ ixgbe_rearm_queues(struct adapter *adapter, u64 queues) } } -static void -ixgbe_handle_rx(void *context, int pending) -{ - struct rx_ring *rxr = context; - struct adapter *adapter = rxr->adapter; - u32 loop = MAX_LOOP; - bool more; - - do { - more = ixgbe_rxeof(rxr, -1); - } while (loop-- && more); - /* Reenable this interrupt */ - ixgbe_enable_queue(adapter, rxr->msix); -} static void -ixgbe_handle_tx(void *context, int pending) +ixgbe_handle_que(void *context, int pending) { - struct tx_ring *txr = context; - struct adapter *adapter = txr->adapter; + struct ix_queue *que = context; + struct adapter *adapter = que->adapter; + struct tx_ring *txr = que->txr; struct ifnet *ifp = adapter->ifp; u32 loop = MAX_LOOP; - bool more; + bool more_rx, more_tx; IXGBE_TX_LOCK(txr); do { - more = ixgbe_txeof(txr); - } while (loop-- && more); + more_rx = ixgbe_rxeof(que, adapter->rx_process_limit); + more_tx = ixgbe_txeof(txr); + } while (loop-- && (more_rx || more_tx)); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { #if __FreeBSD_version >= 800000 @@ -1332,7 +1262,7 @@ ixgbe_handle_tx(void *context, int pending) IXGBE_TX_UNLOCK(txr); /* Reenable this interrupt */ - ixgbe_enable_queue(adapter, txr->msix); + ixgbe_enable_queue(adapter, que->msix); } @@ -1345,33 +1275,32 @@ ixgbe_handle_tx(void *context, int pending) static void ixgbe_legacy_irq(void *arg) { - struct adapter *adapter = arg; + struct ix_queue *que = arg; + struct adapter *adapter = que->adapter; struct ixgbe_hw *hw = &adapter->hw; struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; - bool more; + bool more_tx, more_rx; u32 reg_eicr, loop = MAX_LOOP; reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR); + ++que->irqs; if (reg_eicr == 0) { ixgbe_enable_intr(adapter); return; } - if (ixgbe_rxeof(rxr, adapter->rx_process_limit)) - taskqueue_enqueue(rxr->tq, &rxr->rx_task); + more_rx = ixgbe_rxeof(que, adapter->rx_process_limit); IXGBE_TX_LOCK(txr); - ++txr->tx_irq; do { - more = ixgbe_txeof(txr); - } while (loop-- && more); + more_tx = ixgbe_txeof(txr); + } while (loop-- && more_tx); IXGBE_TX_UNLOCK(txr); - if (more) - taskqueue_enqueue(txr->tq, &txr->tx_task); + if (more_rx || more_tx) + taskqueue_enqueue(que->tq, &que->que_task); /* Check for fan failure */ if ((hw->phy.media_type == ixgbe_media_type_copper) && @@ -1382,15 +1311,8 @@ ixgbe_legacy_irq(void *arg) } /* Link status change */ - if (reg_eicr & IXGBE_EICR_LSC) { - ixgbe_check_link(&adapter->hw, - &adapter->link_speed, &adapter->link_up, 0); - ixgbe_update_link_status(adapter); - } - - /* Update interrupt rate */ - if (ixgbe_enable_aim == TRUE) - ixgbe_update_aim(rxr); + if (reg_eicr & IXGBE_EICR_LSC) + taskqueue_enqueue(adapter->tq, &adapter->link_task); ixgbe_enable_intr(adapter); return; @@ -1399,55 +1321,85 @@ ixgbe_legacy_irq(void *arg) /********************************************************************* * - * MSI TX Interrupt Service routine + * MSI Queue Interrupt Service routine * **********************************************************************/ void -ixgbe_msix_tx(void *arg) +ixgbe_msix_que(void *arg) { - struct tx_ring *txr = arg; - struct adapter *adapter = txr->adapter; - bool more; + struct ix_queue *que = arg; + struct adapter *adapter = que->adapter; + struct tx_ring *txr = que->txr; + struct rx_ring *rxr = que->rxr; + bool more_tx, more_rx; + u32 newitr = 0; - ixgbe_disable_queue(adapter, txr->msix); + ixgbe_disable_queue(adapter, que->msix); + ++que->irqs; + + more_rx = ixgbe_rxeof(que, adapter->rx_process_limit); IXGBE_TX_LOCK(txr); - ++txr->tx_irq; - more = ixgbe_txeof(txr); + more_tx = ixgbe_txeof(txr); IXGBE_TX_UNLOCK(txr); - if (more) - taskqueue_enqueue(txr->tq, &txr->tx_task); - else /* Reenable this interrupt */ - ixgbe_enable_queue(adapter, txr->msix); - return; -} + more_rx = ixgbe_rxeof(que, adapter->rx_process_limit); -/********************************************************************* - * - * MSIX RX Interrupt Service routine - * - **********************************************************************/ -static void -ixgbe_msix_rx(void *arg) -{ - struct rx_ring *rxr = arg; - struct adapter *adapter = rxr->adapter; - bool more; + /* Do AIM now? */ - ixgbe_disable_queue(adapter, rxr->msix); + if (ixgbe_enable_aim == FALSE) + goto no_calc; + /* + ** Do Adaptive Interrupt Moderation: + ** - Write out last calculated setting + ** - Calculate based on average size over + ** the last interval. + */ + if (que->eitr_setting) + IXGBE_WRITE_REG(&adapter->hw, + IXGBE_EITR(que->msix), que->eitr_setting); + + que->eitr_setting = 0; - ++rxr->rx_irq; - more = ixgbe_rxeof(rxr, adapter->rx_process_limit); + /* Idle, do nothing */ + if ((txr->bytes == 0) && (rxr->bytes == 0)) + goto no_calc; + + if ((txr->bytes) && (txr->packets)) + newitr = txr->bytes/txr->packets; + if ((rxr->bytes) && (rxr->packets)) + newitr = max(newitr, + (rxr->bytes / rxr->packets)); + newitr += 24; /* account for hardware frame, crc */ - /* Update interrupt rate */ - if (ixgbe_enable_aim == TRUE) - ixgbe_update_aim(rxr); + /* set an upper boundary */ + newitr = min(newitr, 3000); - if (more) - taskqueue_enqueue(rxr->tq, &rxr->rx_task); + /* Be nice to the mid range */ + if ((newitr > 300) && (newitr < 1200)) + newitr = (newitr / 3); else - ixgbe_enable_queue(adapter, rxr->msix); + newitr = (newitr / 2); + + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + newitr |= newitr << 16; + else + newitr |= IXGBE_EITR_CNT_WDIS; + + /* save for next interrupt */ + que->eitr_setting = newitr; + + /* Reset state */ + txr->bytes = 0; + txr->packets = 0; + rxr->bytes = 0; + rxr->packets = 0; + +no_calc: + if (more_tx || more_rx) + taskqueue_enqueue(que->tq, &que->que_task); + else /* Reenable this interrupt */ + ixgbe_enable_queue(adapter, que->msix); return; } @@ -1512,84 +1464,6 @@ ixgbe_msix_link(void *arg) return; } -/* -** Routine to do adjust the RX EITR value based on traffic, -** its a simple three state model, but seems to help. -** -** Note that the three EITR values are tuneable using -** sysctl in real time. The feature can be effectively -** nullified by setting them equal. -*/ -#define BULK_THRESHOLD 10000 -#define AVE_THRESHOLD 1600 - -static void -ixgbe_update_aim(struct rx_ring *rxr) -{ - struct adapter *adapter = rxr->adapter; - u32 olditr, newitr; - - /* Update interrupt moderation based on traffic */ - olditr = rxr->eitr_setting; - newitr = olditr; - - /* Idle, don't change setting */ - if (rxr->bytes == 0) - return; - - if (olditr == ixgbe_low_latency) { - if (rxr->bytes > AVE_THRESHOLD) - newitr = ixgbe_ave_latency; - } else if (olditr == ixgbe_ave_latency) { - if (rxr->bytes < AVE_THRESHOLD) - newitr = ixgbe_low_latency; - else if (rxr->bytes > BULK_THRESHOLD) - newitr = ixgbe_bulk_latency; - } else if (olditr == ixgbe_bulk_latency) { - if (rxr->bytes < BULK_THRESHOLD) - newitr = ixgbe_ave_latency; - } - - if (olditr != newitr) { - /* Change interrupt rate */ - rxr->eitr_setting = newitr; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(rxr->me), - newitr | (newitr << 16)); - } - - rxr->bytes = 0; - return; -} - -static void -ixgbe_init_moderation(struct adapter *adapter) -{ - struct rx_ring *rxr = adapter->rx_rings; - struct tx_ring *txr = adapter->tx_rings; - - /* Single interrupt - MSI or Legacy? */ - if (adapter->msix < 2) { - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(0), 100); - return; - } - - /* TX irq moderation rate is fixed */ - for (int i = 0; i < adapter->num_queues; i++, txr++) - IXGBE_WRITE_REG(&adapter->hw, - IXGBE_EITR(txr->msix), ixgbe_ave_latency); - - /* RX moderation will be adapted over time, set default */ - for (int i = 0; i < adapter->num_queues; i++, rxr++) { - IXGBE_WRITE_REG(&adapter->hw, - IXGBE_EITR(rxr->msix), ixgbe_low_latency); - } - - /* Set Link moderation */ - IXGBE_WRITE_REG(&adapter->hw, - IXGBE_EITR(adapter->linkvec), IXGBE_LINK_ITR); - -} - /********************************************************************* * * Media Ioctl callback @@ -1665,11 +1539,10 @@ ixgbe_media_change(struct ifnet * ifp) /********************************************************************* * - * This routine maps the mbufs to tx descriptors. - * WARNING: while this code is using an MQ style infrastructure, - * it would NOT work as is with more than 1 queue. + * This routine maps the mbufs to tx descriptors, allowing the + * TX engine to transmit the packets. + * - return 0 on success, positive on failure * - * return 0 on success, positive on failure **********************************************************************/ static int @@ -1695,14 +1568,6 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp) if (m_head->m_flags & M_VLANTAG) cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE; - /* Do a clean if descriptors are low */ - if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) { - ixgbe_txeof(txr); - /* Now do we at least have a minimal? */ - if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) - return (ENOBUFS); - } - /* * Important to capture the first descriptor * used because it will contain the index of @@ -1756,7 +1621,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp) /* Make certain there are enough descriptors */ if (nsegs > txr->tx_avail - 2) { - txr->no_tx_desc_avail++; + txr->no_desc_avail++; error = ENOBUFS; goto xmit_fail; } @@ -1814,7 +1679,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp) txd->read.cmd_type_len = htole32(txr->txd_cmd | cmd_type_len |seglen); txd->read.olinfo_status = htole32(olinfo_status); - last = i; /* Next descriptor that will get completed */ + last = i; /* descriptor that will get completion IRQ */ if (++i == adapter->num_tx_desc) i = 0; @@ -1843,7 +1708,13 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp) * hardware that this frame is available to transmit. */ ++txr->total_packets; + txr->watchdog_time = ticks; IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(txr->me), i); + + /* Do a clean if descriptors are low */ + if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) + ixgbe_txeof(txr); + return (0); xmit_fail: @@ -1978,7 +1849,6 @@ ixgbe_local_timer(void *arg) struct ifnet *ifp = adapter->ifp; device_t dev = adapter->dev; struct tx_ring *txr = adapter->tx_rings; - bool tx_hung = FALSE; mtx_assert(&adapter->core_mtx, MA_OWNED); @@ -1989,21 +1859,32 @@ ixgbe_local_timer(void *arg) ixgbe_update_link_status(adapter); ixgbe_update_stats_counters(adapter); - if (ixgbe_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) { + + /* Debug display */ + if (ixgbe_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) ixgbe_print_hw_stats(adapter); - } + + /* + * If the interface has been paused + * then don't do the watchdog check + */ + if (IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) + goto out; /* ** Check for time since any descriptor was cleaned */ for (int i = 0; i < adapter->num_queues; i++, txr++) { - if (txr->watchdog_check == FALSE) + IXGBE_TX_LOCK(txr); + if (txr->watchdog_check == FALSE) { + IXGBE_TX_UNLOCK(txr); continue; - if ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG) { - tx_hung = TRUE; - goto hung; } + if ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG) + goto hung; + IXGBE_TX_UNLOCK(txr); } out: + ixgbe_rearm_queues(adapter, adapter->que_mask); callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); return; @@ -2017,6 +1898,7 @@ hung: txr->me, txr->tx_avail, txr->next_to_clean); adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; adapter->watchdog_events++; + IXGBE_TX_UNLOCK(txr); ixgbe_init_locked(adapter); } @@ -2123,8 +2005,7 @@ static int ixgbe_allocate_legacy(struct adapter *adapter) { device_t dev = adapter->dev; - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct ix_queue *que = adapter->queues; int error, rid = 0; /* MSI RID at 1 */ @@ -2144,15 +2025,10 @@ ixgbe_allocate_legacy(struct adapter *adapter) * Try allocating a fast interrupt and the associated deferred * processing contexts. */ - TASK_INIT(&txr->tx_task, 0, ixgbe_handle_tx, txr); - TASK_INIT(&rxr->rx_task, 0, ixgbe_handle_rx, rxr); - txr->tq = taskqueue_create_fast("ixgbe_txq", M_NOWAIT, - taskqueue_thread_enqueue, &txr->tq); - rxr->tq = taskqueue_create_fast("ixgbe_rxq", M_NOWAIT, - taskqueue_thread_enqueue, &rxr->tq); - taskqueue_start_threads(&txr->tq, 1, PI_NET, "%s txq", - device_get_nameunit(adapter->dev)); - taskqueue_start_threads(&rxr->tq, 1, PI_NET, "%s rxq", + TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que); + que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT, + taskqueue_thread_enqueue, &que->tq); + taskqueue_start_threads(&que->tq, 1, PI_NET, "%s ixq", device_get_nameunit(adapter->dev)); /* Tasklets for Link, SFP and Multispeed Fiber */ @@ -2169,15 +2045,17 @@ ixgbe_allocate_legacy(struct adapter *adapter) if ((error = bus_setup_intr(dev, adapter->res, INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq, - adapter, &adapter->tag)) != 0) { + que, &adapter->tag)) != 0) { device_printf(dev, "Failed to register fast interrupt " "handler: %d\n", error); - taskqueue_free(txr->tq); - taskqueue_free(rxr->tq); - txr->tq = NULL; - rxr->tq = NULL; + taskqueue_free(que->tq); + taskqueue_free(adapter->tq); + que->tq = NULL; + adapter->tq = NULL; return (error); } + /* For simplicity in the handlers */ + adapter->que_mask = IXGBE_EIMS_ENABLE_MASK; return (0); } @@ -2192,83 +2070,44 @@ static int ixgbe_allocate_msix(struct adapter *adapter) { device_t dev = adapter->dev; - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct ix_queue *que = adapter->queues; int error, rid, vector = 0; - /* TX setup: the code is here for multi tx, - there are other parts of the driver not ready for it */ - for (int i = 0; i < adapter->num_queues; i++, vector++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, vector++, que++) { rid = vector + 1; - txr->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); - if (!txr->res) { + if (que->res == NULL) { device_printf(dev,"Unable to allocate" - " bus resource: tx interrupt [%d]\n", vector); + " bus resource: que interrupt [%d]\n", vector); return (ENXIO); } /* Set the handler function */ - error = bus_setup_intr(dev, txr->res, + error = bus_setup_intr(dev, que->res, INTR_TYPE_NET | INTR_MPSAFE, NULL, - ixgbe_msix_tx, txr, &txr->tag); + ixgbe_msix_que, que, &que->tag); if (error) { - txr->res = NULL; - device_printf(dev, "Failed to register TX handler"); + que->res = NULL; + device_printf(dev, "Failed to register QUE handler"); return (error); } - txr->msix = vector; + que->msix = vector; + adapter->que_mask |= (u64)(1 << que->msix); /* ** Bind the msix vector, and thus the ** ring to the corresponding cpu. */ if (adapter->num_queues > 1) - bus_bind_intr(dev, txr->res, i); + bus_bind_intr(dev, que->res, i); - TASK_INIT(&txr->tx_task, 0, ixgbe_handle_tx, txr); - txr->tq = taskqueue_create_fast("ixgbe_txq", M_NOWAIT, - taskqueue_thread_enqueue, &txr->tq); - taskqueue_start_threads(&txr->tq, 1, PI_NET, "%s txq", + TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que); + que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT, + taskqueue_thread_enqueue, &que->tq); + taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que", device_get_nameunit(adapter->dev)); } - /* RX setup */ - for (int i = 0; i < adapter->num_queues; i++, vector++, rxr++) { - rid = vector + 1; - rxr->res = bus_alloc_resource_any(dev, - SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); - if (!rxr->res) { - device_printf(dev,"Unable to allocate" - " bus resource: rx interrupt [%d]," - "rid = %d\n", i, rid); - return (ENXIO); - } - /* Set the handler function */ - error = bus_setup_intr(dev, rxr->res, - INTR_TYPE_NET | INTR_MPSAFE, NULL, - ixgbe_msix_rx, rxr, &rxr->tag); - if (error) { - rxr->res = NULL; - device_printf(dev, "Failed to register RX handler"); - return (error); - } - rxr->msix = vector; - /* used in local timer */ - adapter->rx_mask |= (u64)(1 << vector); - /* - ** Bind the msix vector, and thus the - ** ring to the corresponding cpu. - */ - if (adapter->num_queues > 1) - bus_bind_intr(dev, rxr->res, i); - - TASK_INIT(&rxr->rx_task, 0, ixgbe_handle_rx, rxr); - rxr->tq = taskqueue_create_fast("ixgbe_rxq", M_NOWAIT, - taskqueue_thread_enqueue, &rxr->tq); - taskqueue_start_threads(&rxr->tq, 1, PI_NET, "%s rxq", - device_get_nameunit(adapter->dev)); - } - - /* Now for Link changes */ + /* and Link */ rid = vector + 1; adapter->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); @@ -2340,15 +2179,15 @@ ixgbe_setup_msix(struct adapter *adapter) } /* Figure out a reasonable auto config value */ - queues = (mp_ncpus > ((msgs-1)/2)) ? (msgs-1)/2 : mp_ncpus; + queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus; if (ixgbe_num_queues == 0) ixgbe_num_queues = queues; /* - ** Want two vectors (RX/TX) per queue + ** Want one vector (RX/TX pair) per queue ** plus an additional for Link. */ - want = (ixgbe_num_queues * 2) + 1; + want = ixgbe_num_queues + 1; if (msgs >= want) msgs = want; else { @@ -2409,8 +2248,7 @@ ixgbe_allocate_pci_resources(struct adapter *adapter) static void ixgbe_free_pci_resources(struct adapter * adapter) { - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct ix_queue *que = adapter->queues; device_t dev = adapter->dev; int rid, memrid; @@ -2431,29 +2269,18 @@ ixgbe_free_pci_resources(struct adapter * adapter) goto mem; /* - ** Release all the interrupt resources: - ** notice this is harmless for Legacy or - ** MSI since pointers will always be NULL + ** Release all msix queue resources: */ - for (int i = 0; i < adapter->num_queues; i++, txr++) { - rid = txr->msix + 1; - if (txr->tag != NULL) { - bus_teardown_intr(dev, txr->res, txr->tag); - txr->tag = NULL; + for (int i = 0; i < adapter->num_queues; i++, que++) { + rid = que->msix + 1; + if (que->tag != NULL) { + bus_teardown_intr(dev, que->res, que->tag); + que->tag = NULL; } - if (txr->res != NULL) - bus_release_resource(dev, SYS_RES_IRQ, rid, txr->res); + if (que->res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, rid, que->res); } - for (int i = 0; i < adapter->num_queues; i++, rxr++) { - rid = rxr->msix + 1; - if (rxr->tag != NULL) { - bus_teardown_intr(dev, rxr->res, rxr->tag); - rxr->tag = NULL; - } - if (rxr->res != NULL) - bus_release_resource(dev, SYS_RES_IRQ, rid, rxr->res); - } /* Clean the Legacy or Link interrupt last */ if (adapter->linkvec) /* we are doing MSIX */ @@ -2467,6 +2294,7 @@ ixgbe_free_pci_resources(struct adapter * adapter) } if (adapter->res != NULL) bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res); + mem: if (adapter->msix) pci_release_msi(dev); @@ -2524,9 +2352,7 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM; ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; - ifp->if_capabilities |= IFCAP_JUMBO_MTU; - if (ixgbe_header_split) - ifp->if_capabilities |= IFCAP_LRO; + ifp->if_capabilities |= IFCAP_JUMBO_MTU | IFCAP_LRO; ifp->if_capenable = ifp->if_capabilities; @@ -2546,6 +2372,7 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) } ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); + return; } @@ -2556,17 +2383,7 @@ ixgbe_config_link(struct adapter *adapter) u32 autoneg, err = 0; bool sfp, negotiate; - switch (hw->phy.type) { - case ixgbe_phy_sfp_avago: - case ixgbe_phy_sfp_ftl: - case ixgbe_phy_sfp_intel: - case ixgbe_phy_sfp_unknown: - case ixgbe_phy_tw_tyco: - case ixgbe_phy_tw_unknown: - sfp = TRUE; - default: - sfp = FALSE; - } + sfp = ixgbe_is_sfp(hw); if (sfp) { if (hw->phy.multispeed_fiber) { @@ -2613,8 +2430,8 @@ ixgbe_dma_malloc(struct adapter *adapter, bus_size_t size, device_t dev = adapter->dev; int r; - r = bus_dma_tag_create(NULL, /* parent */ - 1, 0, /* alignment, bounds */ + r = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */ + DBA_ALIGN, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ @@ -2679,21 +2496,30 @@ ixgbe_dma_free(struct adapter *adapter, struct ixgbe_dma_alloc *dma) static int ixgbe_allocate_queues(struct adapter *adapter) { - device_t dev = adapter->dev; - struct tx_ring *txr; - struct rx_ring *rxr; + device_t dev = adapter->dev; + struct ix_queue *que; + struct tx_ring *txr; + struct rx_ring *rxr; int rsize, tsize, error = IXGBE_SUCCESS; int txconf = 0, rxconf = 0; + /* First allocate the top level queue structs */ + if (!(adapter->queues = + (struct ix_queue *) malloc(sizeof(struct ix_queue) * + adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + device_printf(dev, "Unable to allocate queue memory\n"); + error = ENOMEM; + goto fail; + } + /* First allocate the TX ring struct memory */ if (!(adapter->tx_rings = (struct tx_ring *) malloc(sizeof(struct tx_ring) * adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { device_printf(dev, "Unable to allocate TX ring memory\n"); error = ENOMEM; - goto fail; + goto tx_fail; } - txr = adapter->tx_rings; /* Next allocate the RX */ if (!(adapter->rx_rings = @@ -2703,11 +2529,10 @@ ixgbe_allocate_queues(struct adapter *adapter) error = ENOMEM; goto rx_fail; } - rxr = adapter->rx_rings; /* For the ring itself */ tsize = roundup2(adapter->num_tx_desc * - sizeof(union ixgbe_adv_tx_desc), 4096); + sizeof(union ixgbe_adv_tx_desc), DBA_ALIGN); /* * Now set up the TX queues, txconf is needed to handle the @@ -2746,6 +2571,12 @@ ixgbe_allocate_queues(struct adapter *adapter) /* Allocate a buf ring */ txr->br = buf_ring_alloc(IXGBE_BR_SIZE, M_DEVBUF, M_WAITOK, &txr->tx_mtx); + if (txr->br == NULL) { + device_printf(dev, + "Critical Failure setting up buf ring\n"); + error = ENOMEM; + goto err_tx_desc; + } #endif } @@ -2753,7 +2584,7 @@ ixgbe_allocate_queues(struct adapter *adapter) * Next the RX queues... */ rsize = roundup2(adapter->num_rx_desc * - sizeof(union ixgbe_adv_rx_desc), 4096); + sizeof(union ixgbe_adv_rx_desc), DBA_ALIGN); for (int i = 0; i < adapter->num_queues; i++, rxconf++) { rxr = &adapter->rx_rings[i]; /* Set up some basics */ @@ -2784,6 +2615,16 @@ ixgbe_allocate_queues(struct adapter *adapter) } } + /* + ** Finally set up the queue holding structs + */ + for (int i = 0; i < adapter->num_queues; i++) { + que = &adapter->queues[i]; + que->adapter = adapter; + que->txr = &adapter->tx_rings[i]; + que->rxr = &adapter->rx_rings[i]; + } + return (0); err_rx_desc: @@ -2795,6 +2636,8 @@ err_tx_desc: free(adapter->rx_rings, M_DEVBUF); rx_fail: free(adapter->tx_rings, M_DEVBUF); +tx_fail: + free(adapter->queues, M_DEVBUF); fail: return (error); } @@ -2871,6 +2714,7 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr) int i; /* Clear the old ring contents */ + IXGBE_TX_LOCK(txr); bzero((void *)txr->tx_base, (sizeof(union ixgbe_adv_tx_desc)) * adapter->num_tx_desc); /* Reset indices */ @@ -2902,6 +2746,7 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr) bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + IXGBE_TX_UNLOCK(txr); } /********************************************************************* @@ -3281,6 +3126,7 @@ static void ixgbe_atr(struct tx_ring *txr, struct mbuf *mp) { struct adapter *adapter = txr->adapter; + struct ix_queue *que; struct ixgbe_atr_input atr_input; struct ip *ip; struct tcphdr *th; @@ -3331,6 +3177,7 @@ ixgbe_atr(struct tx_ring *txr, struct mbuf *mp) src_ipv4_addr = ip->ip_src.s_addr; dst_ipv4_addr = ip->ip_dst.s_addr; flex_bytes = etype; + que = &adapter->queues[txr->me]; ixgbe_atr_set_vlan_id_82599(&atr_input, vlan_id); ixgbe_atr_set_src_port_82599(&atr_input, dst_port); @@ -3343,7 +3190,7 @@ ixgbe_atr(struct tx_ring *txr, struct mbuf *mp) /* This assumes the Rx queue and Tx queue are bound to the same CPU */ ixgbe_fdir_add_signature_filter_82599(&adapter->hw, - &atr_input, txr->msix); + &atr_input, que->msix); } #endif @@ -3401,7 +3248,8 @@ ixgbe_txeof(struct tx_ring *txr) ++txr->tx_avail; if (tx_buffer->m_head) { - ifp->if_opackets++; + txr->bytes += + tx_buffer->m_head->m_pkthdr.len; bus_dmamap_sync(txr->txtag, tx_buffer->map, BUS_DMASYNC_POSTWRITE); @@ -3421,6 +3269,8 @@ ixgbe_txeof(struct tx_ring *txr) tx_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[first]; } + ++txr->packets; + ++ifp->if_opackets; /* See if there is more work now */ last = tx_buffer->eop_index; if (last != -1) { @@ -3456,27 +3306,32 @@ ixgbe_txeof(struct tx_ring *txr) /********************************************************************* * - * Refresh mbuf buffers for a range of descriptors + * Refresh mbuf buffers for RX descriptor rings + * - now keeps its own state so discards due to resource + * exhaustion are unnecessary, if an mbuf cannot be obtained + * it just returns, keeping its placeholder, thus it can simply + * be recalled to try again. * **********************************************************************/ -static int -ixgbe_get_buf(struct rx_ring *rxr, int first, int limit) +static void +ixgbe_refresh_mbufs(struct rx_ring *rxr, int limit) { struct adapter *adapter = rxr->adapter; bus_dma_segment_t seg[2]; struct ixgbe_rx_buf *rxbuf; struct mbuf *mh, *mp; bus_dmamap_t map; - int i, nsegs, error; + int i, nsegs, error, cleaned; - i = first; + i = rxr->next_to_refresh; + cleaned = -1; /* Signify no completions */ while (i != limit) { rxbuf = &rxr->rx_buffers[i]; if (rxbuf->m_head == NULL) { mh = m_gethdr(M_DONTWAIT, MT_DATA); if (mh == NULL) - goto failure; + goto update; } else /* reuse */ mh = rxbuf->m_head; @@ -3487,13 +3342,14 @@ ixgbe_get_buf(struct rx_ring *rxr, int first, int limit) mp = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, adapter->rx_mbuf_sz); if (mp == NULL) - goto failure; + goto update; mp->m_len = adapter->rx_mbuf_sz; mp->m_flags &= ~M_PKTHDR; } else { /* reusing */ mp = rxbuf->m_pack; mp->m_len = adapter->rx_mbuf_sz; mp->m_flags &= ~M_PKTHDR; + mp->m_next = NULL; } /* @@ -3509,7 +3365,7 @@ ixgbe_get_buf(struct rx_ring *rxr, int first, int limit) if (error != 0) { printf("GET BUF: dmamap load failure - %d\n", error); m_free(mh); - return (error); + goto update; } /* Unload old mapping and update buffer struct */ @@ -3527,52 +3383,21 @@ ixgbe_get_buf(struct rx_ring *rxr, int first, int limit) rxr->rx_base[i].read.hdr_addr = htole64(seg[0].ds_addr); rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr); + cleaned = i; /* Calculate next index */ if (++i == adapter->num_rx_desc) i = 0; + /* This is the work marker for refresh */ + rxr->next_to_refresh = i; } +update: + if (cleaned != -1) /* If we refreshed some, bump tail */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->me), cleaned); - return (0); - -failure: - panic("GET BUF: ENOBUFS\n"); - -#if 0 - /* - ** If we get here, we have an mbuf resource - ** issue, so we discard the incoming packet - ** and attempt to reuse existing mbufs next - ** pass thru the ring, but to do so we must - ** fix up the descriptor which had the address - ** clobbered with writeback info. - */ -remap: - adapter->mbuf_header_failed++; - merr = ENOBUFS; - /* Is there a reusable buffer? */ - mh = rxr->rx_buffers[i].m_head; - if (mh == NULL) /* Nope, init error */ - return (merr); - mp = rxr->rx_buffers[i].m_pack; - if (mp == NULL) /* Nope, init error */ - return (merr); - /* Get our old mapping */ - rxbuf = &rxr->rx_buffers[i]; - error = bus_dmamap_load_mbuf_sg(rxr->rxtag, - rxbuf->map, mh, seg, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - /* We really have a problem */ - m_free(mh); - return (error); - } - /* Now fix the descriptor as needed */ - rxr->rx_base[i].read.hdr_addr = htole64(seg[0].ds_addr); - rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr); - - return (merr); -#endif + return; } + /********************************************************************* * * Allocate memory for rx_buffer structures. Since we use one @@ -3603,7 +3428,7 @@ ixgbe_allocate_receive_buffers(struct rx_ring *rxr) ** with packet split (hence the two segments, even though ** it may not always use this. */ - if ((error = bus_dma_tag_create(NULL, /* parent */ + if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ @@ -3646,7 +3471,6 @@ fail: return (error); } - /* ** Used to detect a descriptor that has ** been merged by Hardware RSC. @@ -3670,11 +3494,12 @@ ixgbe_setup_hw_rsc(struct rx_ring *rxr) { struct adapter *adapter = rxr->adapter; struct ixgbe_hw *hw = &adapter->hw; - u32 rscctrl, rdrxctl; + u32 rscctrl, rdrxctl; rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP; + rdrxctl |= IXGBE_RDRXCTL_RSCACKC; IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(rxr->me)); @@ -3723,6 +3548,7 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr) dev = adapter->dev; /* Clear the ring contents */ + IXGBE_RX_LOCK(rxr); rsize = roundup2(adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc), DBA_ALIGN); bzero((void *)rxr->rx_base, rsize); @@ -3781,14 +3607,12 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr) /* Setup our descriptor indices */ rxr->next_to_check = 0; - rxr->last_refreshed = 0; + rxr->next_to_refresh = 0; rxr->lro_enabled = FALSE; /* Use header split if configured */ if (ixgbe_header_split) rxr->hdr_split = TRUE; - else - ifp->if_capabilities &= ~IFCAP_LRO; bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -3796,40 +3620,25 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr) /* ** Now set up the LRO interface: ** 82598 uses software LRO, the - ** 82599 on the other hand uses a - ** hardware assist to do the same. - ** We only do LRO when header split - ** is enabled, its simpler that way. + ** 82599 additionally uses a + ** hardware assist. + ** + ** Disable RSC when RXCSUM is off */ - if ((ifp->if_capenable & IFCAP_LRO) && (rxr->hdr_split)) { + if ((adapter->hw.mac.type == ixgbe_mac_82599EB) && + (ifp->if_capenable & IFCAP_RXCSUM)) + ixgbe_setup_hw_rsc(rxr); + else if (ifp->if_capenable & IFCAP_LRO) { int err = tcp_lro_init(lro); if (err) panic("LRO Initialization failed!\n"); INIT_DEBUGOUT("RX Soft LRO Initialized\n"); rxr->lro_enabled = TRUE; lro->ifp = adapter->ifp; - ixgbe_setup_hw_rsc(rxr); } + IXGBE_RX_UNLOCK(rxr); return (0); -#if 0 -fail: - /* - * We need to clean up any buffers allocated - * so far, 'j' is the failing index. - */ - for (int i = 0; i < j; i++) { - rxbuf = &rxr->rx_buffers[i]; - if (rxbuf->m_head != NULL) { - bus_dmamap_sync(rxr->rxtag, rxbuf->map, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(rxr->rxtag, rxbuf->map); - m_freem(rxbuf->m_head); - rxbuf->m_head = NULL; - } - } - return (ENOBUFS); -#endif } /********************************************************************* @@ -4025,6 +3834,7 @@ ixgbe_free_receive_structures(struct adapter *adapter) free(adapter->rx_rings, M_DEVBUF); } + /********************************************************************* * * Free receive ring data structures @@ -4065,6 +3875,61 @@ ixgbe_free_receive_buffers(struct rx_ring *rxr) return; } +static __inline void +ixgbe_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u32 ptype) +{ + + /* + * ATM LRO is only for IPv4/TCP packets and TCP checksum of the packet + * should be computed by hardware. Also it should not have VLAN tag in + * ethernet header. + */ + if (rxr->lro_enabled && + (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && + (ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 && + (ptype & (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)) == + (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP) && + (m->m_pkthdr.csum_flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) == + (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) { + /* + * Send to the stack if: + ** - LRO not enabled, or + ** - no LRO resources, or + ** - lro enqueue fails + */ + if (rxr->lro.lro_cnt != 0) + if (tcp_lro_rx(&rxr->lro, m, 0) == 0) + return; + } + (*ifp->if_input)(ifp, m); +} + +static __inline void +ixgbe_rx_discard(struct rx_ring *rxr, int i) +{ + struct adapter *adapter = rxr->adapter; + struct ixgbe_rx_buf *rbuf; + struct mbuf *mh, *mp; + + rbuf = &rxr->rx_buffers[i]; + if (rbuf->fmp != NULL) /* Partial chain ? */ + m_freem(rbuf->fmp); + + mh = rbuf->m_head; + mp = rbuf->m_pack; + + /* Reuse loaded DMA map and just update mbuf chain */ + mh->m_len = MHLEN; + mh->m_flags |= M_PKTHDR; + mh->m_next = NULL; + + mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz; + mp->m_data = mp->m_ext.ext_buf; + mp->m_next = NULL; + return; +} + + /********************************************************************* * * This routine executes in interrupt context. It replenishes @@ -4077,154 +3942,176 @@ ixgbe_free_receive_buffers(struct rx_ring *rxr) * Return TRUE for more work, FALSE for all clean. *********************************************************************/ static bool -ixgbe_rxeof(struct rx_ring *rxr, int count) +ixgbe_rxeof(struct ix_queue *que, int count) { - struct adapter *adapter = rxr->adapter; - struct ifnet *ifp = adapter->ifp; + struct adapter *adapter = que->adapter; + struct rx_ring *rxr = que->rxr; + struct ifnet *ifp = adapter->ifp; struct lro_ctrl *lro = &rxr->lro; struct lro_entry *queued; - int i, processed = 0; - u32 staterr; + int i, nextp, processed = 0; + u32 staterr = 0; union ixgbe_adv_rx_desc *cur; - + struct ixgbe_rx_buf *rbuf, *nbuf; IXGBE_RX_LOCK(rxr); - i = rxr->next_to_check; - cur = &rxr->rx_base[i]; - staterr = cur->wb.upper.status_error; - if (!(staterr & IXGBE_RXD_STAT_DD)) { - IXGBE_RX_UNLOCK(rxr); - return FALSE; - } + for (i = rxr->next_to_check; count != 0;) { + struct mbuf *sendmp, *mh, *mp; + u32 rsc, ptype; + u16 hlen, plen, hdr, vtag; + bool eop; + + /* Sync the ring. */ + bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - /* Sync the ring */ - bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, - BUS_DMASYNC_POSTREAD); + cur = &rxr->rx_base[i]; + staterr = le32toh(cur->wb.upper.status_error); - while ((staterr & IXGBE_RXD_STAT_DD) && (count != 0) && - (ifp->if_drv_flags & IFF_DRV_RUNNING)) { - struct mbuf *sendmp, *mh, *mp, *nh, *np; - struct ixgbe_rx_buf *nxtbuf; - u32 rsc; - u16 hlen, plen, hdr, nextp, vtag; - bool accept_frame, eop; + if ((staterr & IXGBE_RXD_STAT_DD) == 0) + break; + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + break; + count--; + sendmp = NULL; + nbuf = NULL; + rsc = 0; + cur->wb.upper.status_error = 0; + rbuf = &rxr->rx_buffers[i]; + mh = rbuf->m_head; + mp = rbuf->m_pack; - accept_frame = TRUE; - hlen = plen = rsc = nextp = 0; - sendmp = mh = mp = nh = np = NULL; - - /* Sync the buffers */ - bus_dmamap_sync(rxr->rxtag, rxr->rx_buffers[i].map, - BUS_DMASYNC_POSTREAD); - mh = rxr->rx_buffers[i].m_head; - mp = rxr->rx_buffers[i].m_pack; + plen = le16toh(cur->wb.upper.length); + ptype = le32toh(cur->wb.lower.lo_dword.data) & + IXGBE_RXDADV_PKTTYPE_MASK; + hdr = le16toh(cur->wb.lower.lo_dword.hs_rss.hdr_info); vtag = le16toh(cur->wb.upper.vlan); eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0); + /* Make sure all parts of a bad packet are discarded */ + if (((staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) || + (rxr->discard)) { + ifp->if_ierrors++; + rxr->rx_discarded++; + if (!eop) + rxr->discard = TRUE; + else + rxr->discard = FALSE; + ixgbe_rx_discard(rxr, i); + goto next_desc; + } + + /* + ** On 82599 which supports a hardware + ** LRO (called HW RSC), packets need + ** not be fragmented across sequential + ** descriptors, rather the next descriptor + ** is indicated in bits of the descriptor. + ** This also means that we might proceses + ** more than one packet at a time, something + ** that has never been true before, it + ** required eliminating global chain pointers + ** in favor of what we are doing here. -jfv + */ if (!eop) { /* - ** On 82599 which supports a hardware - ** LRO (called HW RSC), packets need - ** not be fragmented across sequential - ** descriptors, rather the next descriptor - ** is indicated in bits of the current. - ** This also means that we might proceses - ** more than one packet at a time, something - ** that has never been true before, it - ** required eliminating global chain pointers - ** in favor of what we are doing here. -jfv + ** Figure out the next descriptor + ** of this frame. */ if (rxr->hw_rsc == TRUE) { rsc = ixgbe_rsc_count(cur); rxr->rsc_num += (rsc - 1); } - if (rsc) { + if (rsc) { /* Get hardware index */ nextp = ((staterr & IXGBE_RXDADV_NEXTP_MASK) >> IXGBE_RXDADV_NEXTP_SHIFT); - } else { + } else { /* Just sequential */ nextp = i + 1; if (nextp == adapter->num_rx_desc) nextp = 0; } - nxtbuf = &rxr->rx_buffers[nextp]; - prefetch(nxtbuf); + nbuf = &rxr->rx_buffers[nextp]; + prefetch(nbuf); } - /* - ** The way the hardware is configured to - ** split, it will ONLY use the header buffer - ** when header split is enabled, otherwise we - ** get legacy behavior, ie, both header and - ** payload are DMA'd into JUST the payload buffer. + ** The header mbuf is ONLY used when header + ** split is enabled, otherwise we get normal + ** behavior, ie, both header and payload + ** are DMA'd into the payload buffer. ** ** Rather than using the fmp/lmp global pointers ** we now keep the head of a packet chain in the - ** m_nextpkt pointer and pass this along from one + ** buffer struct and pass this along from one ** descriptor to the next, until we get EOP. - ** */ - if ((rxr->hdr_split) && (mh->m_nextpkt == NULL)) { - hdr = le16toh(cur-> - wb.lower.lo_dword.hs_rss.hdr_info); + if (rxr->hdr_split && (rbuf->fmp == NULL)) { + /* This must be an initial descriptor */ hlen = (hdr & IXGBE_RXDADV_HDRBUFLEN_MASK) >> IXGBE_RXDADV_HDRBUFLEN_SHIFT; if (hlen > IXGBE_RX_HDR) hlen = IXGBE_RX_HDR; - plen = le16toh(cur->wb.upper.length); mh->m_len = hlen; mh->m_flags |= M_PKTHDR; mh->m_next = NULL; mh->m_pkthdr.len = mh->m_len; - /* Null this so getbuf replenishes */ - rxr->rx_buffers[i].m_head = NULL; + /* Null buf pointer so it is refreshed */ + rbuf->m_head = NULL; /* - ** Get the payload length, this + ** Check the payload length, this ** could be zero if its a small ** packet. */ - if (plen) { + if (plen > 0) { mp->m_len = plen; mp->m_next = NULL; mp->m_flags &= ~M_PKTHDR; mh->m_next = mp; mh->m_pkthdr.len += mp->m_len; - /* Null this so getbuf replenishes */ - rxr->rx_buffers[i].m_pack = NULL; + /* Null buf pointer so it is refreshed */ + rbuf->m_pack = NULL; rxr->rx_split_packets++; } - /* Setup the forward chain */ - if (eop == 0) { - nh = rxr->rx_buffers[nextp].m_head; - np = rxr->rx_buffers[nextp].m_pack; - nh->m_nextpkt = mh; - if (plen) - mp->m_next = np; - else - mh->m_next = np; - } else { - sendmp = mh; - if (staterr & IXGBE_RXD_STAT_VP) { - sendmp->m_pkthdr.ether_vtag = vtag; - sendmp->m_flags |= M_VLANTAG; - } - } + /* + ** Now create the forward + ** chain so when complete + ** we wont have to. + */ + if (eop == 0) { + /* stash the chain head */ + nbuf->fmp = mh; + /* Make forward chain */ + if (plen) + mp->m_next = nbuf->m_pack; + else + mh->m_next = nbuf->m_pack; + } else { + /* Singlet, prepare to send */ + sendmp = mh; + if (staterr & IXGBE_RXD_STAT_VP) { + sendmp->m_pkthdr.ether_vtag = vtag; + sendmp->m_flags |= M_VLANTAG; + } + } } else { /* ** Either no header split, or a ** secondary piece of a fragmented - ** packet. + ** split packet. */ - mp->m_len = le16toh(cur->wb.upper.length); - rxr->rx_buffers[i].m_pack = NULL; - /* stored head pointer */ - sendmp = mh->m_nextpkt; - if (sendmp != NULL) { + mp->m_len = plen; + /* + ** See if there is a stored head + ** that determines what we are + */ + sendmp = rbuf->fmp; + rbuf->m_pack = rbuf->fmp = NULL; + + if (sendmp != NULL) /* secondary frag */ sendmp->m_pkthdr.len += mp->m_len; - sendmp->m_nextpkt = NULL; - } else { + else { /* first desc of a non-ps chain */ sendmp = mp; sendmp->m_flags |= M_PKTHDR; @@ -4233,106 +4120,53 @@ ixgbe_rxeof(struct rx_ring *rxr, int count) sendmp->m_pkthdr.ether_vtag = vtag; sendmp->m_flags |= M_VLANTAG; } - } - /* Carry head forward */ + } + /* Pass the head pointer on */ if (eop == 0) { - nh = rxr->rx_buffers[nextp].m_head; - np = rxr->rx_buffers[nextp].m_pack; - nh->m_nextpkt = sendmp; - mp->m_next = np; + nbuf->fmp = sendmp; sendmp = NULL; + mp->m_next = nbuf->m_pack; } - mh->m_nextpkt = NULL; } - - if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) - accept_frame = FALSE; - - if (accept_frame) { - ++processed; - if (eop) { - --count; - sendmp->m_pkthdr.rcvif = ifp; - ifp->if_ipackets++; - rxr->rx_packets++; - /* capture data for AIM */ - rxr->bytes += sendmp->m_pkthdr.len; - rxr->rx_bytes += rxr->bytes; - if (ifp->if_capenable & IFCAP_RXCSUM) - ixgbe_rx_checksum(staterr, sendmp); - else - sendmp->m_pkthdr.csum_flags = 0; + ++processed; + /* Sending this frame? */ + if (eop) { + sendmp->m_pkthdr.rcvif = ifp; + ifp->if_ipackets++; + rxr->rx_packets++; + /* capture data for AIM */ + rxr->bytes += sendmp->m_pkthdr.len; + rxr->rx_bytes += sendmp->m_pkthdr.len; + if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) + ixgbe_rx_checksum(staterr, sendmp); #if __FreeBSD_version >= 800000 - /* Get the RSS Hash */ - sendmp->m_pkthdr.flowid = - le16toh(cur->wb.lower.hi_dword.rss); - sendmp->m_flags |= M_FLOWID; + sendmp->m_pkthdr.flowid = que->msix; + sendmp->m_flags |= M_FLOWID; #endif - } - } else { - ifp->if_ierrors++; - /* Reuse loaded DMA map and just update mbuf chain */ - mh->m_len = MHLEN; - mh->m_flags |= M_PKTHDR; - mh->m_next = NULL; - mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz; - mp->m_data = mp->m_ext.ext_buf; - if (mp->m_next) { /* Free chain */ - sendmp = mp->m_next; - m_free(sendmp); - } - mp->m_next = NULL; - if (adapter->max_frame_size <= - (MCLBYTES - ETHER_ALIGN)) - m_adj(mp, ETHER_ALIGN); - sendmp = NULL; } +next_desc: bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - rxr->last_refreshed = i; /* for updating tail */ + /* Advance our pointers to the next descriptor. */ if (++i == adapter->num_rx_desc) i = 0; - /* Prefetch next descriptor */ - cur = &rxr->rx_base[i]; - prefetch(cur); - /* - ** Now send up to the stack, - ** note that the RX lock is - ** held thru this call. - */ - if (sendmp != NULL) { - /* - ** Send to the stack if: - ** - Soft LRO not enabled, or - ** - no Soft LRO resources, or - ** - soft lro enqueue fails - */ - if ((!rxr->lro_enabled) || - ((!lro->lro_cnt) || (tcp_lro_rx(lro, sendmp, 0)))) - (*ifp->if_input)(ifp, sendmp); - } + /* Now send to the stack or do LRO */ + if (sendmp != NULL) + ixgbe_rx_input(rxr, ifp, sendmp, ptype); - /* Replenish every 8 max */ + /* Every 8 descriptors we go to refresh mbufs */ if (processed == 8) { - ixgbe_get_buf(rxr, rxr->next_to_check, i); + ixgbe_refresh_mbufs(rxr, i); processed = 0; - IXGBE_WRITE_REG(&adapter->hw, - IXGBE_RDT(rxr->me), rxr->last_refreshed); - rxr->next_to_check = i; } - - /* Next iteration */ - staterr = cur->wb.upper.status_error; } - /* Replenish remaining work */ + /* Refresh any remaining buf structs */ if (processed != 0) { - ixgbe_get_buf(rxr, rxr->next_to_check, i); + ixgbe_refresh_mbufs(rxr, i); processed = 0; - IXGBE_WRITE_REG(&adapter->hw, - IXGBE_RDT(rxr->me), rxr->last_refreshed); } rxr->next_to_check = i; @@ -4340,8 +4174,7 @@ ixgbe_rxeof(struct rx_ring *rxr, int count) /* * Flush any outstanding LRO work */ - while (!SLIST_EMPTY(&lro->lro_active)) { - queued = SLIST_FIRST(&lro->lro_active); + while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) { SLIST_REMOVE_HEAD(&lro->lro_active, next); tcp_lro_flush(lro, queued); } @@ -4349,17 +4182,18 @@ ixgbe_rxeof(struct rx_ring *rxr, int count) IXGBE_RX_UNLOCK(rxr); /* - ** Leaving with more to clean? - ** then schedule another interrupt. + ** We still have cleaning to do? + ** Schedule another interrupt if so. */ - if (staterr & IXGBE_RXD_STAT_DD) { - ixgbe_rearm_queues(adapter, (u64)(1 << rxr->msix)); - return TRUE; + if ((staterr & IXGBE_RXD_STAT_DD) != 0) { + ixgbe_rearm_queues(adapter, (u64)(1 << que->msix)); + return (TRUE); } - return FALSE; + return (FALSE); } + /********************************************************************* * * Verify that the hardware indicated that the checksum is valid. @@ -4374,7 +4208,6 @@ ixgbe_rx_checksum(u32 staterr, struct mbuf * mp) u8 errors = (u8) (staterr >> 24); if (status & IXGBE_RXD_STAT_IPCS) { - /* Did it pass? */ if (!(errors & IXGBE_RXD_ERR_IPE)) { /* IP Checksum Good */ mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; @@ -4384,7 +4217,6 @@ ixgbe_rx_checksum(u32 staterr, struct mbuf * mp) mp->m_pkthdr.csum_flags = 0; } if (status & IXGBE_RXD_STAT_L4CS) { - /* Did it pass? */ if (!(errors & IXGBE_RXD_ERR_TCPE)) { mp->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); @@ -4493,8 +4325,7 @@ static void ixgbe_enable_intr(struct adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct ix_queue *que = adapter->queues; u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); @@ -4528,10 +4359,8 @@ ixgbe_enable_intr(struct adapter *adapter) ** allow for handling the extended (beyond 32) MSIX ** vectors that can be used by 82599 */ - for (int i = 0; i < adapter->num_queues; i++, rxr++) - ixgbe_enable_queue(adapter, rxr->msix); - for (int i = 0; i < adapter->num_queues; i++, txr++) - ixgbe_enable_queue(adapter, txr->msix); + for (int i = 0; i < adapter->num_queues; i++, que++) + ixgbe_enable_queue(adapter, que->msix); IXGBE_WRITE_FLUSH(hw); @@ -4626,14 +4455,17 @@ ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type) static void ixgbe_configure_ivars(struct adapter *adapter) { - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct ix_queue *que = adapter->queues; - for (int i = 0; i < adapter->num_queues; i++, rxr++) - ixgbe_set_ivar(adapter, i, rxr->msix, 0); - - for (int i = 0; i < adapter->num_queues; i++, txr++) - ixgbe_set_ivar(adapter, i, txr->msix, 1); + for (int i = 0; i < adapter->num_queues; i++, que++) { + /* First the RX queue entry */ + ixgbe_set_ivar(adapter, i, que->msix, 0); + /* ... and the TX */ + ixgbe_set_ivar(adapter, i, que->msix, 1); + /* Set an Initial EITR value */ + IXGBE_WRITE_REG(&adapter->hw, + IXGBE_EITR(que->msix), IXGBE_LOW_LATENCY); + } /* For the Link interrupt */ ixgbe_set_ivar(adapter, 1, adapter->linkvec, -1); @@ -4922,44 +4754,43 @@ static void ixgbe_print_debug_info(struct adapter *adapter) { device_t dev = adapter->dev; - struct rx_ring *rxr = adapter->rx_rings; - struct tx_ring *txr = adapter->tx_rings; - struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_hw *hw = &adapter->hw; + struct ix_queue *que = adapter->queues; + struct rx_ring *rxr; + struct tx_ring *txr; + struct lro_ctrl *lro; device_printf(dev,"Error Byte Count = %u \n", IXGBE_READ_REG(hw, IXGBE_ERRBC)); - for (int i = 0; i < adapter->num_queues; i++, rxr++) { - struct lro_ctrl *lro = &rxr->lro; - device_printf(dev,"Queue[%d]: rdh = %d, hw rdt = %d\n", + for (int i = 0; i < adapter->num_queues; i++, que++) { + txr = que->txr; + rxr = que->rxr; + lro = &rxr->lro; + device_printf(dev,"QUE(%d) IRQs Handled: %lu\n", + que->msix, (long)que->irqs); + device_printf(dev,"RX[%d]: rdh = %d, hw rdt = %d\n", i, IXGBE_READ_REG(hw, IXGBE_RDH(i)), IXGBE_READ_REG(hw, IXGBE_RDT(i))); + device_printf(dev,"TX[%d] tdh = %d, hw tdt = %d\n", i, + IXGBE_READ_REG(hw, IXGBE_TDH(i)), + IXGBE_READ_REG(hw, IXGBE_TDT(i))); device_printf(dev,"RX(%d) Packets Received: %lld\n", rxr->me, (long long)rxr->rx_packets); device_printf(dev,"RX(%d) Split RX Packets: %lld\n", rxr->me, (long long)rxr->rx_split_packets); device_printf(dev,"RX(%d) Bytes Received: %lu\n", rxr->me, (long)rxr->rx_bytes); - device_printf(dev,"RX(%d) IRQ Handled: %lu\n", - rxr->me, (long)rxr->rx_irq); device_printf(dev,"RX(%d) LRO Queued= %d\n", rxr->me, lro->lro_queued); device_printf(dev,"RX(%d) LRO Flushed= %d\n", rxr->me, lro->lro_flushed); device_printf(dev,"RX(%d) HW LRO Merges= %lu\n", rxr->me, (long)rxr->rsc_num); - } - - for (int i = 0; i < adapter->num_queues; i++, txr++) { - device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", i, - IXGBE_READ_REG(hw, IXGBE_TDH(i)), - IXGBE_READ_REG(hw, IXGBE_TDT(i))); device_printf(dev,"TX(%d) Packets Sent: %lu\n", txr->me, (long)txr->total_packets); - device_printf(dev,"TX(%d) IRQ Handled: %lu\n", - txr->me, (long)txr->tx_irq); device_printf(dev,"TX(%d) NO Desc Avail: %lu\n", - txr->me, (long)txr->no_tx_desc_avail); + txr->me, (long)txr->no_desc_avail); } device_printf(dev,"Link IRQ Handled: %lu\n", @@ -5050,174 +4881,3 @@ ixgbe_add_rx_process_limit(struct adapter *adapter, const char *name, SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); } - -#ifdef IXGBE_IEEE1588 - -/* -** ixgbe_hwtstamp_ioctl - control hardware time stamping -** -** Outgoing time stamping can be enabled and disabled. Play nice and -** disable it when requested, although it shouldn't case any overhead -** when no packet needs it. At most one packet in the queue may be -** marked for time stamping, otherwise it would be impossible to tell -** for sure to which packet the hardware time stamp belongs. -** -** Incoming time stamping has to be configured via the hardware -** filters. Not all combinations are supported, in particular event -** type has to be specified. Matching the kind of event packet is -** not supported, with the exception of "all V2 events regardless of -** level 2 or 4". -** -*/ -static int -ixgbe_hwtstamp_ioctl(struct adapter *adapter, struct ifreq *ifr) -{ - struct ixgbe_hw *hw = &adapter->hw; - struct hwtstamp_ctrl *config; - u32 tsync_tx_ctl_bit = IXGBE_TSYNCTXCTL_ENABLED; - u32 tsync_rx_ctl_bit = IXGBE_TSYNCRXCTL_ENABLED; - u32 tsync_rx_ctl_type = 0; - u32 tsync_rx_cfg = 0; - int is_l4 = 0; - int is_l2 = 0; - u16 port = 319; /* PTP */ - u32 regval; - - config = (struct hwtstamp_ctrl *) ifr->ifr_data; - - /* reserved for future extensions */ - if (config->flags) - return (EINVAL); - - switch (config->tx_type) { - case HWTSTAMP_TX_OFF: - tsync_tx_ctl_bit = 0; - break; - case HWTSTAMP_TX_ON: - tsync_tx_ctl_bit = IXGBE_TSYNCTXCTL_ENABLED; - break; - default: - return (ERANGE); - } - - switch (config->rx_filter) { - case HWTSTAMP_FILTER_NONE: - tsync_rx_ctl_bit = 0; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_ALL: - /* - * register TSYNCRXCFG must be set, therefore it is not - * possible to time stamp both Sync and Delay_Req messages - * => fall back to time stamping all packets - */ - tsync_rx_ctl_type = IXGBE_TSYNCRXCTL_TYPE_ALL; - config->rx_filter = HWTSTAMP_FILTER_ALL; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - tsync_rx_ctl_type = IXGBE_TSYNCRXCTL_TYPE_L4_V1; - tsync_rx_cfg = IXGBE_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; - is_l4 = 1; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - tsync_rx_ctl_type = IXGBE_TSYNCRXCTL_TYPE_L4_V1; - tsync_rx_cfg = IXGBE_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; - is_l4 = 1; - break; - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - tsync_rx_ctl_type = IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2; - tsync_rx_cfg = IXGBE_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE; - is_l2 = 1; - is_l4 = 1; - config->rx_filter = HWTSTAMP_FILTER_SOME; - break; - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - tsync_rx_ctl_type = IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2; - tsync_rx_cfg = IXGBE_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE; - is_l2 = 1; - is_l4 = 1; - config->rx_filter = HWTSTAMP_FILTER_SOME; - break; - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - tsync_rx_ctl_type = IXGBE_TSYNCRXCTL_TYPE_EVENT_V2; - config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - is_l2 = 1; - break; - default: - return -ERANGE; - } - - /* enable/disable TX */ - regval = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); - regval = (regval & ~IXGBE_TSYNCTXCTL_ENABLED) | tsync_tx_ctl_bit; - IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, regval); - - /* enable/disable RX, define which PTP packets are time stamped */ - regval = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); - regval = (regval & ~IXGBE_TSYNCRXCTL_ENABLED) | tsync_rx_ctl_bit; - regval = (regval & ~0xE) | tsync_rx_ctl_type; - IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCTL, regval); - IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCFG, tsync_rx_cfg); - - /* - * Ethertype Filter Queue Filter[0][15:0] = 0x88F7 - * (Ethertype to filter on) - * Ethertype Filter Queue Filter[0][26] = 0x1 (Enable filter) - * Ethertype Filter Queue Filter[0][30] = 0x1 (Enable Timestamping) - */ - IXGBE_WRITE_REG(hw, IXGBE_ETQF0, is_l2 ? 0x440088f7 : 0); - - /* L4 Queue Filter[0]: only filter by source and destination port */ - IXGBE_WRITE_REG(hw, IXGBE_SPQF0, htons(port)); - IXGBE_WRITE_REG(hw, IXGBE_IMIREXT(0), is_l4 ? - ((1<<12) | (1<<19) /* bypass size and control flags */) : 0); - IXGBE_WRITE_REG(hw, IXGBE_IMIR(0), is_l4 ? - (htons(port) - | (0<<16) /* immediate interrupt disabled */ - | 0 /* (1<<17) bit cleared: do not bypass - destination port check */) - : 0); - IXGBE_WRITE_REG(hw, IXGBE_FTQF0, is_l4 ? - (0x11 /* UDP */ - | (1<<15) /* VF not compared */ - | (1<<27) /* Enable Timestamping */ - | (7<<28) /* only source port filter enabled, - source/target address and protocol - masked */) - : ((1<<15) | (15<<28) /* all mask bits set = filter not - enabled */)); - - wrfl(); - - adapter->hwtstamp_ctrl = config; - - /* clear TX/RX time stamp registers, just to be sure */ - regval = IXGBE_READ_REG(hw, IXGBE_TXSTMPH); - regval = IXGBE_READ_REG(hw, IXGBE_RXSTMPH); - - return (error); -} - -/* -** ixgbe_read_clock - read raw cycle counter (to be used by time counter) -*/ -static cycle_t ixgbe_read_clock(const struct cyclecounter *tc) -{ - struct adapter *adapter = - container_of(tc, struct igb_adapter, cycles); - struct ixgbe_hw *hw = &adapter->hw; - u64 stamp; - - stamp = IXGBE_READ_REG(hw, IXGBE_SYSTIML); - stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32ULL; - - return (stamp); -} - -#endif /* IXGBE_IEEE1588 */ diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index d52eed3a07e..008d2c8cb01 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -176,7 +176,7 @@ #define MSIX_82599_BAR 4 #define IXGBE_TSO_SIZE 65535 #define IXGBE_TX_BUFFER_SIZE ((u32) 1514) -#define IXGBE_RX_HDR 256 +#define IXGBE_RX_HDR 128 #define IXGBE_VFTA_SIZE 128 #define IXGBE_BR_SIZE 4096 #define CSUM_OFFLOAD 7 /* Bits in csum flags */ @@ -231,6 +231,7 @@ struct ixgbe_tx_buf { struct ixgbe_rx_buf { struct mbuf *m_head; struct mbuf *m_pack; + struct mbuf *fmp; bus_dmamap_t map; }; @@ -248,20 +249,34 @@ struct ixgbe_dma_alloc { }; /* - * The transmit ring, one per tx queue +** Driver queue struct: this is the interrupt container +** for the associated tx and rx ring. +*/ +struct ix_queue { + struct adapter *adapter; + u32 msix; /* This queue's MSIX vector */ + u32 eims; /* This queue's EIMS bit */ + u32 eitr_setting; + struct resource *res; + void *tag; + struct tx_ring *txr; + struct rx_ring *rxr; + struct task que_task; + struct taskqueue *tq; + u64 irqs; +}; + +/* + * The transmit ring, one per queue */ struct tx_ring { struct adapter *adapter; struct mtx tx_mtx; u32 me; - u32 msix; bool watchdog_check; int watchdog_time; union ixgbe_adv_tx_desc *tx_base; - volatile u32 tx_hwb; struct ixgbe_dma_alloc txdma; - struct task tx_task; - struct taskqueue *tq; u32 next_avail_desc; u32 next_to_clean; struct ixgbe_tx_buf *tx_buffers; @@ -272,17 +287,14 @@ struct tx_ring { #if __FreeBSD_version >= 800000 struct buf_ring *br; #endif - /* Interrupt resources */ - void *tag; - struct resource *res; #ifdef IXGBE_FDIR u16 atr_sample; u16 atr_count; #endif + u32 bytes; /* used for AIM */ + u32 packets; /* Soft Stats */ - u32 no_tx_desc_avail; - u32 no_tx_desc_late; - u64 tx_irq; + u64 no_desc_avail; u64 total_packets; }; @@ -294,35 +306,29 @@ struct rx_ring { struct adapter *adapter; struct mtx rx_mtx; u32 me; - u32 msix; - u32 payload; - struct task rx_task; - struct taskqueue *tq; union ixgbe_adv_rx_desc *rx_base; struct ixgbe_dma_alloc rxdma; struct lro_ctrl lro; bool lro_enabled; bool hdr_split; bool hw_rsc; - unsigned int last_refreshed; - unsigned int next_to_check; + bool discard; + u32 next_to_refresh; + u32 next_to_check; + char mtx_name[16]; struct ixgbe_rx_buf *rx_buffers; bus_dma_tag_t rxtag; bus_dmamap_t spare_map; - char mtx_name[16]; u32 bytes; /* Used for AIM calc */ - u32 eitr_setting; - - /* Interrupt resources */ - void *tag; - struct resource *res; + u32 packets; /* Soft stats */ u64 rx_irq; u64 rx_split_packets; u64 rx_packets; u64 rx_bytes; + u64 rx_discarded; u64 rsc_num; #ifdef IXGBE_FDIR u64 flm; @@ -331,94 +337,94 @@ struct rx_ring { /* Our adapter structure */ struct adapter { - struct ifnet *ifp; - struct ixgbe_hw hw; + struct ifnet *ifp; + struct ixgbe_hw hw; struct ixgbe_osdep osdep; - struct device *dev; + struct device *dev; - struct resource *pci_mem; - struct resource *msix_mem; + struct resource *pci_mem; + struct resource *msix_mem; /* * Interrupt resources: this set is * either used for legacy, or for Link * when doing MSIX */ - void *tag; - struct resource *res; + void *tag; + struct resource *res; - struct ifmedia media; - struct callout timer; - int msix; - int if_flags; + struct ifmedia media; + struct callout timer; + int msix; + int if_flags; - struct mtx core_mtx; + struct mtx core_mtx; - eventhandler_tag vlan_attach; - eventhandler_tag vlan_detach; + eventhandler_tag vlan_attach; + eventhandler_tag vlan_detach; - u16 num_vlans; - u16 num_queues; + u16 num_vlans; + u16 num_queues; /* Info about the board itself */ - u32 optics; - bool link_active; - u16 max_frame_size; - u32 link_speed; - bool link_up; - u32 linkvec; + u32 optics; + bool link_active; + u16 max_frame_size; + u32 link_speed; + bool link_up; + u32 linkvec; /* Mbuf cluster size */ - u32 rx_mbuf_sz; + u32 rx_mbuf_sz; /* Support for pluggable optics */ - bool sfp_probe; - struct task link_task; /* Link tasklet */ - struct task mod_task; /* SFP tasklet */ - struct task msf_task; /* Multispeed Fiber tasklet */ + bool sfp_probe; + struct task link_task; /* Link tasklet */ + struct task mod_task; /* SFP tasklet */ + struct task msf_task; /* Multispeed Fiber */ #ifdef IXGBE_FDIR int fdir_reinit; struct task fdir_task; #endif struct taskqueue *tq; + /* + ** Queues: + ** This is the irq holder, it has + ** and RX/TX pair or rings associated + ** with it. + */ + struct ix_queue *queues; + /* * Transmit rings: * Allocated at run time, an array of rings. */ - struct tx_ring *tx_rings; - int num_tx_desc; + struct tx_ring *tx_rings; + int num_tx_desc; /* * Receive rings: * Allocated at run time, an array of rings. */ - struct rx_ring *rx_rings; - int num_rx_desc; - u64 rx_mask; - u32 rx_process_limit; - -#ifdef IXGBE_IEEE1588 - /* IEEE 1588 precision time support */ - struct cyclecounter cycles; - struct nettimer clock; - struct nettime_compare compare; - struct hwtstamp_ctrl hwtstamp; -#endif + struct rx_ring *rx_rings; + int num_rx_desc; + u64 que_mask; + u32 rx_process_limit; /* Misc stats maintained by the driver */ - unsigned long dropped_pkts; - unsigned long mbuf_defrag_failed; - unsigned long mbuf_header_failed; - unsigned long mbuf_packet_failed; - unsigned long no_tx_map_avail; - unsigned long no_tx_dma_setup; - unsigned long watchdog_events; - unsigned long tso_tx; - unsigned long link_irq; + unsigned long dropped_pkts; + unsigned long mbuf_defrag_failed; + unsigned long mbuf_header_failed; + unsigned long mbuf_packet_failed; + unsigned long no_tx_map_avail; + unsigned long no_tx_dma_setup; + unsigned long watchdog_events; + unsigned long tso_tx; + unsigned long link_irq; - struct ixgbe_hw_stats stats; + struct ixgbe_hw_stats stats; }; /* Precision Time Sync (IEEE 1588) defines */ @@ -452,8 +458,8 @@ ixgbe_is_sfp(struct ixgbe_hw *hw) case ixgbe_phy_sfp_ftl: case ixgbe_phy_sfp_intel: case ixgbe_phy_sfp_unknown: - case ixgbe_phy_tw_tyco: - case ixgbe_phy_tw_unknown: + case ixgbe_phy_sfp_passive_tyco: + case ixgbe_phy_sfp_passive_unknown: return TRUE; default: return FALSE; diff --git a/sys/dev/ixgbe/ixgbe_82598.c b/sys/dev/ixgbe/ixgbe_82598.c index 12711b0a9b4..0570aa5c588 100644 --- a/sys/dev/ixgbe/ixgbe_82598.c +++ b/sys/dev/ixgbe/ixgbe_82598.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -59,6 +59,7 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, bool autoneg_wait_to_complete); static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw); +void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw); s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, @@ -164,6 +165,7 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw) /* MAC */ mac->ops.start_hw = &ixgbe_start_hw_82598; + mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_82598; mac->ops.reset_hw = &ixgbe_reset_hw_82598; mac->ops.get_media_type = &ixgbe_get_media_type_82598; mac->ops.get_supported_physical_layer = @@ -273,7 +275,8 @@ out: * @hw: pointer to hardware structure * * Starts the hardware using the generic start_hw function. - * Then set pcie completion timeout + * Disables relaxed ordering Then set pcie completion timeout + * **/ s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) { @@ -287,17 +290,17 @@ s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) /* Disable relaxed ordering */ for (i = 0; ((i < hw->mac.max_tx_queues) && - (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { + (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval); } for (i = 0; ((i < hw->mac.max_rx_queues) && - (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { + (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | - IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } @@ -439,15 +442,23 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) DEBUGFUNC("ixgbe_fc_enable_82598"); /* - * On 82598 backplane having FC on causes resets while doing - * KX, so turn off here. + * On 82598 having Rx FC on causes resets while doing 1G + * so if it's on turn it off once we know link_speed. For + * more details see 82598 Specification update. */ hw->mac.ops.check_link(hw, &link_speed, &link_up, FALSE); - if (link_up && - link_speed == IXGBE_LINK_SPEED_1GB_FULL && - hw->mac.ops.get_media_type(hw) == ixgbe_media_type_backplane) { - hw->fc.disable_fc_autoneg = TRUE; - hw->fc.requested_mode = ixgbe_fc_none; + if (link_up && link_speed == IXGBE_LINK_SPEED_1GB_FULL) { + switch (hw->fc.requested_mode) { + case ixgbe_fc_full: + hw->fc.requested_mode = ixgbe_fc_tx_pause; + break; + case ixgbe_fc_rx_pause: + hw->fc.requested_mode = ixgbe_fc_none; + break; + default: + /* no change */ + break; + } } /* Negotiate the fc mode to use */ @@ -842,12 +853,9 @@ no_phy_reset: * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset */ - status = ixgbe_disable_pcie_master(hw); - if (status != IXGBE_SUCCESS) { - status = IXGBE_ERR_MASTER_REQUESTS_PENDING; - DEBUGOUT("PCI-E Master disable polling has failed.\n"); - } + ixgbe_disable_pcie_master(hw); +mac_reset_top: /* * Issue global reset to the MAC. This needs to be a SW reset. * If link reset is used, it might reset the MAC when mng is using it @@ -868,6 +876,19 @@ no_phy_reset: DEBUGOUT("Reset polling failed to complete.\n"); } + /* + * Double resets are required for recovery from certain error + * conditions. Between resets, it is necessary to stall to allow time + * for any pending HW events to complete. We use 1usec since that is + * what is needed for ixgbe_disable_pcie_master(). The second reset + * then clears out any effects of those events. + */ + if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { + hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; + usec_delay(1); + goto mac_reset_top; + } + msec_delay(50); gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); @@ -1299,3 +1320,32 @@ static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw) return IXGBE_SUCCESS; } +/** + * ixgbe_enable_relaxed_ordering_82598 - enable relaxed ordering + * @hw: pointer to hardware structure + * + **/ +void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw) +{ + u32 regval; + u32 i; + + DEBUGFUNC("ixgbe_enable_relaxed_ordering_82598"); + + /* Enable relaxed ordering */ + for (i = 0; ((i < hw->mac.max_tx_queues) && + (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); + regval |= IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval); + } + + for (i = 0; ((i < hw->mac.max_rx_queues) && + (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); + regval |= (IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); + } + +} diff --git a/sys/dev/ixgbe/ixgbe_82599.c b/sys/dev/ixgbe/ixgbe_82599.c index 97b655a26ac..8c5ff21200d 100644 --- a/sys/dev/ixgbe/ixgbe_82599.c +++ b/sys/dev/ixgbe/ixgbe_82599.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -64,6 +64,7 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw); s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw); +void ixgbe_enable_relaxed_ordering_82599(struct ixgbe_hw *hw); s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw); @@ -267,6 +268,8 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, DEBUGFUNC("ixgbe_get_link_capabilities_82599"); + + /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not @@ -878,7 +881,7 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; - u32 ctrl, ctrl_ext; + u32 ctrl; u32 i; u32 autoc; u32 autoc2; @@ -913,12 +916,9 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset */ - status = ixgbe_disable_pcie_master(hw); - if (status != IXGBE_SUCCESS) { - status = IXGBE_ERR_MASTER_REQUESTS_PENDING; - DEBUGOUT("PCI-E Master disable polling has failed.\n"); - } + ixgbe_disable_pcie_master(hw); +mac_reset_top: /* * Issue global reset to the MAC. This needs to be a SW reset. * If link reset is used, it might reset the MAC when mng is using it @@ -938,10 +938,19 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) status = IXGBE_ERR_RESET_FAILED; DEBUGOUT("Reset polling failed to complete.\n"); } - /* Clear PF Reset Done bit so PF/VF Mail Ops can work */ - ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); - ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; - IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); + + /* + * Double resets are required for recovery from certain error + * conditions. Between resets, it is necessary to stall to allow time + * for any pending HW events to complete. We use 1usec since that is + * what is needed for ixgbe_disable_pcie_master(). The second reset + * then clears out any effects of those events. + */ + if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { + hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; + usec_delay(1); + goto mac_reset_top; + } msec_delay(50); @@ -981,8 +990,6 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); - - /* Store the permanent SAN mac address */ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); @@ -1207,6 +1214,9 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc) /* Send interrupt when 64 filters are left */ fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT; + /* Initialize the drop queue to Rx queue 127 */ + fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT); + switch (pballoc) { case IXGBE_FDIR_PBALLOC_64K: /* 2k - 1 perfect filters */ @@ -1886,23 +1896,26 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter * @hw: pointer to hardware structure * @input: input bitstream + * @input_masks: masks for the input bitstream + * @soft_id: software index for the filters * @queue: queue index to direct traffic to * * Note that the caller to this function must lock before calling, since the * hardware writes must be protected from one another. **/ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, - struct ixgbe_atr_input *input, - u16 soft_id, - u8 queue) + struct ixgbe_atr_input *input, + struct ixgbe_atr_input_masks *input_masks, + u16 soft_id, u8 queue) { u32 fdircmd = 0; u32 fdirhash; - u32 src_ipv4, dst_ipv4; + u32 src_ipv4 = 0, dst_ipv4 = 0; u32 src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4; u16 src_port, dst_port, vlan_id, flex_bytes; u16 bucket_hash; u8 l4type; + u8 fdirm = 0; DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599"); @@ -1959,7 +1972,6 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, /* IPv4 */ ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4); IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4); - } ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4); @@ -1968,7 +1980,78 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id | (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT))); IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port | - (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT))); + (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT))); + + /* + * Program the relevant mask registers. If src/dst_port or src/dst_addr + * are zero, then assume a full mask for that field. Also assume that + * a VLAN of 0 is unspecified, so mask that out as well. L4type + * cannot be masked out in this implementation. + * + * This also assumes IPv4 only. IPv6 masking isn't supported at this + * point in time. + */ + if (src_ipv4 == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask); + + if (dst_ipv4 == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xffffffff); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask); + + switch (l4type & IXGBE_ATR_L4TYPE_MASK) { + case IXGBE_ATR_L4TYPE_TCP: + if (src_port == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xffff); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, + input_masks->src_port_mask); + + if (dst_port == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, + (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) | + (0xffff << 16))); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, + (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) | + (input_masks->dst_port_mask << 16))); + break; + case IXGBE_ATR_L4TYPE_UDP: + if (src_port == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xffff); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, + input_masks->src_port_mask); + + if (dst_port == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, + (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) | + (0xffff << 16))); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, + (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) | + (input_masks->src_port_mask << 16))); + break; + default: + /* this already would have failed above */ + break; + } + + /* Program the last mask register, FDIRM */ + if (input_masks->vlan_id_mask || !vlan_id) + /* Mask both VLAN and VLANP - bits 0 and 1 */ + fdirm |= (IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP); + + if (input_masks->data_mask || !flex_bytes) + /* Flex bytes need masking, so mask the whole thing - bit 4 */ + fdirm |= IXGBE_FDIRM_FLEX; + + /* Now mask VM pool and destination IPv6 - bits 5 and 2 */ + fdirm |= (IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6); + + IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW; fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE; @@ -2063,7 +2146,7 @@ s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw) for (i = 0; i < hw->mac.max_rx_queues; i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | - IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } @@ -2192,10 +2275,14 @@ sfp_check: goto out; switch (hw->phy.type) { - case ixgbe_phy_tw_tyco: - case ixgbe_phy_tw_unknown: + case ixgbe_phy_sfp_passive_tyco: + case ixgbe_phy_sfp_passive_unknown: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; break; + case ixgbe_phy_sfp_ftl_active: + case ixgbe_phy_sfp_active_unknown: + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA; + break; case ixgbe_phy_sfp_avago: case ixgbe_phy_sfp_ftl: case ixgbe_phy_sfp_intel: @@ -2328,3 +2415,30 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw) fw_version_out: return status; } +/** + * ixgbe_enable_relaxed_ordering_82599 - Enable relaxed ordering + * @hw: pointer to hardware structure + * + **/ +void ixgbe_enable_relaxed_ordering_82599(struct ixgbe_hw *hw) +{ + u32 regval; + u32 i; + + DEBUGFUNC("ixgbe_enable_relaxed_ordering_82599"); + + /* Enable relaxed ordering */ + for (i = 0; i < hw->mac.max_tx_queues; i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); + regval |= IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); + } + + for (i = 0; i < hw->mac.max_rx_queues; i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); + regval |= (IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); + } + +} diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c index 44644574860..a65686e29f2 100644 --- a/sys/dev/ixgbe/ixgbe_api.c +++ b/sys/dev/ixgbe/ixgbe_api.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -111,6 +111,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_SFP: case IXGBE_DEV_ID_82599_CX4: + case IXGBE_DEV_ID_82599_T3_LOM: hw->mac.type = ixgbe_mac_82599EB; break; default: @@ -167,6 +168,20 @@ s32 ixgbe_start_hw(struct ixgbe_hw *hw) IXGBE_NOT_IMPLEMENTED); } +/** + * ixgbe_enable_relaxed_ordering - Enables tx relaxed ordering, + * which is disabled by default in ixgbe_start_hw(); + * + * @hw: pointer to hardware structure + * + * Enable relaxed ordering; + **/ +void ixgbe_enable_relaxed_ordering(struct ixgbe_hw *hw) +{ + if (hw->mac.ops.enable_relaxed_ordering) + hw->mac.ops.enable_relaxed_ordering(hw); +} + /** * ixgbe_clear_hw_cntrs - Clear hardware counters * @hw: pointer to hardware structure diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h index 8ab78ad8720..48c523c1897 100644 --- a/sys/dev/ixgbe/ixgbe_api.h +++ b/sys/dev/ixgbe/ixgbe_api.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -43,6 +43,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw); s32 ixgbe_init_hw(struct ixgbe_hw *hw); s32 ixgbe_reset_hw(struct ixgbe_hw *hw); s32 ixgbe_start_hw(struct ixgbe_hw *hw); +void ixgbe_enable_relaxed_ordering(struct ixgbe_hw *hw); s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw); enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw); s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr); @@ -122,6 +123,7 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, u8 queue); s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, struct ixgbe_atr_input *input, + struct ixgbe_atr_input_masks *masks, u16 soft_id, u8 queue); u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *input, u32 key); diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index 89e57d83dab..217c477a6c6 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -474,8 +474,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests */ - if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) - DEBUGOUT("PCI-E Master disable polling has failed.\n"); + ixgbe_disable_pcie_master(hw); return IXGBE_SUCCESS; } @@ -2198,10 +2197,14 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) u32 i; u32 reg_val; u32 number_of_queues; - s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; + s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_disable_pcie_master"); + /* Just jump out if bus mastering is already disabled */ + if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) + goto out; + /* Disable the receive unit by stopping each queue */ number_of_queues = hw->mac.max_rx_queues; for (i = 0; i < number_of_queues; i++) { @@ -2217,13 +2220,42 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val); for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { - if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) { - status = IXGBE_SUCCESS; - break; - } + if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) + goto out; usec_delay(100); } + DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); + status = IXGBE_ERR_MASTER_REQUESTS_PENDING; + + /* + * The GIO Master Disable bit didn't clear. There are multiple reasons + * for this listed in the datasheet 5.2.5.3.2 Master Disable, and they + * all require a double reset to recover from. Before proceeding, we + * first wait a little more to try to ensure that, at a minimum, the + * PCIe block has no transactions pending. + */ + for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { + if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) & + IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) + break; + usec_delay(100); + } + + if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT) + DEBUGOUT("PCIe transaction pending bit also did not clear.\n"); + + /* + * Two consecutive resets are required via CTRL.RST per datasheet + * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine + * of this need. The first reset prevents new master requests from + * being issued by our device. We then must wait 1usec for any + * remaining completions from the PCIe bus to trickle in, and then reset + * again to clear out any effects they may have had on our device. + */ + hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; + +out: return status; } @@ -2695,6 +2727,10 @@ s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) u32 first_empty_slot = 0; s32 regindex; + /* short cut the special case */ + if (vlan == 0) + return 0; + /* * Search for the vlan id in the VLVF entries. Save off the first empty * slot found along the way @@ -2717,7 +2753,7 @@ s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) regindex = first_empty_slot; else { DEBUGOUT("No space in VLVF.\n"); - regindex = -1; + regindex = IXGBE_ERR_NO_SPACE; } } @@ -2738,8 +2774,11 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, { s32 regindex; u32 bitindex; + u32 vfta; u32 bits; u32 vt; + u32 targetbit; + bool vfta_changed = FALSE; DEBUGFUNC("ixgbe_set_vfta_generic"); @@ -2749,6 +2788,7 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, /* * this is a 2 part operation - first the VFTA, then the * VLVF and VLVFB if VT Mode is set + * We don't write the VFTA until we know the VLVF part succeeded. */ /* Part 1 @@ -2759,13 +2799,20 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, */ regindex = (vlan >> 5) & 0x7F; bitindex = vlan & 0x1F; - bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); - if (vlan_on) - bits |= (1 << bitindex); - else - bits &= ~(1 << bitindex); - IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); + targetbit = (1 << bitindex); + vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); + if (vlan_on) { + if (!(vfta & targetbit)) { + vfta |= targetbit; + vfta_changed = TRUE; + } + } else { + if ((vfta & targetbit)) { + vfta &= ~targetbit; + vfta_changed = TRUE; + } + } /* Part 2 * If VT Mode is set @@ -2777,61 +2824,84 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, */ vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); if (vt & IXGBE_VT_CTL_VT_ENABLE) { - if (vlan == 0) { - regindex = 0; - } else { - regindex = ixgbe_find_vlvf_slot(hw, vlan); - if (regindex < 0) - goto out; - } + s32 vlvf_index; + + vlvf_index = ixgbe_find_vlvf_slot(hw, vlan); + if (vlvf_index < 0) + return vlvf_index; if (vlan_on) { /* set the pool bit */ if (vind < 32) { bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex*2)); + IXGBE_VLVFB(vlvf_index*2)); bits |= (1 << vind); IXGBE_WRITE_REG(hw, - IXGBE_VLVFB(regindex*2), + IXGBE_VLVFB(vlvf_index*2), bits); } else { bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); - bits |= (1 << vind); + IXGBE_VLVFB((vlvf_index*2)+1)); + bits |= (1 << (vind-32)); IXGBE_WRITE_REG(hw, - IXGBE_VLVFB((regindex*2)+1), + IXGBE_VLVFB((vlvf_index*2)+1), bits); } } else { /* clear the pool bit */ if (vind < 32) { bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex*2)); + IXGBE_VLVFB(vlvf_index*2)); bits &= ~(1 << vind); IXGBE_WRITE_REG(hw, - IXGBE_VLVFB(regindex*2), + IXGBE_VLVFB(vlvf_index*2), bits); bits |= IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); + IXGBE_VLVFB((vlvf_index*2)+1)); } else { bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); - bits &= ~(1 << vind); + IXGBE_VLVFB((vlvf_index*2)+1)); + bits &= ~(1 << (vind-32)); IXGBE_WRITE_REG(hw, - IXGBE_VLVFB((regindex*2)+1), + IXGBE_VLVFB((vlvf_index*2)+1), bits); bits |= IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex*2)); + IXGBE_VLVFB(vlvf_index*2)); } } - if (bits) - IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), + /* + * If there are still bits set in the VLVFB registers + * for the VLAN ID indicated we need to see if the + * caller is requesting that we clear the VFTA entry bit. + * If the caller has requested that we clear the VFTA + * entry bit but there are still pools/VFs using this VLAN + * ID entry then ignore the request. We're not worried + * about the case where we're turning the VFTA VLAN ID + * entry bit on, only when requested to turn it off as + * there may be multiple pools and/or VFs using the + * VLAN ID entry. In that case we cannot clear the + * VFTA bit until all pools/VFs using that VLAN ID have also + * been cleared. This will be indicated by "bits" being + * zero. + */ + if (bits) { + IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), (IXGBE_VLVF_VIEN | vlan)); + if (!vlan_on) { + /* someone wants to clear the vfta entry + * but some pools/VFs are still using it. + * Ignore it. */ + vfta_changed = FALSE; + } + } else - IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0); + IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); } -out: + + if (vfta_changed) + IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta); + return IXGBE_SUCCESS; } @@ -2869,14 +2939,23 @@ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) * Reads the links register to determine if link is up and the current speed **/ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete) + bool *link_up, bool link_up_wait_to_complete) { - u32 links_reg; + u32 links_reg, links_orig; u32 i; DEBUGFUNC("ixgbe_check_mac_link_generic"); + /* clear the old state */ + links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + + if (links_orig != links_reg) { + DEBUGOUT2("LINKS changed from %08X to %08X\n", + links_orig, links_reg); + } + if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { if (links_reg & IXGBE_LINKS_UP) { diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c index 9bab98d2952..7ec2981d4c2 100644 --- a/sys/dev/ixgbe/ixgbe_phy.c +++ b/sys/dev/ixgbe/ixgbe_phy.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -77,7 +77,8 @@ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw) phy->ops.i2c_bus_clear = &ixgbe_i2c_bus_clear; phy->ops.identify_sfp = &ixgbe_identify_sfp_module_generic; phy->sfp_type = ixgbe_sfp_type_unknown; - + phy->ops.check_overtemp = &ixgbe_tn_check_overtemp; + phy->ops.set_low_power_state = &ixgbe_tn_set_low_power_state; return IXGBE_SUCCESS; } @@ -241,13 +242,19 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) IXGBE_MDIO_PHY_XS_DEV_TYPE, IXGBE_MDIO_PHY_XS_RESET); - /* Poll for reset bit to self-clear indicating reset is complete */ - for (i = 0; i < 500; i++) { - msec_delay(1); + /* + * Poll for reset bit to self-clear indicating reset is complete. + * Some PHYs could take up to 3 seconds to complete and need about + * 1.7 usec delay after the reset is complete. + */ + for (i = 0; i < 30; i++) { + msec_delay(100); hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &ctrl); - if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET)) + if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET)) { + usec_delay(2); break; + } } if (ctrl & IXGBE_MDIO_PHY_XS_RESET) { @@ -922,6 +929,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) u8 comp_codes_10g = 0; u8 oui_bytes[3] = {0, 0, 0}; u8 cable_tech = 0; + u8 cable_spec = 0; u16 enforce_sfp = 0; DEBUGFUNC("ixgbe_identify_sfp_module_generic"); @@ -968,6 +976,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) * 4 SFP_DA_CORE1 - 82599-specific * 5 SFP_SR/LR_CORE0 - 82599-specific * 6 SFP_SR/LR_CORE1 - 82599-specific + * 7 SFP_act_lmt_DA_CORE0 - 82599-specific + * 8 SFP_act_lmt_DA_CORE1 - 82599-specific */ if (hw->mac.type == ixgbe_mac_82598EB) { if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) @@ -979,29 +989,40 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) else hw->phy.sfp_type = ixgbe_sfp_type_unknown; } else if (hw->mac.type == ixgbe_mac_82599EB) { - if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) + if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0; else hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core1; - else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) + } else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) { + hw->phy.ops.read_i2c_eeprom( + hw, IXGBE_SFF_CABLE_SPEC_COMP, + &cable_spec); + if (cable_spec & + IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = + ixgbe_sfp_type_da_act_lmt_core0; + else + hw->phy.sfp_type = + ixgbe_sfp_type_da_act_lmt_core1; + } else + hw->phy.sfp_type = + ixgbe_sfp_type_unknown; + } else if (comp_codes_10g & + (IXGBE_SFF_10GBASESR_CAPABLE | + IXGBE_SFF_10GBASELR_CAPABLE)) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_srlr_core0; else hw->phy.sfp_type = ixgbe_sfp_type_srlr_core1; - else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = - ixgbe_sfp_type_srlr_core0; - else - hw->phy.sfp_type = - ixgbe_sfp_type_srlr_core1; - else + } else { hw->phy.sfp_type = ixgbe_sfp_type_unknown; + } } if (hw->phy.sfp_type != stored_sfp_type) @@ -1036,10 +1057,14 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) switch (vendor_oui) { case IXGBE_SFF_VENDOR_OUI_TYCO: if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) - hw->phy.type = ixgbe_phy_tw_tyco; + hw->phy.type = + ixgbe_phy_sfp_passive_tyco; break; case IXGBE_SFF_VENDOR_OUI_FTL: - hw->phy.type = ixgbe_phy_sfp_ftl; + if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) + hw->phy.type = ixgbe_phy_sfp_ftl_active; + else + hw->phy.type = ixgbe_phy_sfp_ftl; break; case IXGBE_SFF_VENDOR_OUI_AVAGO: hw->phy.type = ixgbe_phy_sfp_avago; @@ -1049,15 +1074,20 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) break; default: if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) - hw->phy.type = ixgbe_phy_tw_unknown; + hw->phy.type = + ixgbe_phy_sfp_passive_unknown; + else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) + hw->phy.type = + ixgbe_phy_sfp_active_unknown; else hw->phy.type = ixgbe_phy_sfp_unknown; break; } } - /* All passive DA cables are supported */ - if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) { + /* Allow any DA cable vendor */ + if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE | + IXGBE_SFF_DA_ACTIVE_CABLE)) { status = IXGBE_SUCCESS; goto out; } @@ -1108,6 +1138,7 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, u16 *data_offset) { u16 sfp_id; + u16 sfp_type = hw->phy.sfp_type; DEBUGFUNC("ixgbe_get_sfp_init_sequence_offsets"); @@ -1121,6 +1152,12 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, (hw->phy.sfp_type == ixgbe_sfp_type_da_cu)) return IXGBE_ERR_SFP_NOT_SUPPORTED; + /* Limiting active cables must be initialized as SR modules */ + if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0) + sfp_type = ixgbe_sfp_type_srlr_core0; + else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1) + sfp_type = ixgbe_sfp_type_srlr_core1; + /* Read offset to PHY init contents */ hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset); @@ -1137,7 +1174,7 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, hw->eeprom.ops.read(hw, *list_offset, &sfp_id); while (sfp_id != IXGBE_PHY_INIT_END_NL) { - if (sfp_id == hw->phy.sfp_type) { + if (sfp_id == sfp_type) { (*list_offset)++; hw->eeprom.ops.read(hw, *list_offset, data_offset); if ((!*data_offset) || (*data_offset == 0xFFFF)) { @@ -1722,3 +1759,56 @@ void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw) /* Put the i2c bus back to default state */ ixgbe_i2c_stop(hw); } + +/** + * ixgbe_check_overtemp - Checks if an overtemp occured. + * @hw: pointer to hardware structure + * + * Checks if the LASI temp alarm status was triggered due to overtemp + **/ +s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw) +{ + s32 status = IXGBE_SUCCESS; + u16 phy_data = 0; + + DEBUGFUNC("ixgbe_tn_check_overtemp"); + + if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM) + goto out; + + /* Check that the LASI temp alarm status was triggered */ + hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_data); + + if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM)) + goto out; + + status = IXGBE_ERR_OVERTEMP; +out: + return status; +} + + +/** + * ixgbe_set_tn_low_power_state - Sets the teranetics phy into low power state + * @hw: pointer to hardware structure + * + * Sets the phy into low power mode when LASI temp alarm status is triggered + **/ +s32 ixgbe_tn_set_low_power_state(struct ixgbe_hw *hw) +{ + s32 status = IXGBE_SUCCESS; + u16 phy_data = 0; + + DEBUGFUNC("ixgbe_set_tn_low_power_state"); + + /* Set the phy into low power mode */ + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_CONTROL_ADDR, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_data); + phy_data |= IXGBE_MDIO_PHY_LOW_POWER_MODE; + hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_PMD_CONTROL_ADDR, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, phy_data); + + return status; +} + diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h index 39f3bc83f0a..8f49aa83e8f 100644 --- a/sys/dev/ixgbe/ixgbe_phy.h +++ b/sys/dev/ixgbe/ixgbe_phy.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -47,9 +47,12 @@ #define IXGBE_SFF_1GBE_COMP_CODES 0x6 #define IXGBE_SFF_10GBE_COMP_CODES 0x3 #define IXGBE_SFF_CABLE_TECHNOLOGY 0x8 +#define IXGBE_SFF_CABLE_SPEC_COMP 0x3C /* Bitmasks */ #define IXGBE_SFF_DA_PASSIVE_CABLE 0x4 +#define IXGBE_SFF_DA_ACTIVE_CABLE 0x8 +#define IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4 #define IXGBE_SFF_1GBASESX_CAPABLE 0x1 #define IXGBE_SFF_1GBASELX_CAPABLE 0x2 #define IXGBE_SFF_10GBASESR_CAPABLE 0x10 @@ -84,6 +87,9 @@ #define IXGBE_I2C_T_SU_STO 4 #define IXGBE_I2C_T_BUF 5 +#define IXGBE_TN_LASI_STATUS_REG 0x9005 +#define IXGBE_TN_LASI_STATUS_TEMP_ALARM 0x0008 + s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw); bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr); @@ -119,6 +125,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw); s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, u16 *list_offset, u16 *data_offset); +s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw); +s32 ixgbe_tn_set_low_power_state(struct ixgbe_hw *hw); s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h index 0b101197709..2e1f0623b42 100644 --- a/sys/dev/ixgbe/ixgbe_type.h +++ b/sys/dev/ixgbe/ixgbe_type.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2009, Intel Corporation + Copyright (c) 2001-2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -57,9 +57,11 @@ #define IXGBE_DEV_ID_82599_KX4 0x10F7 #define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 +#define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC +#define IXGBE_DEV_ID_82599_T3_LOM 0x151C /* General Registers */ #define IXGBE_CTRL 0x00000 @@ -89,7 +91,7 @@ /* General Receive Control */ #define IXGBE_GRC_MNG 0x00000001 /* Manageability Enable */ -#define IXGBE_GRC_APME 0x00000002 /* Advanced Power Management Enable */ +#define IXGBE_GRC_APME 0x00000002 /* APM enabled in EEPROM */ #define IXGBE_VPDDIAG0 0x10204 #define IXGBE_VPDDIAG1 0x10208 @@ -198,6 +200,7 @@ #define IXGBE_RFCTL 0x05008 #define IXGBE_DRECCCTL 0x02F08 #define IXGBE_DRECCCTL_DISABLE 0 + /* Multicast Table Array - 128 entries */ #define IXGBE_MTA(_i) (0x05200 + ((_i) * 4)) #define IXGBE_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ @@ -334,7 +337,7 @@ /* Wake Up Control */ #define IXGBE_WUC_PME_EN 0x00000002 /* PME Enable */ #define IXGBE_WUC_PME_STATUS 0x00000004 /* PME Status */ -#define IXGBE_WUC_ADVD3WUC 0x00000010 /* D3Cold wake up cap. enable*/ +#define IXGBE_WUC_WKEN 0x00000010 /* Enable PE_WAKE_N pin assertion */ /* Wake Up Filter Control */ #define IXGBE_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ @@ -736,6 +739,12 @@ #define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000 #define IXGBE_GCR_CAP_VER2 0x00040000 +#define IXGBE_GCR_EXT_MSIX_EN 0x80000000 +#define IXGBE_GCR_EXT_VT_MODE_16 0x00000001 +#define IXGBE_GCR_EXT_VT_MODE_32 0x00000002 +#define IXGBE_GCR_EXT_VT_MODE_64 0x00000003 +#define IXGBE_GCR_EXT_SRIOV (IXGBE_GCR_EXT_MSIX_EN | \ + IXGBE_GCR_EXT_VT_MODE_64) /* Time Sync Registers */ #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */ #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */ @@ -889,6 +898,8 @@ #define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */ #define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 /* RSC First packet size */ #define IXGBE_RDRXCTL_RSCLLIDIS 0x00800000 /* Disable RSC compl on LLI */ +#define IXGBE_RDRXCTL_RSCACKC 0x02000000 /* must set 1 when RSC enabled */ +#define IXGBE_RDRXCTL_FCOE_WRFIX 0x04000000 /* must set 1 when RSC enabled */ /* RQTC Bit Masks and Shifts */ #define IXGBE_RQTC_SHIFT_TC(_i) ((_i) * 4) @@ -1020,7 +1031,9 @@ #define IXGBE_MDIO_PHY_10GBASET_ABILITY 0x0004 /* 10GBaseT capable */ #define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */ #define IXGBE_MDIO_PHY_100BASETX_ABILITY 0x0080 /* 100BaseTX capable */ +#define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE 0x0800 /* Set low power mode */ +#define IXGBE_MDIO_PMA_PMD_CONTROL_ADDR 0x0000 /* PMA/PMD Control Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */ @@ -1369,10 +1382,12 @@ * EAPOL 802.1x (0x888e): Filter 0 * FCoE (0x8906): Filter 2 * 1588 (0x88f7): Filter 3 + * FIP (0x8914): Filter 4 */ #define IXGBE_ETQF_FILTER_EAPOL 0 #define IXGBE_ETQF_FILTER_FCOE 2 #define IXGBE_ETQF_FILTER_1588 3 +#define IXGBE_ETQF_FILTER_FIP 4 /* VLAN Control Bit Masks */ #define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */ #define IXGBE_VLNCTRL_CFI 0x10000000 /* bit 28 */ @@ -1476,6 +1491,7 @@ #define IXGBE_AUTOC2_10G_XFI (0x1 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_10G_SFI (0x2 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) + /* LINKS Bit Masks */ #define IXGBE_LINKS_KX_AN_COMP 0x80000000 #define IXGBE_LINKS_UP 0x40000000 @@ -1655,6 +1671,8 @@ #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN 0x1 /* Alt. WWN base exists */ /* PCI Bus Info */ +#define IXGBE_PCI_DEVICE_STATUS 0xAA +#define IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING 0x0020 #define IXGBE_PCI_LINK_STATUS 0xB2 #define IXGBE_PCI_DEVICE_CONTROL2 0xC8 #define IXGBE_PCI_LINK_WIDTH 0x3F0 @@ -1787,6 +1805,7 @@ #define IXGBE_MTQC_64Q_1PB 0x0 /* 64 queues 1 pack buffer */ #define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */ #define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */ +#define IXGBE_MTQC_4TC_4TQ 0x8 /* 4 TC if RT_ENA and VT_ENA */ #define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */ /* Receive Descriptor bit definitions */ @@ -2000,10 +2019,9 @@ enum ixgbe_fdir_pballoc_type { #define IXGBE_FDIRM_VLANID 0x00000001 #define IXGBE_FDIRM_VLANP 0x00000002 #define IXGBE_FDIRM_POOL 0x00000004 -#define IXGBE_FDIRM_L3P 0x00000008 -#define IXGBE_FDIRM_L4P 0x00000010 -#define IXGBE_FDIRM_FLEX 0x00000020 -#define IXGBE_FDIRM_DIPv6 0x00000040 +#define IXGBE_FDIRM_L4P 0x00000008 +#define IXGBE_FDIRM_FLEX 0x00000010 +#define IXGBE_FDIRM_DIPv6 0x00000020 #define IXGBE_FDIRFREE_FREE_MASK 0xFFFF #define IXGBE_FDIRFREE_FREE_SHIFT 0 @@ -2218,6 +2236,8 @@ typedef u32 ixgbe_physical_layer; #define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400 #define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800 #define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000 +#define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000 + /* Software ATR hash keys */ #define IXGBE_ATR_BUCKET_HASH_KEY 0xE214AD3D @@ -2258,6 +2278,15 @@ struct ixgbe_atr_input { u8 byte_stream[42]; }; +struct ixgbe_atr_input_masks { + u32 src_ip_mask; + u32 dst_ip_mask; + u16 src_port_mask; + u16 dst_port_mask; + u16 vlan_id_mask; + u16 data_mask; +}; + enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, ixgbe_eeprom_spi, @@ -2281,10 +2310,12 @@ enum ixgbe_phy_type { ixgbe_phy_qt, ixgbe_phy_xaui, ixgbe_phy_nl, - ixgbe_phy_tw_tyco, - ixgbe_phy_tw_unknown, + ixgbe_phy_sfp_passive_tyco, + ixgbe_phy_sfp_passive_unknown, + ixgbe_phy_sfp_active_unknown, ixgbe_phy_sfp_avago, ixgbe_phy_sfp_ftl, + ixgbe_phy_sfp_ftl_active, ixgbe_phy_sfp_unknown, ixgbe_phy_sfp_intel, ixgbe_phy_sfp_unsupported, /*Enforce bit set with unsupported module*/ @@ -2312,6 +2343,8 @@ enum ixgbe_sfp_type { ixgbe_sfp_type_da_cu_core1 = 4, ixgbe_sfp_type_srlr_core0 = 5, ixgbe_sfp_type_srlr_core1 = 6, + ixgbe_sfp_type_da_act_lmt_core0 = 7, + ixgbe_sfp_type_da_act_lmt_core1 = 8, ixgbe_sfp_type_not_present = 0xFFFE, ixgbe_sfp_type_unknown = 0xFFFF }; @@ -2354,25 +2387,25 @@ enum ixgbe_bus_type { /* PCI bus speeds */ enum ixgbe_bus_speed { ixgbe_bus_speed_unknown = 0, - ixgbe_bus_speed_33, - ixgbe_bus_speed_66, - ixgbe_bus_speed_100, - ixgbe_bus_speed_120, - ixgbe_bus_speed_133, - ixgbe_bus_speed_2500, - ixgbe_bus_speed_5000, + ixgbe_bus_speed_33 = 33, + ixgbe_bus_speed_66 = 66, + ixgbe_bus_speed_100 = 100, + ixgbe_bus_speed_120 = 120, + ixgbe_bus_speed_133 = 133, + ixgbe_bus_speed_2500 = 2500, + ixgbe_bus_speed_5000 = 5000, ixgbe_bus_speed_reserved }; /* PCI bus widths */ enum ixgbe_bus_width { ixgbe_bus_width_unknown = 0, - ixgbe_bus_width_pcie_x1, - ixgbe_bus_width_pcie_x2, + ixgbe_bus_width_pcie_x1 = 1, + ixgbe_bus_width_pcie_x2 = 2, ixgbe_bus_width_pcie_x4 = 4, ixgbe_bus_width_pcie_x8 = 8, - ixgbe_bus_width_32, - ixgbe_bus_width_64, + ixgbe_bus_width_32 = 32, + ixgbe_bus_width_64 = 64, ixgbe_bus_width_reserved }; @@ -2503,6 +2536,7 @@ struct ixgbe_mac_operations { s32 (*reset_hw)(struct ixgbe_hw *); s32 (*start_hw)(struct ixgbe_hw *); s32 (*clear_hw_cntrs)(struct ixgbe_hw *); + void (*enable_relaxed_ordering)(struct ixgbe_hw *); enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); u32 (*get_supported_physical_layer)(struct ixgbe_hw *); s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *); @@ -2570,6 +2604,8 @@ struct ixgbe_phy_operations { s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *); s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8); void (*i2c_bus_clear)(struct ixgbe_hw *); + s32 (*check_overtemp)(struct ixgbe_hw *); + s32 (*set_low_power_state)(struct ixgbe_hw *); }; struct ixgbe_eeprom_info { @@ -2580,6 +2616,7 @@ struct ixgbe_eeprom_info { u16 address_bits; }; +#define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01 struct ixgbe_mac_info { struct ixgbe_mac_operations ops; enum ixgbe_mac_type type; @@ -2603,6 +2640,7 @@ struct ixgbe_mac_info { u32 orig_autoc2; bool orig_link_settings_stored; bool autotry_restart; + u8 flags; }; struct ixgbe_phy_info { @@ -2668,6 +2706,8 @@ struct ixgbe_hw { #define IXGBE_ERR_NO_SAN_ADDR_PTR -22 #define IXGBE_ERR_FDIR_REINIT_FAILED -23 #define IXGBE_ERR_EEPROM_VERSION -24 +#define IXGBE_ERR_NO_SPACE -25 +#define IXGBE_ERR_OVERTEMP -26 #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF diff --git a/sys/dev/ofw/ofw_standard.c b/sys/dev/ofw/ofw_standard.c index de18a9e73df..0fda7db8467 100644 --- a/sys/dev/ofw/ofw_standard.c +++ b/sys/dev/ofw/ofw_standard.c @@ -165,7 +165,7 @@ ofw_std_init(ofw_t ofw, void *openfirm) static int ofw_std_test(ofw_t ofw, const char *name) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -187,7 +187,7 @@ static int ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns, unsigned long *returns) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -217,7 +217,7 @@ ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns, static phandle_t ofw_std_peer(ofw_t ofw, phandle_t node) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -239,7 +239,7 @@ ofw_std_peer(ofw_t ofw, phandle_t node) static phandle_t ofw_std_child(ofw_t ofw, phandle_t node) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -261,7 +261,7 @@ ofw_std_child(ofw_t ofw, phandle_t node) static phandle_t ofw_std_parent(ofw_t ofw, phandle_t node) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -283,7 +283,7 @@ ofw_std_parent(ofw_t ofw, phandle_t node) static phandle_t ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -305,7 +305,7 @@ ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance) static ssize_t ofw_std_getproplen(ofw_t ofw, phandle_t package, const char *propname) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -330,7 +330,7 @@ static ssize_t ofw_std_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, size_t buflen) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -359,7 +359,7 @@ static int ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf, size_t size) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -387,7 +387,7 @@ static int ofw_std_setprop(ofw_t ofw, phandle_t package, const char *propname, const void *buf, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -415,7 +415,7 @@ ofw_std_setprop(ofw_t ofw, phandle_t package, const char *propname, static ssize_t ofw_std_canon(ofw_t ofw, const char *device, char *buf, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -441,7 +441,7 @@ ofw_std_canon(ofw_t ofw, const char *device, char *buf, size_t len) static phandle_t ofw_std_finddevice(ofw_t ofw, const char *device) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -463,7 +463,7 @@ ofw_std_finddevice(ofw_t ofw, const char *device) static ssize_t ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -489,7 +489,7 @@ ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) static ssize_t ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -516,7 +516,7 @@ static int ofw_std_call_method(ofw_t ofw, ihandle_t instance, const char *method, int nargs, int nreturns, unsigned long *args_and_returns) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -559,7 +559,7 @@ ofw_std_call_method(ofw_t ofw, ihandle_t instance, const char *method, static ihandle_t ofw_std_open(ofw_t ofw, const char *device) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -581,7 +581,7 @@ ofw_std_open(ofw_t ofw, const char *device) static void ofw_std_close(ofw_t ofw, ihandle_t instance) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -599,7 +599,7 @@ ofw_std_close(ofw_t ofw, ihandle_t instance) static ssize_t ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -626,7 +626,7 @@ ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) static ssize_t ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -652,7 +652,7 @@ ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) static int ofw_std_seek(ofw_t ofw, ihandle_t instance, uint64_t pos) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -682,7 +682,7 @@ ofw_std_seek(ofw_t ofw, ihandle_t instance, uint64_t pos) static caddr_t ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -708,7 +708,7 @@ ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align) static void ofw_std_release(ofw_t ofw, void *virt, size_t size) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -732,7 +732,7 @@ ofw_std_release(ofw_t ofw, void *virt, size_t size) static void ofw_std_enter(ofw_t ofw) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -748,7 +748,7 @@ ofw_std_enter(ofw_t ofw) static void ofw_std_exit(ofw_t ofw) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; diff --git a/sys/dev/ppc/ppc_pci.c b/sys/dev/ppc/ppc_pci.c index c8e40b56377..ed59413ee9c 100644 --- a/sys/dev/ppc/ppc_pci.c +++ b/sys/dev/ppc/ppc_pci.c @@ -89,6 +89,7 @@ static struct pci_id pci_ids[] = { { 0x84031415, "Oxford Semiconductor OX12PCI840 Parallel port", 0x10 }, { 0x95131415, "Oxford Semiconductor OX16PCI954 Parallel port", 0x10 }, { 0x98059710, "NetMos NM9805 1284 Printer port", 0x10 }, + { 0x99019710, "MosChip MCS9901 PCIe to Peripheral Controller", 0x10 }, { 0xffff } }; diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index d0ebfad0071..19801b2e694 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -1071,6 +1071,7 @@ dsp_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, if (IOCGROUP(cmd) == 'M') { if (cmd == OSS_GETVERSION) { *arg_i = SOUND_VERSION; + PCM_GIANT_EXIT(d); return (0); } ret = dsp_ioctl_channel(i_dev, PCM_VOLCH(i_dev), cmd, arg); diff --git a/sys/dev/syscons/scvgarndr.c b/sys/dev/syscons/scvgarndr.c index fd823ce434b..dbee6f200d4 100644 --- a/sys/dev/syscons/scvgarndr.c +++ b/sys/dev/syscons/scvgarndr.c @@ -181,9 +181,17 @@ static u_short mouse_or_mask[16] = { #define vga_drawpxl(pos, color) \ switch (scp->sc->adp->va_info.vi_depth) { \ case 32: \ - case 24: \ writel(pos, vga_palette32[color]); \ break; \ + case 24: \ + if (((pos) & 1) == 0) { \ + writew(pos, vga_palette32[color]); \ + writeb(pos + 2, vga_palette32[color] >> 16);\ + } else { \ + writeb(pos, vga_palette32[color]); \ + writew(pos + 1, vga_palette32[color] >> 8);\ + } \ + break; \ case 16: \ if (scp->sc->adp->va_info.vi_pixel_fsizes[1] == 5)\ writew(pos, vga_palette15[color]); \ diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c index 3c0663ddce5..c8d2d61a670 100644 --- a/sys/dev/usb/controller/ehci_pci.c +++ b/sys/dev/usb/controller/ehci_pci.c @@ -208,6 +208,8 @@ ehci_pci_match(device_t self) return "NVIDIA nForce3 250 USB 2.0 controller"; case 0x005b10de: return "NVIDIA nForce4 USB 2.0 controller"; + case 0x036d10de: + return "NVIDIA nForce MCP55 USB 2.0 controller"; case 0x03f210de: return "NVIDIA nForce MCP61 USB 2.0 controller"; case 0x0aa610de: diff --git a/sys/dev/usb/controller/ohci_pci.c b/sys/dev/usb/controller/ohci_pci.c index 962aacd67ed..b37fc3348aa 100644 --- a/sys/dev/usb/controller/ohci_pci.c +++ b/sys/dev/usb/controller/ohci_pci.c @@ -166,6 +166,8 @@ ohci_pci_match(device_t self) case 0x00d710de: return ("nVidia nForce3 USB Controller"); + case 0x036c10de: + return ("nVidia nForce MCP55 USB Controller"); case 0x03f110de: return ("nVidia nForce MCP61 USB Controller"); case 0x0aa510de: diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index 399cd591b6a..8584f8d505d 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -896,8 +896,7 @@ ukbd_attach(device_t dev) hid_input, 0, &sc->sc_loc_apple_fn, &flags, &temp_id)) { if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_APPLE_FN | - UKBD_FLAG_APPLE_SWAP; + sc->sc_flags |= UKBD_FLAG_APPLE_FN; DPRINTFN(1, "Found Apple FN-key\n"); apple_keys = 1; sc->sc_kbd_id = temp_id; diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c index aa89fdc6011..b829ac1d307 100644 --- a/sys/dev/usb/quirk/usb_quirk.c +++ b/sys/dev/usb/quirk/usb_quirk.c @@ -227,6 +227,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */ + USB_QUIRK(JMICRON, JM20336, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE), @@ -317,6 +318,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(PNY, ATTACHE2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_START_STOP), + USB_QUIRK(PROLIFIC, PL2506, 0x0000, 0xffff, + UQ_MSC_NO_SYNC_CACHE), USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN, USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY), @@ -442,6 +445,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(ACTIONS, MP4, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE), USB_QUIRK(ASUS, GMSC, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(UNKNOWN4, USBMEMSTICK, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), }; #undef USB_QUIRK_VP #undef USB_QUIRK diff --git a/sys/dev/usb/usb_compat_linux.c b/sys/dev/usb/usb_compat_linux.c index b95a4f6f349..fc28a1c5060 100644 --- a/sys/dev/usb/usb_compat_linux.c +++ b/sys/dev/usb/usb_compat_linux.c @@ -435,7 +435,7 @@ usb_submit_urb(struct urb *urb, uint16_t mem_flags) uhe->bsd_xfer[1]) { /* we are ready! */ - TAILQ_INSERT_HEAD(&uhe->bsd_urb_list, urb, bsd_urb_list); + TAILQ_INSERT_TAIL(&uhe->bsd_urb_list, urb, bsd_urb_list); urb->status = -EINPROGRESS; @@ -908,6 +908,7 @@ usb_linux_create_usb_device(struct usb_device *udev, device_t dev) if (p_uhe) { bcopy(ed, &p_uhe->desc, sizeof(p_uhe->desc)); p_uhe->bsd_iface_index = iface_index - 1; + TAILQ_INIT(&p_uhe->bsd_urb_list); p_uhe++; } if (p_uhi) { diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 69fbeafa2a3..e4128515567 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -58,6 +58,7 @@ $FreeBSD$ vendor UNKNOWN1 0x0053 Unknown vendor vendor UNKNOWN2 0x0105 Unknown vendor vendor EGALAX2 0x0123 eGalax, Inc. +vendor UNKNOWN4 0x0204 Unknown vendor vendor HUMAX 0x02ad HUMAX vendor LTS 0x0386 LTS vendor BWCT 0x03da Bernd Walter Computer Technology @@ -1098,6 +1099,7 @@ product BROADCOM BCM2033 0x2033 BCM2033 Bluetooth USB dongle /* Brother Industries products */ product BROTHER HL1050 0x0002 HL-1050 laser printer +product BROTHER MFC8600_9650 0x0100 MFC8600/9650 multifunction device /* Behavior Technology Computer products */ product BTC BTC7932 0x6782 Keyboard with mouse port @@ -1812,6 +1814,7 @@ product JABLOTRON PC60B 0x0001 PC-60B product JATON EDA 0x5704 Ethernet /* JMicron products */ +product JMICRON JM20336 0x2336 USB to SATA Bridge product JMICRON JM20337 0x2338 USB to ATA/ATAPI Bridge /* JVC products */ @@ -2127,6 +2130,7 @@ product MUSTEK 1200UB 0x0006 1200 UB scanner product MUSTEK 1200USBPLUS 0x0007 1200 USB Plus scanner product MUSTEK 1200CUPLUS 0x0008 1200 CU Plus scanner product MUSTEK BEARPAW1200F 0x0010 BearPaw 1200F scanner +product MUSTEK BEARPAW2400TA 0x0218 BearPaw 2400TA scanner product MUSTEK BEARPAW1200TA 0x021e BearPaw 1200TA scanner product MUSTEK 600USB 0x0873 600 USB scanner product MUSTEK MDC800 0xa800 MDC-800 digital camera @@ -2412,6 +2416,7 @@ product PROLIFIC PL2303 0x2303 PL2303 Serial (ATEN/IOGEAR UC232A) product PROLIFIC PL2305 0x2305 Parallel printer product PROLIFIC ATAPI4 0x2307 ATAPI-4 Controller product PROLIFIC PL2501 0x2501 PL2501 Host-Host interface +product PROLIFIC PL2506 0x2506 PL2506 USB to IDE Bridge product PROLIFIC PHAROS 0xaaa0 Prolific Pharos product PROLIFIC RSAQ3 0xaaa2 PL2303 Serial Adapter (IODATA USB-RSAQ3) product PROLIFIC2 WSIM 0x2001 Willcom WSIM @@ -2512,12 +2517,14 @@ product QUALCOMMINC E2003 0x2003 3G modem /* Quanta products */ /* Quanta products */ +product QUANTA RW6815_1 0x00ce HP iPAQ rw6815 product QUANTA RT3070 0x0304 RT3070 product QUANTA Q101 0xea02 HSDPA modem product QUANTA Q111 0xea03 HSDPA modem product QUANTA GLX 0xea04 HSDPA modem product QUANTA GKE 0xea05 HSDPA modem product QUANTA GLE 0xea06 HSDPA modem +product QUANTA RW6815_2 0xf003 HP iPAQ rw6815 /* Qtronix products */ product QTRONIX 980N 0x2011 Scorpion-980N keyboard @@ -2725,6 +2732,7 @@ product SIERRA AIRCARD875 0x6820 Aircard 875 HSDPA product SIERRA TRUINSTALL 0x0fff Aircard Tru Installer /* Sigmatel products */ +product SIGMATEL WBT_3052 0x4200 WBT-3052 IrDA/USB Bridge product SIGMATEL I_BEAD100 0x8008 i-Bead 100 MP3 Player /* SIIG products */ @@ -3023,6 +3031,9 @@ product UMEDIA AR5523_2_NF 0x3206 AR5523 (no firmware) /* Universal Access products */ product UNIACCESS PANACHE 0x0101 Panache Surf USB ISDN Adapter +/* Unknown vendors */ +product UNKNOWN4 USBMEMSTICK 0x6025 Flash Disk CBM + /* U.S. Robotics products */ product USR USR5423 0x0121 USR5423 WLAN diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index 7f27494bb8b..8092a5d4610 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -117,7 +117,7 @@ struct mtx nfs_slock_mutex; /* local functions */ static int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *); -#if defined(__i386__) +#ifdef __NO_STRICT_ALIGNMENT /* * These architectures don't need re-alignment, so just return. */ @@ -127,7 +127,7 @@ newnfs_realign(struct mbuf **pm) return; } -#else +#else /* !__NO_STRICT_ALIGNMENT */ /* * newnfs_realign: * @@ -185,7 +185,7 @@ newnfs_realign(struct mbuf **pm) pm = &m->m_next; } } -#endif /* !__i386__ */ +#endif /* __NO_STRICT_ALIGNMENT */ #ifdef notdef static void diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index ba41780ed98..8ecb5f508b2 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -2443,6 +2443,9 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam, *credp = NULL; exp->nes_numsecflavor = 0; error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); + if (error != 0) + /* Make sure the server replies ESTALE to the client. */ + error = ESTALE; if (nam && !error) { error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, &exp->nes_numsecflavor, &secflavors); diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c index 0b6525e79e8..931b7c30338 100644 --- a/sys/geom/geom_io.c +++ b/sys/geom/geom_io.c @@ -443,7 +443,10 @@ g_io_request(struct bio *bp, struct g_consumer *cp) ("Bio already on queue bp=%p", bp)); bp->bio_flags |= BIO_ONQUEUE; - binuptime(&bp->bio_t0); + if (g_collectstats) + binuptime(&bp->bio_t0); + else + getbinuptime(&bp->bio_t0); /* * The statistics collection is lockless, as such, but we diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 1ef94ead8c5..695b656f21b 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -1461,11 +1461,7 @@ SYSCTL_PROC(_machdep, OID_AUTO, idle, CTLTYPE_STRING | CTLFLAG_RW, 0, 0, * Reset registers to default values on exec. */ void -exec_setregs(td, entry, stack, ps_strings) - struct thread *td; - u_long entry; - u_long stack; - u_long ps_strings; +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *regs = td->td_frame; struct pcb *pcb = td->td_pcb; @@ -1481,7 +1477,7 @@ exec_setregs(td, entry, stack, ps_strings) mtx_unlock_spin(&dt_lock); bzero((char *)regs, sizeof(struct trapframe)); - regs->tf_eip = entry; + regs->tf_eip = imgp->entry_addr; regs->tf_esp = stack; regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T); regs->tf_ss = _udatasel; @@ -1491,7 +1487,7 @@ exec_setregs(td, entry, stack, ps_strings) regs->tf_cs = _ucodesel; /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ - regs->tf_ebx = ps_strings; + regs->tf_ebx = imgp->ps_strings; /* * Reset the hardware debug registers if they were in use. diff --git a/sys/i386/i386/mca.c b/sys/i386/i386/mca.c index 9b9f9451597..8d33b51b96e 100644 --- a/sys/i386/i386/mca.c +++ b/sys/i386/i386/mca.c @@ -60,11 +60,20 @@ static int mca_count; /* Number of records stored. */ SYSCTL_NODE(_hw, OID_AUTO, mca, CTLFLAG_RD, NULL, "Machine Check Architecture"); -static int mca_enabled = 0; +static int mca_enabled = 1; TUNABLE_INT("hw.mca.enabled", &mca_enabled); SYSCTL_INT(_hw_mca, OID_AUTO, enabled, CTLFLAG_RDTUN, &mca_enabled, 0, "Administrative toggle for machine check support"); +static int amd10h_L1TP = 1; +TUNABLE_INT("hw.mca.amd10h_L1TP", &amd10h_L1TP); +SYSCTL_INT(_hw_mca, OID_AUTO, amd10h_L1TP, CTLFLAG_RDTUN, &amd10h_L1TP, 0, + "Administrative toggle for logging of level one TLB parity (L1TP) errors"); + +int workaround_erratum383; +SYSCTL_INT(_hw_mca, OID_AUTO, erratum383, CTLFLAG_RD, &workaround_erratum383, 0, + "Is the workaround for Erratum 383 on AMD Family 10h processors enabled?"); + static STAILQ_HEAD(, mca_internal) mca_records; static struct callout mca_timer; static int mca_ticks = 3600; /* Check hourly by default. */ @@ -527,7 +536,7 @@ void mca_init(void) { uint64_t mcg_cap; - uint64_t ctl; + uint64_t ctl, mask; int skip; int i; @@ -535,6 +544,15 @@ mca_init(void) if (!mca_enabled || !(cpu_feature & CPUID_MCE)) return; + /* + * On AMD Family 10h processors, unless logging of level one TLB + * parity (L1TP) errors is disabled, enable the recommended workaround + * for Erratum 383. + */ + if (cpu_vendor_id == CPU_VENDOR_AMD && + CPUID_TO_FAMILY(cpu_id) == 0x10 && amd10h_L1TP) + workaround_erratum383 = 1; + if (cpu_feature & CPUID_MCA) { if (PCPU_GET(cpuid) == 0) mca_setup(); @@ -545,6 +563,19 @@ mca_init(void) /* Enable MCA features. */ wrmsr(MSR_MCG_CTL, MCG_CTL_ENABLE); + /* + * Disable logging of level one TLB parity (L1TP) errors by + * the data cache as an alternative workaround for AMD Family + * 10h Erratum 383. Unlike the recommended workaround, there + * is no performance penalty to this workaround. However, + * L1TP errors will go unreported. + */ + if (cpu_vendor_id == CPU_VENDOR_AMD && + CPUID_TO_FAMILY(cpu_id) == 0x10 && !amd10h_L1TP) { + mask = rdmsr(MSR_MC0_CTL_MASK); + if ((mask & (1UL << 5)) == 0) + wrmsr(MSR_MC0_CTL_MASK, mask | (1UL << 5)); + } for (i = 0; i < (mcg_cap & MCG_CAP_COUNT); i++) { /* By default enable logging of all errors. */ ctl = 0xffffffffffffffffUL; diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index e9dd20716c1..7c74f00bb2c 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -5,7 +5,7 @@ * All rights reserved. * Copyright (c) 1994 David Greenman * All rights reserved. - * Copyright (c) 2005-2008 Alan L. Cox + * Copyright (c) 2005-2010 Alan L. Cox * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -207,8 +207,8 @@ vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ int pgeflag = 0; /* PG_G or-in */ int pseflag = 0; /* PG_PS or-in */ -static int nkpt; -vm_offset_t kernel_vm_end; +static int nkpt = NKPT; +vm_offset_t kernel_vm_end = KERNBASE + NKPT * NBPDR; extern u_int32_t KERNend; extern u_int32_t KPTphys; @@ -297,6 +297,7 @@ static void pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte); static boolean_t pmap_is_modified_pvh(struct md_page *pvh); static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode); +static void pmap_kenter_pde(vm_offset_t va, pd_entry_t newpde); static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va); static void pmap_pde_attr(pd_entry_t *pde, int cache_bits); static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); @@ -315,6 +316,9 @@ static void pmap_remove_entry(struct pmap *pmap, vm_page_t m, static void pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t m); static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m); +static void pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, + pd_entry_t newpde); +static void pmap_update_pde_invalidate(vm_offset_t va, pd_entry_t newpde); static vm_page_t pmap_allocpte(pmap_t pmap, vm_offset_t va, int flags); @@ -380,11 +384,17 @@ pmap_bootstrap(vm_paddr_t firstaddr) kernel_pmap->pm_active = -1; /* don't allow deactivation */ TAILQ_INIT(&kernel_pmap->pm_pvchunk); LIST_INIT(&allpmaps); + + /* + * Request a spin mutex so that changes to allpmaps cannot be + * preempted by smp_rendezvous_cpus(). Otherwise, + * pmap_update_pde_kernel() could access allpmaps while it is + * being changed. + */ mtx_init(&allpmaps_lock, "allpmaps", NULL, MTX_SPIN); mtx_lock_spin(&allpmaps_lock); LIST_INSERT_HEAD(&allpmaps, kernel_pmap, pm_list); mtx_unlock_spin(&allpmaps_lock); - nkpt = NKPT; /* * Reserve some special page table entries/VA space for temporary @@ -692,19 +702,21 @@ pmap_init(void) pv_entry_high_water = 9 * (pv_entry_max / 10); /* - * Disable large page mappings by default if the kernel is running in - * a virtual machine on an AMD Family 10h processor. This is a work- - * around for Erratum 383. + * If the kernel is running in a virtual machine on an AMD Family 10h + * processor, then it must assume that MCA is enabled by the virtual + * machine monitor. */ if (vm_guest == VM_GUEST_VM && cpu_vendor_id == CPU_VENDOR_AMD && CPUID_TO_FAMILY(cpu_id) == 0x10) - pg_ps_enabled = 0; + workaround_erratum383 = 1; /* - * Are large page mappings enabled? + * Are large page mappings supported and enabled? */ TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled); - if (pg_ps_enabled) { + if (pseflag == 0) + pg_ps_enabled = 0; + else if (pg_ps_enabled) { KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0, ("pmap_init: can't assign to pagesizes[1]")); pagesizes[1] = NBPDR; @@ -850,6 +862,69 @@ pmap_cache_bits(int mode, boolean_t is_pde) cache_bits |= PG_NC_PWT; return (cache_bits); } + +/* + * The caller is responsible for maintaining TLB consistency. + */ +static void +pmap_kenter_pde(vm_offset_t va, pd_entry_t newpde) +{ + pd_entry_t *pde; + pmap_t pmap; + boolean_t PTD_updated; + + PTD_updated = FALSE; + mtx_lock_spin(&allpmaps_lock); + LIST_FOREACH(pmap, &allpmaps, pm_list) { + if ((pmap->pm_pdir[PTDPTDI] & PG_FRAME) == (PTDpde[0] & + PG_FRAME)) + PTD_updated = TRUE; + pde = pmap_pde(pmap, va); + pde_store(pde, newpde); + } + mtx_unlock_spin(&allpmaps_lock); + KASSERT(PTD_updated, + ("pmap_kenter_pde: current page table is not in allpmaps")); +} + +/* + * After changing the page size for the specified virtual address in the page + * table, flush the corresponding entries from the processor's TLB. Only the + * calling processor's TLB is affected. + * + * The calling thread must be pinned to a processor. + */ +static void +pmap_update_pde_invalidate(vm_offset_t va, pd_entry_t newpde) +{ + u_long cr4; + + if ((newpde & PG_PS) == 0) + /* Demotion: flush a specific 2MB page mapping. */ + invlpg(va); + else if ((newpde & PG_G) == 0) + /* + * Promotion: flush every 4KB page mapping from the TLB + * because there are too many to flush individually. + */ + invltlb(); + else { + /* + * Promotion: flush every 4KB page mapping from the TLB, + * including any global (PG_G) mappings. + */ + cr4 = rcr4(); + load_cr4(cr4 & ~CR4_PGE); + /* + * Although preemption at this point could be detrimental to + * performance, it would not lead to an error. PG_G is simply + * ignored if CR4.PGE is clear. Moreover, in case this block + * is re-entered, the load_cr4() either above or below will + * modify CR4.PGE flushing the TLB. + */ + load_cr4(cr4 | CR4_PGE); + } +} #ifdef SMP /* * For SMP, these functions have to use the IPI mechanism for coherence. @@ -946,6 +1021,92 @@ pmap_invalidate_cache(void) smp_cache_flush(); sched_unpin(); } + +struct pde_action { + cpumask_t store; /* processor that updates the PDE */ + cpumask_t invalidate; /* processors that invalidate their TLB */ + vm_offset_t va; + pd_entry_t *pde; + pd_entry_t newpde; +}; + +static void +pmap_update_pde_kernel(void *arg) +{ + struct pde_action *act = arg; + pd_entry_t *pde; + pmap_t pmap; + + if (act->store == PCPU_GET(cpumask)) + /* + * Elsewhere, this operation requires allpmaps_lock for + * synchronization. Here, it does not because it is being + * performed in the context of an all_cpus rendezvous. + */ + LIST_FOREACH(pmap, &allpmaps, pm_list) { + pde = pmap_pde(pmap, act->va); + pde_store(pde, act->newpde); + } +} + +static void +pmap_update_pde_user(void *arg) +{ + struct pde_action *act = arg; + + if (act->store == PCPU_GET(cpumask)) + pde_store(act->pde, act->newpde); +} + +static void +pmap_update_pde_teardown(void *arg) +{ + struct pde_action *act = arg; + + if ((act->invalidate & PCPU_GET(cpumask)) != 0) + pmap_update_pde_invalidate(act->va, act->newpde); +} + +/* + * Change the page size for the specified virtual address in a way that + * prevents any possibility of the TLB ever having two entries that map the + * same virtual address using different page sizes. This is the recommended + * workaround for Erratum 383 on AMD Family 10h processors. It prevents a + * machine check exception for a TLB state that is improperly diagnosed as a + * hardware error. + */ +static void +pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, pd_entry_t newpde) +{ + struct pde_action act; + cpumask_t active, cpumask; + + sched_pin(); + cpumask = PCPU_GET(cpumask); + if (pmap == kernel_pmap) + active = all_cpus; + else + active = pmap->pm_active; + if ((active & PCPU_GET(other_cpus)) != 0) { + act.store = cpumask; + act.invalidate = active; + act.va = va; + act.pde = pde; + act.newpde = newpde; + smp_rendezvous_cpus(cpumask | active, + smp_no_rendevous_barrier, pmap == kernel_pmap ? + pmap_update_pde_kernel : pmap_update_pde_user, + pmap_update_pde_teardown, &act); + } else { + if (pmap == kernel_pmap) + pmap_kenter_pde(va, newpde); + else + pde_store(pde, newpde); + if ((active & cpumask) != 0) + pmap_update_pde_invalidate(va, newpde); + } + sched_unpin(); +} #else /* !SMP */ /* * Normal, non-SMP, 486+ invalidation functions. @@ -983,6 +1144,18 @@ pmap_invalidate_cache(void) wbinvd(); } + +static void +pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, pd_entry_t newpde) +{ + + if (pmap == kernel_pmap) + pmap_kenter_pde(va, newpde); + else + pde_store(pde, newpde); + if (pmap == kernel_pmap || pmap->pm_active) + pmap_update_pde_invalidate(va, newpde); +} #endif /* !SMP */ void @@ -1856,32 +2029,17 @@ SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG|CTLFLAG_RD, void pmap_growkernel(vm_offset_t addr) { - struct pmap *pmap; vm_paddr_t ptppaddr; vm_page_t nkpg; pd_entry_t newpdir; - pt_entry_t *pde; - boolean_t updated_PTD; mtx_assert(&kernel_map->system_mtx, MA_OWNED); - if (kernel_vm_end == 0) { - kernel_vm_end = KERNBASE; - nkpt = 0; - while (pdir_pde(PTD, kernel_vm_end)) { - kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); - nkpt++; - if (kernel_vm_end - 1 >= kernel_map->max_offset) { - kernel_vm_end = kernel_map->max_offset; - break; - } - } - } - addr = roundup2(addr, PAGE_SIZE * NPTEPG); + addr = roundup2(addr, NBPDR); if (addr - 1 >= kernel_map->max_offset) addr = kernel_map->max_offset; while (kernel_vm_end < addr) { if (pdir_pde(PTD, kernel_vm_end)) { - kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); + kernel_vm_end = (kernel_vm_end + NBPDR) & ~PDRMASK; if (kernel_vm_end - 1 >= kernel_map->max_offset) { kernel_vm_end = kernel_map->max_offset; break; @@ -1903,19 +2061,8 @@ pmap_growkernel(vm_offset_t addr) newpdir = (pd_entry_t) (ptppaddr | PG_V | PG_RW | PG_A | PG_M); pdir_pde(KPTD, kernel_vm_end) = pgeflag | newpdir; - updated_PTD = FALSE; - mtx_lock_spin(&allpmaps_lock); - LIST_FOREACH(pmap, &allpmaps, pm_list) { - if ((pmap->pm_pdir[PTDPTDI] & PG_FRAME) == (PTDpde[0] & - PG_FRAME)) - updated_PTD = TRUE; - pde = pmap_pde(pmap, kernel_vm_end); - pde_store(pde, newpdir); - } - mtx_unlock_spin(&allpmaps_lock); - KASSERT(updated_PTD, - ("pmap_growkernel: current page table is not in allpmaps")); - kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); + pmap_kenter_pde(kernel_vm_end, newpdir); + kernel_vm_end = (kernel_vm_end + NBPDR) & ~PDRMASK; if (kernel_vm_end - 1 >= kernel_map->max_offset) { kernel_vm_end = kernel_map->max_offset; break; @@ -2358,7 +2505,6 @@ static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) { pd_entry_t newpde, oldpde; - pmap_t allpmaps_entry; pt_entry_t *firstpte, newpte; vm_paddr_t mptepa; vm_page_t free, mpte; @@ -2464,25 +2610,11 @@ pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) * processor changing the setting of PG_A and/or PG_M between * the read above and the store below. */ - if (pmap == kernel_pmap) { - /* - * A harmless race exists between this loop and the bcopy() - * in pmap_pinit() that initializes the kernel segment of - * the new page table directory. Specifically, that bcopy() - * may copy the new PDE from the PTD to the new page table - * before this loop updates that new page table. - */ - mtx_lock_spin(&allpmaps_lock); - LIST_FOREACH(allpmaps_entry, &allpmaps, pm_list) { - pde = pmap_pde(allpmaps_entry, va); - KASSERT(*pde == newpde || (*pde & PG_PTE_PROMOTE) == - (oldpde & PG_PTE_PROMOTE), - ("pmap_demote_pde: pde was %#jx, expected %#jx", - (uintmax_t)*pde, (uintmax_t)oldpde)); - pde_store(pde, newpde); - } - mtx_unlock_spin(&allpmaps_lock); - } else + if (workaround_erratum383) + pmap_update_pde(pmap, va, pde, newpde); + else if (pmap == kernel_pmap) + pmap_kenter_pde(va, newpde); + else pde_store(pde, newpde); if (firstpte == PADDR2) mtx_unlock(&PMAP2mutex); @@ -3001,7 +3133,6 @@ static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) { pd_entry_t newpde; - pmap_t allpmaps_entry; pt_entry_t *firstpte, oldpte, pa, *pte; vm_offset_t oldpteva; vm_page_t mpte; @@ -3013,7 +3144,7 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) * either invalid, unused, or does not map the first 4KB physical page * within a 2- or 4MB page. */ - firstpte = vtopte(trunc_4mpage(va)); + firstpte = pmap_pte_quick(pmap, trunc_4mpage(va)); setpde: newpde = *firstpte; if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V)) { @@ -3105,14 +3236,11 @@ setpte: /* * Map the superpage. */ - if (pmap == kernel_pmap) { - mtx_lock_spin(&allpmaps_lock); - LIST_FOREACH(allpmaps_entry, &allpmaps, pm_list) { - pde = pmap_pde(allpmaps_entry, va); - pde_store(pde, PG_PS | newpde); - } - mtx_unlock_spin(&allpmaps_lock); - } else + if (workaround_erratum383) + pmap_update_pde(pmap, va, pde, PG_PS | newpde); + else if (pmap == kernel_pmap) + pmap_kenter_pde(va, PG_PS | newpde); + else pde_store(pde, PG_PS | newpde); pmap_pde_promotions++; diff --git a/sys/i386/ibcs2/ibcs2_stat.c b/sys/i386/ibcs2/ibcs2_stat.c index 92530715635..b61e45ef4bf 100644 --- a/sys/i386/ibcs2/ibcs2_stat.c +++ b/sys/i386/ibcs2/ibcs2_stat.c @@ -72,9 +72,9 @@ bsd_stat2ibcs_stat(st, st4) st4->st_size = (ibcs2_off_t)st->st_size; else st4->st_size = -2; - st4->st_atim = (ibcs2_time_t)st->st_atime; - st4->st_mtim = (ibcs2_time_t)st->st_mtime; - st4->st_ctim = (ibcs2_time_t)st->st_ctime; + st4->st_atim = (ibcs2_time_t)st->st_atim.tv_sec; + st4->st_mtim = (ibcs2_time_t)st->st_mtim.tv_sec; + st4->st_ctim = (ibcs2_time_t)st->st_ctim.tv_sec; } static int diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index e2968e9d4fc..44eb8a6e2ab 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -73,6 +73,7 @@ extern int szosigcode; #endif extern uint32_t *vm_page_dump; extern int vm_page_dump_size; +extern int workaround_erratum383; typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); struct thread; diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h index 64a55350391..d2494c72100 100644 --- a/sys/i386/include/specialreg.h +++ b/sys/i386/include/specialreg.h @@ -551,6 +551,7 @@ /* AMD64 MSR's */ #define MSR_EFER 0xc0000080 /* extended features */ #define MSR_K8_UCODE_UPDATE 0xc0010020 /* update microcode */ +#define MSR_MC0_CTL_MASK 0xc0010044 /* VIA ACE crypto featureset: for via_feature_rng */ #define VIA_HAS_RNG 1 /* cpu has RNG */ diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index d614716dcb8..fe84c063ba9 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -178,9 +178,9 @@ struct l_newstat { l_ulong st_size; l_ulong st_blksize; l_ulong st_blocks; - struct l_timespec st_atimespec; - struct l_timespec st_mtimespec; - struct l_timespec st_ctimespec; + struct l_timespec st_atim; + struct l_timespec st_mtim; + struct l_timespec st_ctim; l_ulong __unused4; l_ulong __unused5; }; @@ -194,9 +194,9 @@ struct l_stat { l_ushort st_gid; l_ushort st_rdev; l_long st_size; - struct l_timespec st_atimespec; - struct l_timespec st_mtimespec; - struct l_timespec st_ctimespec; + struct l_timespec st_atim; + struct l_timespec st_mtim; + struct l_timespec st_ctim; l_long st_blksize; l_long st_blocks; l_ulong st_flags; @@ -217,9 +217,9 @@ struct l_stat64 { l_ulong st_blksize; l_ulong st_blocks; l_ulong __pad4; - struct l_timespec st_atimespec; - struct l_timespec st_mtimespec; - struct l_timespec st_ctimespec; + struct l_timespec st_atim; + struct l_timespec st_mtim; + struct l_timespec st_ctim; l_ulonglong st_ino; }; diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 069b5bb8572..3f0c6f4100e 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -105,8 +105,8 @@ static int elf_linux_fixup(register_t **stack_base, static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params); static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); -static void exec_linux_setregs(struct thread *td, u_long entry, - u_long stack, u_long ps_strings); +static void exec_linux_setregs(struct thread *td, + struct image_params *imgp, u_long stack); static register_t *linux_copyout_strings(struct image_params *imgp); static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel); @@ -927,12 +927,11 @@ exec_linux_imgact_try(struct image_params *imgp) * override the exec_setregs default(s) here. */ static void -exec_linux_setregs(struct thread *td, u_long entry, - u_long stack, u_long ps_strings) +exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct pcb *pcb = td->td_pcb; - exec_setregs(td, entry, stack, ps_strings); + exec_setregs(td, imgp, stack); /* Linux sets %gs to 0, we default to _udatasel */ pcb->pcb_gs = 0; diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC index 1df2e00829c..9b53bf3f1f7 100644 --- a/sys/ia64/conf/GENERIC +++ b/sys/ia64/conf/GENERIC @@ -20,20 +20,21 @@ # # $FreeBSD$ -cpu ITANIUM +cpu ITANIUM2 ident GENERIC makeoptions DEBUG=-g # Build kernel with debug information. options AUDIT # Security event auditing options CD9660 # ISO 9660 Filesystem -options COMPAT_FREEBSD6 # Compatible with FreeBSD6 options COMPAT_FREEBSD7 # Compatible with FreeBSD7 options DDB # Support DDB options DEADLKRES # Enable the deadlock resolver options FFS # Berkeley Fast Filesystem +options FLOWTABLE # per-cpu routing cache options GDB # Support remote GDB options GEOM_LABEL # Provides labelization +options INCLUDE_CONFIG_FILE # Include this file in kernel options INET # InterNETworking options INET6 # IPv6 communications protocols options INVARIANTS # Enable calls of extra sanity checking @@ -44,9 +45,11 @@ options MAC # TrustedBSD MAC Framework options MD_ROOT # MD usable as root device options MSDOSFS # MSDOS Filesystem options NFSCLIENT # Network Filesystem Client -options NFSSERVER # Network Filesystem Server options NFSLOCKD # Network Lock Manager +options NFSSERVER # Network Filesystem Server options NFS_ROOT # NFS usable as root device +options P1003_1B_SEMAPHORES # POSIX-style semaphores +options PREEMPTION # Enable kernel thread preemption options PRINTF_BUFR_SIZE=128 # Printf buffering to limit interspersion options PROCFS # Process filesystem (/proc) options PSEUDOFS # Pseudo-filesystem framework @@ -59,15 +62,12 @@ options STACK # stack(9) support options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options SYSVSHM # SYSV-style shared memory -options P1003_1B_SEMAPHORES # POSIX-style semaphores options UFS_ACL # Support for access control lists options UFS_DIRHASH # Hash-based directory lookup scheme options UFS_GJOURNAL # Enable gjournal-based UFS journaling options WITNESS # Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B RT extensions -options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) -options INCLUDE_CONFIG_FILE # Include this file in kernel # Various "busses" device firewire # FireWire bus code @@ -81,20 +81,25 @@ device ata # ATA controller device atadisk # ATA disk drives device atapicd # ATAPI CDROM drives device atapifd # ATAPI floppy drives +device atapist # ATAPI tape drives device ataraid # ATA RAID drives # SCSI Controllers device ahc # AHA2940 and AIC7xxx devices device ahd # AHA39320/29320 and AIC79xx devices +device hptiop # Highpoint RocketRaid 3xxx series device isp # Qlogic family device mpt # LSI-Logic MPT-Fusion device sym # NCR/Symbios Logic # RAID controllers interfaced to the SCSI subsystem +device amr # AMI MegaRAID device ciss # Compaq Smart RAID 5* device dpt # DPT Smartcache III, IV device iir # Intel Integrated RAID +device ips # IBM (Adaptec) ServeRAID device mly # Mylex AcceleRAID/eXtremeRAID +device twa # 3ware 9000 series PATA/SATA RAID # SCSI peripherals device cd # CD-ROM, DVD-ROM etc. @@ -107,7 +112,6 @@ device ses # Environmental Services (and SAF-TE) # RAID controllers device aac # Adaptec FSA RAID device aacp # SCSI passthrough for aac (requires CAM) -device amr # AMI MegaRAID device ida # Compaq Smart RAID device mlx # Mylex DAC960 family @@ -123,34 +127,58 @@ device ums # Mouse # PCI Ethernet NICs. device de # DEC/Intel DC21x4x (``Tulip'') -device em # Intel PRO/1000 adapter Gigabit Ethernet Card -device le # AMD Am7900 LANCE and Am79C9xx PCnet +device em # Intel PRO/1000 Gigabit Ethernet Family +device igb # Intel PRO/1000 PCIE Server Gigabit Family +device ixgbe # Intel PRO/10GbE PCIE Ethernet Family device txp # 3Com 3cR990 (``Typhoon'') -device vx # 3Com 3c590, 3c595 (``Vortex'') # PCI Ethernet NICs that use the common MII bus controller code. +device ae # Attansic/Atheros L2 FastEthernet +device age # Attansic/Atheros L1 Gigabit Ethernet +device alc # Atheros AR8131/AR8132 Ethernet +device ale # Atheros AR8121/AR8113/AR8114 Ethernet +device bce # Broadcom BCM5706/BCM5708 Gigabit Ethernet +device bfe # Broadcom BCM440x 10/100 Ethernet device bge # Broadcom BCM570xx Gigabit Ethernet -device dc # DEC/Intel 21143 and various workalikes +device et # Agere ET1310 10/100/Gigabit Ethernet +device jme # JMicron JMC250 Gigabit/JMC260 Fast Ethernet +device msk # Marvell/SysKonnect Yukon II Gigabit Ethernet +device nge # NatSemi DP83820 gigabit Ethernet device fxp # Intel EtherExpress PRO/100B (82557, 82558) -device pcn # AMD Am79C97x PCI 10/100 (precedence over 'le') device re # RealTek 8139C+/8169/8169S/8110S -device rl # RealTek 8129/8139 device sf # Adaptec AIC-6915 (``Starfire'') -device sis # Silicon Integrated Systems SiS 900/SiS 7016 +device sk # SysKonnect SK-984x & SK-982x gigabit Ethernet +device ste # Sundance ST201 (D-Link DFE-550TX) +device stge # Sundance/Tamarack TC9021 gigabit Ethernet +device tx # SMC EtherPower II (83c170 ``EPIC'') +device vge # VIA VT612x gigabit Ethernet device xl # 3Com 3c90x ("Boomerang", "Cyclone") # USB Ethernet device aue # ADMtek USB Ethernet +device axe # ASIX Electronics USB Ethernet device cdce # Generic USB over Ethernet device cue # CATC USB Ethernet device kue # Kawasaki LSI USB Ethernet +device rue # RealTek RTL8150 USB Ethernet +device udav # Davicom DM9601E USB + +# USB Serial +device uark # Technologies ARK3116 based serial adapters +device ubsa # Belkin F5U103 and compatible serial adapters +device uftdi # For FTDI usb serial adapters +device uipaq # Some WinCE based devices +device uplcom # Prolific PL-2303 serial adapters +device uslcom # SI Labs CP2101/CP2102 serial adapters +device uvisor # Visor and Palm devices +device uvscom # USB serial support for DDI pocket's PHS # FireWire support +device fwip # IP over FireWire (RFC 2734,3146) device sbp # SCSI over FireWire (need scbus & da) # Various (pseudo) devices device ether # Ethernet support -device vlan # 802.1Q VLAN support device faith # IPv6-to-IPv4 relaying (translation) device gif # IPv6 and IPv4 tunneling device loop # Network loopback @@ -160,6 +188,7 @@ device puc # Multi I/O cards and multi-channel UARTs device random # Entropy device device tun # Packet tunnel. device uart # Serial port (UART) +device vlan # 802.1Q VLAN support device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/sys/ia64/ia32/ia32_signal.c b/sys/ia64/ia32/ia32_signal.c index a981c8444cd..e5eee411ccd 100644 --- a/sys/ia64/ia32/ia32_signal.c +++ b/sys/ia64/ia32/ia32_signal.c @@ -120,7 +120,7 @@ freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) void -ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *tf = td->td_frame; vm_offset_t gdt, ldt; @@ -129,7 +129,7 @@ ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) struct segment_descriptor desc; struct vmspace *vmspace = td->td_proc->p_vmspace; - exec_setregs(td, entry, stack, ps_strings); + exec_setregs(td, imgp, stack); /* Non-syscall frames are cleared by exec_setregs() */ if (tf->tf_flags & FRAME_SYSCALL) { diff --git a/sys/ia64/ia64/autoconf.c b/sys/ia64/ia64/autoconf.c index 5a380516320..cf073c83509 100644 --- a/sys/ia64/ia64/autoconf.c +++ b/sys/ia64/ia64/autoconf.c @@ -39,15 +39,9 @@ #include #include -#include #include - -#include -#include -#include -#include -#include -#include +#include +#include static void configure_first(void *); static void configure(void *); @@ -97,12 +91,9 @@ static void configure_final(void *dummy) { - /* - * Now we're ready to handle (pending) interrupts. - * XXX this is slightly misplaced. - */ - enable_intr(); - cninit_finish(); + + ia64_enable_intr(); + cold = 0; } diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c index 2e7f2d87972..33dbb2e3c1e 100644 --- a/sys/ia64/ia64/clock.c +++ b/sys/ia64/ia64/clock.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include SYSCTL_NODE(_debug, OID_AUTO, clock, CTLFLAG_RW, 0, "clock statistics"); @@ -91,60 +92,63 @@ ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf) int count; PCPU_INC(md.stats.pcs_nclks); - intrcnt[INTRCNT_CLOCK]++; - itc = ia64_get_itc(); + if (PCPU_GET(cpuid) == 0) { + /* + * Clock processing on the BSP. + */ + intrcnt[INTRCNT_CLOCK]++; - adj = PCPU_GET(md.clockadj); - clk = PCPU_GET(md.clock); + itc = ia64_get_itc(); - delta = itc - clk; - count = 0; - while (delta >= ia64_clock_reload) { - /* Only the BSP runs the real clock */ - if (PCPU_GET(cpuid) == 0) + adj = PCPU_GET(md.clockadj); + clk = PCPU_GET(md.clock); + + delta = itc - clk; + count = 0; + while (delta >= ia64_clock_reload) { +#ifdef SMP + ipi_all_but_self(ia64_clock_xiv); +#endif hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - else - hardclock_cpu(TRAPF_USERMODE(tf)); + if (profprocs != 0) + profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); + statclock(TRAPF_USERMODE(tf)); + delta -= ia64_clock_reload; + clk += ia64_clock_reload; + if (adj != 0) + adjust_ticks++; + count++; + } + ia64_set_itm(ia64_get_itc() + ia64_clock_reload - adj); + ia64_srlz_d(); + if (count > 0) { + adjust_lost += count - 1; + if (delta > (ia64_clock_reload >> 3)) { + if (adj == 0) + adjust_edges++; + adj = ia64_clock_reload >> 4; + } else + adj = 0; + } else { + adj = 0; + adjust_excess++; + } + PCPU_SET(md.clock, clk); + PCPU_SET(md.clockadj, adj); + } else { + /* + * Clock processing on the BSP. + */ + hardclock_cpu(TRAPF_USERMODE(tf)); if (profprocs != 0) profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); statclock(TRAPF_USERMODE(tf)); - delta -= ia64_clock_reload; - clk += ia64_clock_reload; - if (adj != 0) - adjust_ticks++; - count++; } - ia64_set_itm(ia64_get_itc() + ia64_clock_reload - adj); - ia64_srlz_d(); - if (count > 0) { - adjust_lost += count - 1; - if (delta > (ia64_clock_reload >> 3)) { - if (adj == 0) - adjust_edges++; - adj = ia64_clock_reload >> 4; - } else - adj = 0; - } else { - adj = 0; - adjust_excess++; - } - PCPU_SET(md.clock, clk); - PCPU_SET(md.clockadj, adj); + return (0); } -void -pcpu_initclock(void) -{ - - PCPU_SET(md.clockadj, 0); - PCPU_SET(md.clock, ia64_get_itc()); - ia64_set_itm(PCPU_GET(md.clock) + ia64_clock_reload); - ia64_set_itv(ia64_clock_xiv); - ia64_srlz_d(); -} - /* * Start the real-time and statistics clocks. We use ar.itc and cr.itm * to implement a 1000hz clock. @@ -154,7 +158,7 @@ cpu_initclocks() { u_long itc_freq; - ia64_clock_xiv = ia64_xiv_alloc(PI_REALTIME, IA64_XIV_IRQ, + ia64_clock_xiv = ia64_xiv_alloc(PI_REALTIME, IA64_XIV_IPI, ia64_ih_clock); if (ia64_clock_xiv == 0) panic("No XIV for clock interrupts"); @@ -169,7 +173,11 @@ cpu_initclocks() tc_init(&ia64_timecounter); #endif - pcpu_initclock(); + PCPU_SET(md.clockadj, 0); + PCPU_SET(md.clock, ia64_get_itc()); + ia64_set_itm(PCPU_GET(md.clock) + ia64_clock_reload); + ia64_set_itv(ia64_clock_xiv); + ia64_srlz_d(); } void diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c index 3376111fd16..adb16ece9d5 100644 --- a/sys/ia64/ia64/interrupt.c +++ b/sys/ia64/ia64/interrupt.c @@ -122,7 +122,7 @@ ia64_xiv_reserve(u_int xiv, enum ia64_xiv_use what, ia64_ihtype ih) return (EBUSY); ia64_xiv[xiv] = what; ia64_handler[xiv] = (ih == NULL) ? ia64_ih_invalid: ih; - if (1 || bootverbose) + if (bootverbose) printf("XIV %u: use=%u, IH=%p\n", xiv, what, ih); return (0); } @@ -139,7 +139,7 @@ ia64_xiv_alloc(u_int prio, enum ia64_xiv_use what, ia64_ihtype ih) xiv0 = IA64_NXIVS - (hwprio + 1) * 16; - KASSERT(xiv0 > IA64_MIN_XIV, ("%s: min XIV", __func__)); + KASSERT(xiv0 >= IA64_MIN_XIV, ("%s: min XIV", __func__)); KASSERT(xiv0 < IA64_NXIVS, ("%s: max XIV", __func__)); xiv = xiv0; @@ -280,6 +280,27 @@ ia64_teardown_intr(void *cookie) return (intr_event_remove_handler(cookie)); } +void +ia64_bind_intr(void) +{ + struct ia64_intr *i; + struct pcpu *pc; + u_int xiv; + int cpu; + + cpu = MAXCPU; + for (xiv = IA64_NXIVS - 1; xiv >= IA64_MIN_XIV; xiv--) { + if (ia64_xiv[xiv] != IA64_XIV_IRQ) + continue; + i = ia64_intrs[xiv]; + do { + cpu = (cpu == 0) ? MAXCPU - 1 : cpu - 1; + pc = cpuid_to_pcpu[cpu]; + } while (pc == NULL || !pc->pc_md.awake); + sapic_bind_intr(i->irq, pc); + } +} + /* * Interrupt handlers. */ @@ -318,9 +339,9 @@ ia64_handle_intr(struct trapframe *tf) out: if (TRAPF_USERMODE(tf)) { while (td->td_flags & (TDF_ASTPENDING|TDF_NEEDRESCHED)) { - enable_intr(); + ia64_enable_intr(); ast(tf); - disable_intr(); + ia64_disable_intr(); } } } diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index ec3d612ebac..c13adc3181b 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -1328,7 +1328,7 @@ set_mcontext(struct thread *td, const mcontext_t *mc) * Clear registers on exec. */ void -exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *tf; uint64_t *ksttop, *kst; @@ -1366,7 +1366,7 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) *kst-- = 0; if (((uintptr_t)kst & 0x1ff) == 0x1f8) *kst-- = 0; - *kst-- = ps_strings; + *kst-- = imgp->ps_strings; if (((uintptr_t)kst & 0x1ff) == 0x1f8) *kst-- = 0; *kst = stack; @@ -1381,11 +1381,11 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) * Assumes that (bspstore & 0x1f8) < 0x1e0. */ suword((caddr_t)tf->tf_special.bspstore - 24, stack); - suword((caddr_t)tf->tf_special.bspstore - 16, ps_strings); + suword((caddr_t)tf->tf_special.bspstore - 16, imgp->ps_strings); suword((caddr_t)tf->tf_special.bspstore - 8, 0); } - tf->tf_special.iip = entry; + tf->tf_special.iip = imgp->entry_addr; tf->tf_special.sp = (stack & ~15) - 16; tf->tf_special.rsc = 0xf; tf->tf_special.fpsr = IA64_FPSR_DEFAULT; diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index 05a655d8aec..600803a74b4 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -206,12 +206,11 @@ ia64_ap_startup(void) CTR1(KTR_SMP, "SMP: cpu%d launched", PCPU_GET(cpuid)); - /* kick off the clock on this AP */ - pcpu_initclock(); - + /* Mask interval timer interrupts on APs. */ + ia64_set_itv(0x10000); ia64_set_tpr(0); ia64_srlz_d(); - enable_intr(); + ia64_enable_intr(); sched_throw(NULL); /* NOTREACHED */ @@ -383,6 +382,12 @@ cpu_mp_unleash(void *dummy) smp_active = 1; smp_started = 1; + + /* + * Now that all CPUs are up and running, bind interrupts to each of + * them. + */ + ia64_bind_intr(); } /* diff --git a/sys/ia64/ia64/nexus.c b/sys/ia64/ia64/nexus.c index 69f62a9b2fb..9885b747aa2 100644 --- a/sys/ia64/ia64/nexus.c +++ b/sys/ia64/ia64/nexus.c @@ -50,13 +50,13 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -73,7 +73,6 @@ static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); struct nexus_device { struct resource_list nx_resources; - int nx_pcibus; }; #define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) @@ -87,8 +86,6 @@ static device_t nexus_add_child(device_t bus, int order, const char *name, int unit); static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); -static int nexus_read_ivar(device_t, device_t, int, uintptr_t *); -static int nexus_write_ivar(device_t, device_t, int, uintptr_t); static int nexus_activate_resource(device_t, device_t, int, int, struct resource *); static int nexus_deactivate_resource(device_t, device_t, int, int, @@ -105,6 +102,7 @@ static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); static int nexus_get_resource(device_t, device_t, int, int, u_long *, u_long *); static void nexus_delete_resource(device_t, device_t, int, int); +static int nexus_bind_intr(device_t, device_t, struct resource *, int); static int nexus_config_intr(device_t, int, enum intr_trigger, enum intr_polarity); @@ -123,8 +121,6 @@ static device_method_t nexus_methods[] = { /* Bus interface */ DEVMETHOD(bus_print_child, nexus_print_child), DEVMETHOD(bus_add_child, nexus_add_child), - DEVMETHOD(bus_read_ivar, nexus_read_ivar), - DEVMETHOD(bus_write_ivar, nexus_write_ivar), DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_release_resource, nexus_release_resource), DEVMETHOD(bus_activate_resource, nexus_activate_resource), @@ -135,6 +131,7 @@ static device_method_t nexus_methods[] = { DEVMETHOD(bus_set_resource, nexus_set_resource), DEVMETHOD(bus_get_resource, nexus_get_resource), DEVMETHOD(bus_delete_resource, nexus_delete_resource), + DEVMETHOD(bus_bind_intr, nexus_bind_intr), DEVMETHOD(bus_config_intr, nexus_config_intr), /* Clock interface */ @@ -215,8 +212,6 @@ nexus_print_child(device_t bus, device_t child) retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); - if (ndev->nx_pcibus != -1) - retval += printf(" pcibus %d", ndev->nx_pcibus); if (device_get_flags(child)) retval += printf(" flags %#x", device_get_flags(child)); retval += printf(" on motherboard\n"); /* XXX "motherboard", ick */ @@ -234,7 +229,6 @@ nexus_add_child(device_t bus, int order, const char *name, int unit) if (!ndev) return(0); resource_list_init(&ndev->nx_resources); - ndev->nx_pcibus = -1; child = device_add_child_ordered(bus, order, name, unit); @@ -244,37 +238,6 @@ nexus_add_child(device_t bus, int order, const char *name, int unit) return(child); } -static int -nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct nexus_device *ndev = DEVTONX(child); - - switch (which) { - case NEXUS_IVAR_PCIBUS: - *result = ndev->nx_pcibus; - break; - default: - return ENOENT; - } - return 0; -} - - -static int -nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) -{ - struct nexus_device *ndev = DEVTONX(child); - - switch (which) { - case NEXUS_IVAR_PCIBUS: - ndev->nx_pcibus = value; - break; - default: - return ENOENT; - } - return 0; -} - /* * Allocate a resource on behalf of child. NB: child is usually going to be a @@ -501,6 +464,17 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, return (sapic_config_intr(irq, trig, pol)); } +static int +nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) +{ + struct pcpu *pc; + + pc = cpuid_to_pcpu[cpu]; + if (pc == NULL) + return (EINVAL); + return (sapic_bind_intr(rman_get_start(irq), pc)); +} + static int nexus_gettime(device_t dev, struct timespec *ts) { diff --git a/sys/ia64/ia64/sapic.c b/sys/ia64/ia64/sapic.c index cb8a1c305ea..5aa14493e77 100644 --- a/sys/ia64/ia64/sapic.c +++ b/sys/ia64/ia64/sapic.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -171,6 +172,26 @@ sapic_lookup(u_int irq, u_int *vecp) } +int +sapic_bind_intr(u_int irq, struct pcpu *pc) +{ + struct sapic_rte rte; + struct sapic *sa; + + sa = sapic_lookup(irq, NULL); + if (sa == NULL) + return (EINVAL); + + mtx_lock_spin(&sa->sa_mtx); + sapic_read_rte(sa, irq - sa->sa_base, &rte); + rte.rte_destination_id = (pc->pc_md.lid >> 24) & 255; + rte.rte_destination_eid = (pc->pc_md.lid >> 16) & 255; + rte.rte_delivery_mode = SAPIC_DELMODE_FIXED; + sapic_write_rte(sa, irq - sa->sa_base, &rte); + mtx_unlock_spin(&sa->sa_mtx); + return (0); +} + int sapic_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol) { diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c index 62644622d79..f539097c265 100644 --- a/sys/ia64/ia64/trap.c +++ b/sys/ia64/ia64/trap.c @@ -334,11 +334,11 @@ int do_ast(struct trapframe *tf) { - disable_intr(); + ia64_disable_intr(); while (curthread->td_flags & (TDF_ASTPENDING|TDF_NEEDRESCHED)) { - enable_intr(); + ia64_enable_intr(); ast(tf); - disable_intr(); + ia64_disable_intr(); } /* * Keep interrupts disabled. We return r10 as a favor to the EPC diff --git a/sys/ia64/include/acpica_machdep.h b/sys/ia64/include/acpica_machdep.h index 26191c0a527..38efffdfd79 100644 --- a/sys/ia64/include/acpica_machdep.h +++ b/sys/ia64/include/acpica_machdep.h @@ -56,8 +56,8 @@ #define ACPI_ASM_MACROS #define BREAKPOINT3 -#define ACPI_DISABLE_IRQS() disable_intr() -#define ACPI_ENABLE_IRQS() enable_intr() +#define ACPI_DISABLE_IRQS() ia64_disable_intr() +#define ACPI_ENABLE_IRQS() ia64_enable_intr() #define ACPI_FLUSH_CPU_CACHE() /* XXX ia64_fc()? */ diff --git a/sys/ia64/include/cpufunc.h b/sys/ia64/include/cpufunc.h index 9ae06a2253d..925d4bafa4a 100644 --- a/sys/ia64/include/cpufunc.h +++ b/sys/ia64/include/cpufunc.h @@ -56,13 +56,13 @@ breakpoint(void) static __inline void -disable_intr(void) +ia64_disable_intr(void) { __asm __volatile ("rsm psr.i"); } static __inline void -enable_intr(void) +ia64_enable_intr(void) { __asm __volatile ("ssm psr.i;; srlz.d"); } @@ -71,8 +71,9 @@ static __inline register_t intr_disable(void) { register_t psr; + __asm __volatile ("mov %0=psr;;" : "=r"(psr)); - disable_intr(); + ia64_disable_intr(); return ((psr & IA64_PSR_I) ? 1 : 0); } @@ -80,7 +81,7 @@ static __inline void intr_restore(register_t ie) { if (ie) - enable_intr(); + ia64_enable_intr(); } #endif /* __GNUCLIKE_ASM */ diff --git a/sys/ia64/include/intr.h b/sys/ia64/include/intr.h index b26190c52fd..81603cfabfd 100644 --- a/sys/ia64/include/intr.h +++ b/sys/ia64/include/intr.h @@ -35,6 +35,7 @@ #define IA64_MAX_HWPRIO 14 +struct pcpu; struct sapic; struct thread; struct trapframe; @@ -65,6 +66,7 @@ typedef u_int (ia64_ihtype)(struct thread *, u_int, struct trapframe *); extern struct ia64_pib *ia64_pib; +void ia64_bind_intr(void); void ia64_handle_intr(struct trapframe *); int ia64_setup_intr(const char *, int, driver_filter_t, driver_intr_t, void *, enum intr_type, void **); @@ -75,6 +77,7 @@ u_int ia64_xiv_alloc(u_int, enum ia64_xiv_use, ia64_ihtype); int ia64_xiv_free(u_int, enum ia64_xiv_use); int ia64_xiv_reserve(u_int, enum ia64_xiv_use, ia64_ihtype); +int sapic_bind_intr(u_int, struct pcpu *); int sapic_config_intr(u_int, enum intr_trigger, enum intr_polarity); struct sapic *sapic_create(u_int, u_int, uint64_t); int sapic_enable(struct sapic *, u_int, u_int); diff --git a/sys/ia64/include/nexusvar.h b/sys/ia64/include/nexusvar.h deleted file mode 100644 index be38f33a075..00000000000 --- a/sys/ia64/include/nexusvar.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 2000 Peter Wemm - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _MACHINE_NEXUSVAR_H_ -#define _MACHINE_NEXUSVAR_H_ 1 - -enum nexus_device_ivars { - NEXUS_IVAR_PCIBUS -}; - -#define NEXUS_ACCESSOR(var, ivar, type) \ - __BUS_ACCESSOR(nexus, var, NEXUS, ivar, type) - -NEXUS_ACCESSOR(pcibus, PCIBUS, u_int32_t) - -#undef NEXUS_ACCESSOR - -#endif /* !_MACHINE_NEXUSVAR_H_ */ diff --git a/sys/ia64/include/pcpu.h b/sys/ia64/include/pcpu.h index 9eb8efba017..3c6e6a762af 100644 --- a/sys/ia64/include/pcpu.h +++ b/sys/ia64/include/pcpu.h @@ -91,8 +91,6 @@ __curthread(void) #define PCPU_PTR(member) (&pcpup->pc_ ## member) #define PCPU_SET(member,value) (pcpup->pc_ ## member = (value)) -void pcpu_initclock(void); - #endif /* _KERNEL */ #endif /* !_MACHINE_PCPU_H_ */ diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 0fffb9fb4c9..236894f4b2d 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -832,13 +832,8 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) phdr[i].p_vaddr + et_dyn_addr - seg_addr); /* - * Is this .text or .data? We can't use - * VM_PROT_WRITE or VM_PROT_EXEC, it breaks the - * alpha terribly and possibly does other bad - * things so we stick to the old way of figuring - * it out: If the segment contains the program - * entry point, it's a text segment, otherwise it - * is a data segment. + * Make the largest executable segment the official + * text segment and all others data. * * Note that obreak() assumes that data_addr + * data_size == end of data load area, and the ELF @@ -846,12 +841,10 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * address. If multiple data segments exist, the * last one will be used. */ - if (hdr->e_entry >= phdr[i].p_vaddr && - hdr->e_entry < (phdr[i].p_vaddr + - phdr[i].p_memsz)) { + + if (phdr[i].p_flags & PF_X && text_size < seg_size) { text_size = seg_size; text_addr = seg_addr; - entry = (u_long)hdr->e_entry + et_dyn_addr; } else { data_size = seg_size; data_addr = seg_addr; @@ -871,6 +864,8 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) data_size = text_size; } + entry = (u_long)hdr->e_entry + et_dyn_addr; + /* * Check limits. It should be safe to check the * limits after loading the segments since we do @@ -948,6 +943,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) imgp->auxargs = elf_auxargs; imgp->interpreted = 0; + imgp->reloc_base = addr; imgp->proc->p_osrel = osrel; return (error); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index dce624d484b..ed22519f693 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -372,6 +372,7 @@ do_execve(td, args, mac_p) imgp->execlabel = NULL; imgp->attr = &attr; imgp->entry_addr = 0; + imgp->reloc_base = 0; imgp->vmspace_destroyed = 0; imgp->interpreted = 0; imgp->opened = 0; @@ -799,11 +800,10 @@ interpret: /* Set values passed into the program in registers. */ if (p->p_sysent->sv_setregs) - (*p->p_sysent->sv_setregs)(td, imgp->entry_addr, - (u_long)(uintptr_t)stack_base, imgp->ps_strings); + (*p->p_sysent->sv_setregs)(td, imgp, + (u_long)(uintptr_t)stack_base); else - exec_setregs(td, imgp->entry_addr, - (u_long)(uintptr_t)stack_base, imgp->ps_strings); + exec_setregs(td, imgp, (u_long)(uintptr_t)stack_base); vfs_mark_atime(imgp->vp, td->td_ucred); @@ -1260,7 +1260,7 @@ exec_copyout_strings(imgp) * Fill in "ps_strings" struct for ps, w, etc. */ suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); - suword(&arginfo->ps_nargvstr, argc); + suword32(&arginfo->ps_nargvstr, argc); /* * Fill in argument portion of vector table. @@ -1276,7 +1276,7 @@ exec_copyout_strings(imgp) suword(vectp++, 0); suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); - suword(&arginfo->ps_nenvstr, envc); + suword32(&arginfo->ps_nenvstr, envc); /* * Fill in environment portion of vector table. diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index c1f13e05862..81b4c5f3dcb 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -199,8 +199,8 @@ void rw_destroy(struct rwlock *rw) { - KASSERT(rw->rw_lock == RW_UNLOCKED, ("rw lock not unlocked")); - KASSERT(rw->rw_recurse == 0, ("rw lock still recursed")); + KASSERT(rw->rw_lock == RW_UNLOCKED, ("rw lock %p not unlocked", rw)); + KASSERT(rw->rw_recurse == 0, ("rw lock %p still recursed", rw)); rw->rw_lock = RW_DESTROYED; lock_destroy(&rw->lock_object); } diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index fcfb226ea71..e098648a669 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1428,9 +1428,9 @@ pipe_stat(fp, ub, active_cred, td) else ub->st_size = pipe->pipe_buffer.cnt; ub->st_blocks = (ub->st_size + ub->st_blksize - 1) / ub->st_blksize; - ub->st_atimespec = pipe->pipe_atime; - ub->st_mtimespec = pipe->pipe_mtime; - ub->st_ctimespec = pipe->pipe_ctime; + ub->st_atim = pipe->pipe_atime; + ub->st_mtim = pipe->pipe_mtime; + ub->st_ctim = pipe->pipe_ctime; ub->st_uid = fp->f_cred->cr_uid; ub->st_gid = fp->f_cred->cr_gid; /* diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index 290fdc2ec15..5cfbc713be5 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -556,9 +556,9 @@ ptsdev_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, #endif /* PTS_EXTERNAL */ sb->st_ino = sb->st_rdev = tty_udev(tp); - sb->st_atimespec = dev->si_atime; - sb->st_ctimespec = dev->si_ctime; - sb->st_mtimespec = dev->si_mtime; + sb->st_atim = dev->si_atime; + sb->st_ctim = dev->si_ctime; + sb->st_mtim = dev->si_mtime; sb->st_uid = dev->si_uid; sb->st_gid = dev->si_gid; sb->st_mode = dev->si_mode | S_IFCHR; diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index a34c22859a2..1319666e2c9 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -2447,10 +2447,10 @@ mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred, struct mqfs_node *pn = fp->f_data; bzero(st, sizeof *st); - st->st_atimespec = pn->mn_atime; - st->st_mtimespec = pn->mn_mtime; - st->st_ctimespec = pn->mn_ctime; - st->st_birthtimespec = pn->mn_birth; + st->st_atim = pn->mn_atime; + st->st_mtim = pn->mn_mtime; + st->st_ctim = pn->mn_ctime; + st->st_birthtim = pn->mn_birth; st->st_uid = pn->mn_uid; st->st_gid = pn->mn_gid; st->st_mode = S_IFIFO | pn->mn_mode; diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index a6b2f75f401..d9229ead170 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -219,10 +219,10 @@ ksem_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, bzero(sb, sizeof(*sb)); sb->st_mode = S_IFREG | ks->ks_mode; /* XXX */ - sb->st_atimespec = ks->ks_atime; - sb->st_ctimespec = ks->ks_ctime; - sb->st_mtimespec = ks->ks_mtime; - sb->st_birthtimespec = ks->ks_birthtime; + sb->st_atim = ks->ks_atime; + sb->st_ctim = ks->ks_ctime; + sb->st_mtim = ks->ks_mtime; + sb->st_birthtim = ks->ks_birthtime; sb->st_uid = ks->ks_uid; sb->st_gid = ks->ks_gid; diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 32bfd2d0769..fe1a224d2c5 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -219,10 +219,10 @@ shm_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, sb->st_blksize = PAGE_SIZE; sb->st_size = shmfd->shm_size; sb->st_blocks = (sb->st_size + sb->st_blksize - 1) / sb->st_blksize; - sb->st_atimespec = shmfd->shm_atime; - sb->st_ctimespec = shmfd->shm_ctime; - sb->st_mtimespec = shmfd->shm_mtime; - sb->st_birthtimespec = shmfd->shm_birthtime; + sb->st_atim = shmfd->shm_atime; + sb->st_ctim = shmfd->shm_ctime; + sb->st_mtim = shmfd->shm_mtime; + sb->st_birthtim = shmfd->shm_birthtime; sb->st_uid = shmfd->shm_uid; sb->st_gid = shmfd->shm_gid; diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 6f10b49c418..5b6ccf6ff46 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -948,19 +948,17 @@ relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) #endif /* - * Check for degenerate name (e.g. / or "") - * which is a way of talking about a directory, - * e.g. like "/." or ".". + * Check for "" which represents the root directory after slash + * removal. */ if (cnp->cn_nameptr[0] == '\0') { - if (cnp->cn_nameiop != LOOKUP || wantparent) { - error = EISDIR; - goto bad; - } - if (dp->v_type != VDIR) { - error = ENOTDIR; - goto bad; - } + /* + * Support only LOOKUP for "/" because lookup() + * can't succeed for CREATE, DELETE and RENAME. + */ + KASSERT(cnp->cn_nameiop == LOOKUP, ("nameiop must be LOOKUP")); + KASSERT(dp->v_type == VDIR, ("dp is not a directory")); + if (!(cnp->cn_flags & LOCKLEAF)) VOP_UNLOCK(dp, 0); *vpp = dp; diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index bcc3cbb45b1..c329adc9480 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -2269,9 +2269,9 @@ cvtstat(st, ost) ost->st_size = st->st_size; else ost->st_size = -2; - ost->st_atime = st->st_atime; - ost->st_mtime = st->st_mtime; - ost->st_ctime = st->st_ctime; + ost->st_atim = st->st_atim; + ost->st_mtim = st->st_mtim; + ost->st_ctim = st->st_ctim; ost->st_blksize = st->st_blksize; ost->st_blocks = st->st_blocks; ost->st_flags = st->st_flags; @@ -2431,15 +2431,15 @@ cvtnstat(sb, nsb) nsb->st_uid = sb->st_uid; nsb->st_gid = sb->st_gid; nsb->st_rdev = sb->st_rdev; - nsb->st_atimespec = sb->st_atimespec; - nsb->st_mtimespec = sb->st_mtimespec; - nsb->st_ctimespec = sb->st_ctimespec; + nsb->st_atim = sb->st_atim; + nsb->st_mtim = sb->st_mtim; + nsb->st_ctim = sb->st_ctim; nsb->st_size = sb->st_size; nsb->st_blocks = sb->st_blocks; nsb->st_blksize = sb->st_blksize; nsb->st_flags = sb->st_flags; nsb->st_gen = sb->st_gen; - nsb->st_birthtimespec = sb->st_birthtimespec; + nsb->st_birthtim = sb->st_birthtim; } #ifndef _SYS_SYSPROTO_H_ diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index a16fa6762a5..74e6c0221fb 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -782,10 +782,10 @@ vn_stat(vp, sb, active_cred, file_cred, td) if (vap->va_size > OFF_MAX) return (EOVERFLOW); sb->st_size = vap->va_size; - sb->st_atimespec = vap->va_atime; - sb->st_mtimespec = vap->va_mtime; - sb->st_ctimespec = vap->va_ctime; - sb->st_birthtimespec = vap->va_birthtime; + sb->st_atim = vap->va_atime; + sb->st_mtim = vap->va_mtime; + sb->st_ctim = vap->va_ctime; + sb->st_birthtim = vap->va_birthtime; /* * According to www.opengroup.org, the meaning of st_blksize is diff --git a/sys/mips/include/cpufunc.h b/sys/mips/include/cpufunc.h index d4ca0f198d1..f9100eaeb32 100644 --- a/sys/mips/include/cpufunc.h +++ b/sys/mips/include/cpufunc.h @@ -283,6 +283,35 @@ breakpoint(void) __asm __volatile ("break"); } +#if defined(__GNUC__) && !defined(__mips_o32) +static inline uint64_t +mips3_ld(const volatile uint64_t *va) +{ + uint64_t rv; + +#if defined(_LP64) + rv = *va; +#else + __asm volatile("ld %0,0(%1)" : "=d"(rv) : "r"(va)); +#endif + + return (rv); +} + +static inline void +mips3_sd(volatile uint64_t *va, uint64_t v) +{ +#if defined(_LP64) + *va = v; +#else + __asm volatile("sd %0,0(%1)" :: "r"(v), "r"(va)); +#endif +} +#else +uint64_t mips3_ld(volatile uint64_t *va); +void mips3_sd(volatile uint64_t *, uint64_t); +#endif /* __GNUC__ */ + #endif /* _KERNEL */ #define readb(va) (*(volatile uint8_t *) (va)) diff --git a/sys/mips/mips/pm_machdep.c b/sys/mips/mips/pm_machdep.c index 712763b1020..03867b0a839 100644 --- a/sys/mips/mips/pm_machdep.c +++ b/sys/mips/mips/pm_machdep.c @@ -472,7 +472,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs) * code by the MIPS elf abi). */ void -exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { bzero((caddr_t)td->td_frame, sizeof(struct trapframe)); @@ -481,8 +481,8 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) * Make sp 64-bit aligned. */ td->td_frame->sp = ((register_t) stack) & ~(sizeof(__int64_t) - 1); - td->td_frame->pc = entry & ~3; - td->td_frame->t9 = entry & ~3; /* abicall req */ + td->td_frame->pc = imgp->entry_addr & ~3; + td->td_frame->t9 = imgp->entry_addr & ~3; /* abicall req */ #if 0 // td->td_frame->sr = SR_KSU_USER | SR_EXL | SR_INT_ENAB; //? td->td_frame->sr |= idle_mask & ALL_INT_MASK; @@ -511,7 +511,7 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) td->td_frame->a0 = (register_t) stack; td->td_frame->a1 = 0; td->td_frame->a2 = 0; - td->td_frame->a3 = (register_t)ps_strings; + td->td_frame->a3 = (register_t)imgp->ps_strings; td->td_md.md_flags &= ~MDTD_FPUSED; if (PCPU_GET(fpcurthread) == td) diff --git a/sys/mips/mips/support.S b/sys/mips/mips/support.S index 6282eb0339f..2aed3e613fd 100644 --- a/sys/mips/mips/support.S +++ b/sys/mips/mips/support.S @@ -50,6 +50,38 @@ * $FreeBSD$ */ +/* + * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jonathan R. Stone for + * the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + /* * Contains code that is the first executed at boot time plus * assembly language support routines. @@ -61,6 +93,7 @@ #include #include #include +#include #include "assym.s" @@ -1586,3 +1619,78 @@ LEAF(octeon_get_control) .set mips0 END(octeon_get_control) #endif + +LEAF(mips3_ld) + .set push + .set noreorder + .set mips64 +#if defined(__mips_o32) + mfc0 t0, MIPS_COP_0_STATUS # turn off interrupts + and t1, t0, ~(MIPS_SR_INT_IE) + mtc0 t1, MIPS_COP_0_STATUS + COP0_SYNC + nop + nop + nop + + ld v0, 0(a0) +#if _BYTE_ORDER == _BIG_ENDIAN + dsll v1, v0, 32 + dsra v1, v1, 32 # low word in v1 + dsra v0, v0, 32 # high word in v0 +#else + dsra v1, v0, 32 # high word in v1 + dsll v0, v0, 32 + dsra v0, v0, 32 # low word in v0 +#endif + + mtc0 t0, MIPS_COP_0_STATUS # restore intr status. + COP0_SYNC + nop +#else /* !__mips_o32 */ + ld v0, 0(a0) +#endif /* !__mips_o32 */ + + jr ra + nop + .set pop +END(mips3_ld) + +LEAF(mips3_sd) + .set push + .set mips64 + .set noreorder +#if defined(__mips_o32) + mfc0 t0, MIPS_COP_0_STATUS # turn off interrupts + and t1, t0, ~(MIPS_SR_INT_IE) + mtc0 t1, MIPS_COP_0_STATUS + COP0_SYNC + nop + nop + nop + + # NOTE: a1 is padding! + +#if _BYTE_ORDER == _BIG_ENDIAN + dsll a2, a2, 32 # high word in a2 + dsll a3, a3, 32 # low word in a3 + dsrl a3, a3, 32 +#else + dsll a2, a2, 32 # low word in a2 + dsrl a2, a2, 32 + dsll a3, a3, 32 # high word in a3 +#endif + or a1, a2, a3 + sd a1, 0(a0) + + mtc0 t0, MIPS_COP_0_STATUS # restore intr status. + COP0_SYNC + nop +#else /* !__mips_o32 */ + sd a1, 0(a0) +#endif /* !__mips_o32 */ + + jr ra + nop + .set pop +END(mips3_sd) diff --git a/sys/mips/mips/tick.c b/sys/mips/mips/tick.c index b83d83f5f74..60b3511e0c0 100644 --- a/sys/mips/mips/tick.c +++ b/sys/mips/mips/tick.c @@ -63,17 +63,14 @@ static uint64_t cycles_per_hz, cycles_per_stathz, cycles_per_profhz; static u_int32_t counter_upper = 0; static u_int32_t counter_lower_last = 0; -struct clk_ticks -{ +struct clk_ticks { u_long hard_ticks; u_long stat_ticks; u_long prof_ticks; - /* - * pad for cache line alignment of pcpu info - * cache-line-size - number of used bytes - */ - char pad[32-(3*sizeof (u_long))]; -} static pcpu_ticks[MAXCPU]; + uint32_t compare_ticks; +} __aligned(CACHE_LINE_SIZE); + +static struct clk_ticks pcpu_ticks[MAXCPU]; /* * Device methods @@ -260,25 +257,47 @@ clock_intr(void *arg) { struct clk_ticks *cpu_ticks; struct trapframe *tf; - uint32_t ltick; + uint32_t count, compare, delta; + + cpu_ticks = &pcpu_ticks[PCPU_GET(cpuid)]; + /* * Set next clock edge. */ - ltick = mips_rd_count(); - mips_wr_compare(ltick + cycles_per_tick); - cpu_ticks = &pcpu_ticks[PCPU_GET(cpuid)]; + count = mips_rd_count(); + compare = cpu_ticks->compare_ticks; + cpu_ticks->compare_ticks = count + cycles_per_tick; + mips_wr_compare(cpu_ticks->compare_ticks); critical_enter(); - if (ltick < counter_lower_last) { + if (count < counter_lower_last) { counter_upper++; - counter_lower_last = ltick; + counter_lower_last = count; } /* * Magic. Setting up with an arg of NULL means we get passed tf. */ tf = (struct trapframe *)arg; + delta = cycles_per_tick; + + /* + * Account for the "lost time" between when the timer interrupt fired + * and when 'clock_intr' actually started executing. + */ + delta += count - compare; + + /* + * If the COUNT and COMPARE registers are no longer in sync then make + * up some reasonable value for the 'delta'. + * + * This could happen, for e.g., after we resume normal operations after + * exiting the debugger. + */ + if (delta > cycles_per_hz) + delta = cycles_per_hz; + /* Fire hardclock at hz. */ - cpu_ticks->hard_ticks += cycles_per_tick; + cpu_ticks->hard_ticks += delta; if (cpu_ticks->hard_ticks >= cycles_per_hz) { cpu_ticks->hard_ticks -= cycles_per_hz; if (PCPU_GET(cpuid) == 0) @@ -288,14 +307,14 @@ clock_intr(void *arg) } /* Fire statclock at stathz. */ - cpu_ticks->stat_ticks += cycles_per_tick; + cpu_ticks->stat_ticks += delta; if (cpu_ticks->stat_ticks >= cycles_per_stathz) { cpu_ticks->stat_ticks -= cycles_per_stathz; statclock(USERMODE(tf->sr)); } /* Fire profclock at profhz, but only when needed. */ - cpu_ticks->prof_ticks += cycles_per_tick; + cpu_ticks->prof_ticks += delta; if (cpu_ticks->prof_ticks >= cycles_per_profhz) { cpu_ticks->prof_ticks -= cycles_per_profhz; if (profprocs != 0) diff --git a/sys/mips/sibyte/sb_asm.S b/sys/mips/sibyte/sb_asm.S index 4baa5f39787..312d3a58535 100644 --- a/sys/mips/sibyte/sb_asm.S +++ b/sys/mips/sibyte/sb_asm.S @@ -28,61 +28,11 @@ #include #include -#include - -/* - * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit - * processor. It has some registers that must be accessed using 64-bit load - * and store instructions. - * - * So we have to resort to assembly because the compiler does not emit the - * 'ld' and 'sd' instructions since it thinks that it is compiling for a - * 32-bit mips processor. - */ .set mips64 .set noat .set noreorder -/* - * Parameters: uint32_t ptr - * Return value: *(uint64_t *)ptr - */ -LEAF(sb_load64) - ld v1, 0(a0) /* result = *(uint64_t *)ptr */ - move v0, v1 -#if _BYTE_ORDER == _BIG_ENDIAN - dsll32 v1, v1, 0 - dsra32 v1, v1, 0 /* v1 = lower_uint32(result) */ - jr ra - dsra32 v0, v0, 0 /* v0 = upper_uint32(result) */ -#else - dsll32 v0, v0, 0 - dsra32 v0, v0, 0 /* v0 = lower_uint32(result) */ - jr ra - dsra32 v1, v1, 0 /* v1 = upper_uint32(result) */ -#endif -END(sb_load64) - -/* - * Parameters: uint32_t ptr, uint64_t val - * Return value: void - */ -LEAF(sb_store64) -#if _BYTE_ORDER == _BIG_ENDIAN - dsll32 a2, a2, 0 /* a2 = upper_uint32(val) */ - dsll32 a3, a3, 0 /* a3 = lower_uint32(val) */ - dsrl32 a3, a3, 0 -#else - dsll32 a3, a3, 0 /* a3 = upper_uint32(val) */ - dsll32 a2, a2, 0 /* a2 = lower_uint32(val) */ - dsrl32 a2, a2, 0 -#endif - or t0, a2, a3 - jr ra - sd t0, 0(a0) -END(sb_store64) - #ifdef SMP /* * This function must be implemented in assembly because it is called early diff --git a/sys/mips/sibyte/sb_scd.c b/sys/mips/sibyte/sb_scd.c index c8fec6978a9..bfaa8d471f0 100644 --- a/sys/mips/sibyte/sb_scd.c +++ b/sys/mips/sibyte/sb_scd.c @@ -38,8 +38,15 @@ __FBSDID("$FreeBSD$"); #include "sb_scd.h" -extern void sb_store64(uint32_t addr, uint64_t val); -extern uint64_t sb_load64(uint32_t addr); +/* + * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit + * processor. It has some registers that must be accessed using 64-bit load + * and store instructions. + * + * We use the mips_ld() and mips_sd() functions to do this for us. + */ +#define sb_store64(addr, val) mips3_sd((uint64_t *)(addr), (val)) +#define sb_load64(addr) mips3_ld((uint64_t *)(addr)) /* * System Control and Debug (SCD) unit on the Sibyte ZBbus. diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 72c126ac563..47800c30ed1 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -565,10 +565,7 @@ _zfs= zfs .endif .if ${MACHINE_ARCH} == "ia64" -# Modules not enabled on ia64 (as compared to i386) include: -# aac acpi aout apm atspeaker drm ibcs2 linprocfs linux ncv -# nsp s3 sbni stg vesa -# acpi is not enabled because it is broken as a module on ia64 +_aac= aac _aic= aic _an= an _arcnet= arcnet @@ -581,12 +578,17 @@ _cm= cm _cmx= cmx _coff= coff _cpufreq= cpufreq +_dpt= dpt _em= em _ep= ep +_et= et _exca= exca _fe= fe +_hptiop= hptiop +_ida= ida _igb= igb _iir= iir +_ips= ips _mly= mly _pccard= pccard _scsi_low= scsi_low @@ -595,6 +597,7 @@ _sound= sound _splash= splash _sppp= sppp _streams= streams +_twa= twa _wi= wi _xe= xe .endif diff --git a/sys/modules/dummynet/Makefile b/sys/modules/dummynet/Makefile index c25a7a7b0f4..a8813e277d1 100644 --- a/sys/modules/dummynet/Makefile +++ b/sys/modules/dummynet/Makefile @@ -5,6 +5,8 @@ .PATH: ${.CURDIR}/../../netinet/ipfw KMOD= dummynet SRCS= ip_dummynet.c +SRCS+= ip_dn_glue.c ip_dn_io.c +SRCS+= dn_heap.c dn_sched_fifo.c dn_sched_qfq.c dn_sched_rr.c dn_sched_wf2q.c SRCS+= opt_inet6.h .if !defined(KERNBUILDDIR) diff --git a/sys/modules/ixgbe/Makefile b/sys/modules/ixgbe/Makefile index 844ac7c5e55..2de7549a581 100644 --- a/sys/modules/ixgbe/Makefile +++ b/sys/modules/ixgbe/Makefile @@ -6,7 +6,7 @@ SRCS += ixgbe.c # Shared source SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c SRCS += ixgbe_82599.c ixgbe_82598.c -CFLAGS+= -I${.CURDIR}/../../dev/ixgbe -DSMP +CFLAGS+= -I${.CURDIR}/../../dev/ixgbe -DSMP -DIXGBE_FDIR clean: rm -f device_if.h bus_if.h pci_if.h setdef* *_StripErr diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c index fe79c807fb1..39b6b40a996 100644 --- a/sys/net/flowtable.c +++ b/sys/net/flowtable.c @@ -155,30 +155,33 @@ struct flowtable_stats { uint64_t ft_frees; uint64_t ft_hits; uint64_t ft_lookups; -} __aligned(128); +} __aligned(CACHE_LINE_SIZE); struct flowtable { struct flowtable_stats ft_stats[MAXCPU]; int ft_size; int ft_lock_count; uint32_t ft_flags; - - uint32_t ft_udp_idle; - uint32_t ft_fin_wait_idle; - uint32_t ft_syn_idle; - uint32_t ft_tcp_idle; - char *ft_name; fl_lock_t *ft_lock; fl_lock_t *ft_unlock; fl_rtalloc_t *ft_rtalloc; + /* + * XXX need to pad out + */ struct mtx *ft_locks; - union flentryp ft_table; bitstr_t *ft_masks[MAXCPU]; bitstr_t *ft_tmpmask; struct flowtable *ft_next; -} __aligned(128); + + uint32_t ft_count __aligned(CACHE_LINE_SIZE); + uint32_t ft_udp_idle __aligned(CACHE_LINE_SIZE); + uint32_t ft_fin_wait_idle; + uint32_t ft_syn_idle; + uint32_t ft_tcp_idle; + boolean_t ft_full; +} __aligned(CACHE_LINE_SIZE); static struct proc *flowcleanerproc; static VNET_DEFINE(struct flowtable *, flow_list_head); @@ -191,9 +194,11 @@ static VNET_DEFINE(uma_zone_t, flow_ipv6_zone); #define V_flow_ipv4_zone VNET(flow_ipv4_zone) #define V_flow_ipv6_zone VNET(flow_ipv6_zone) + static struct cv flowclean_cv; static struct mtx flowclean_lock; static uint32_t flowclean_cycles; +static uint32_t flowclean_freq; #ifdef FLOWTABLE_DEBUG #define FLDPRINTF(ft, flags, fmt, ...) \ @@ -230,7 +235,7 @@ static VNET_DEFINE(int, flowtable_syn_expire) = SYN_IDLE; static VNET_DEFINE(int, flowtable_udp_expire) = UDP_IDLE; static VNET_DEFINE(int, flowtable_fin_wait_expire) = FIN_WAIT_IDLE; static VNET_DEFINE(int, flowtable_tcp_expire) = TCP_IDLE; -static VNET_DEFINE(int, flowtable_nmbflows) = 4096; +static VNET_DEFINE(int, flowtable_nmbflows); static VNET_DEFINE(int, flowtable_ready) = 0; #define V_flowtable_enable VNET(flowtable_enable) @@ -905,6 +910,61 @@ flowtable_set_hashkey(struct flentry *fle, uint32_t *key) hashkey[i] = key[i]; } +static struct flentry * +flow_alloc(struct flowtable *ft) +{ + struct flentry *newfle; + uma_zone_t zone; + + newfle = NULL; + zone = (ft->ft_flags & FL_IPV6) ? V_flow_ipv6_zone : V_flow_ipv4_zone; + + newfle = uma_zalloc(zone, M_NOWAIT | M_ZERO); + if (newfle != NULL) + atomic_add_int(&ft->ft_count, 1); + return (newfle); +} + +static void +flow_free(struct flentry *fle, struct flowtable *ft) +{ + uma_zone_t zone; + + zone = (ft->ft_flags & FL_IPV6) ? V_flow_ipv6_zone : V_flow_ipv4_zone; + atomic_add_int(&ft->ft_count, -1); + uma_zfree(zone, fle); +} + +static int +flow_full(struct flowtable *ft) +{ + boolean_t full; + uint32_t count; + + full = ft->ft_full; + count = ft->ft_count; + + if (full && (count < (V_flowtable_nmbflows - (V_flowtable_nmbflows >> 3)))) + ft->ft_full = FALSE; + else if (!full && (count > (V_flowtable_nmbflows - (V_flowtable_nmbflows >> 5)))) + ft->ft_full = TRUE; + + if (full && !ft->ft_full) { + flowclean_freq = 4*hz; + if ((ft->ft_flags & FL_HASH_ALL) == 0) + ft->ft_udp_idle = ft->ft_fin_wait_idle = + ft->ft_syn_idle = ft->ft_tcp_idle = 5; + cv_broadcast(&flowclean_cv); + } else if (!full && ft->ft_full) { + flowclean_freq = 20*hz; + if ((ft->ft_flags & FL_HASH_ALL) == 0) + ft->ft_udp_idle = ft->ft_fin_wait_idle = + ft->ft_syn_idle = ft->ft_tcp_idle = 30; + } + + return (ft->ft_full); +} + static int flowtable_insert(struct flowtable *ft, uint32_t hash, uint32_t *key, uint32_t fibnum, struct route *ro, uint16_t flags) @@ -912,12 +972,10 @@ flowtable_insert(struct flowtable *ft, uint32_t hash, uint32_t *key, struct flentry *fle, *fletail, *newfle, **flep; struct flowtable_stats *fs = &ft->ft_stats[curcpu]; int depth; - uma_zone_t flezone; bitstr_t *mask; uint8_t proto; - flezone = (flags & FL_IPV6) ? V_flow_ipv6_zone : V_flow_ipv4_zone; - newfle = uma_zalloc(flezone, M_NOWAIT | M_ZERO); + newfle = flow_alloc(ft); if (newfle == NULL) return (ENOMEM); @@ -948,9 +1006,8 @@ flowtable_insert(struct flowtable *ft, uint32_t hash, uint32_t *key, * or we lost a race to insert */ FL_ENTRY_UNLOCK(ft, hash); - uma_zfree((newfle->f_flags & FL_IPV6) ? - V_flow_ipv6_zone : V_flow_ipv4_zone, newfle); - + flow_free(newfle, ft); + if (flags & FL_OVERWRITE) goto skip; return (EEXIST); @@ -1147,7 +1204,7 @@ keycheck: } FL_ENTRY_UNLOCK(ft, hash); uncached: - if (flags & FL_NOAUTO) + if (flags & FL_NOAUTO || flow_full(ft)) return (NULL); fs->ft_misses++; @@ -1325,7 +1382,7 @@ flowtable_alloc(char *name, int nentry, int flags) * */ static void -fle_free(struct flentry *fle) +fle_free(struct flentry *fle, struct flowtable *ft) { struct rtentry *rt; struct llentry *lle; @@ -1334,8 +1391,7 @@ fle_free(struct flentry *fle) lle = __DEVOLATILE(struct llentry *, fle->f_lle); RTFREE(rt); LLE_FREE(lle); - uma_zfree((fle->f_flags & FL_IPV6) ? - V_flow_ipv6_zone : V_flow_ipv4_zone, fle); + flow_free(fle, ft); } static void @@ -1426,7 +1482,7 @@ flowtable_free_stale(struct flowtable *ft, struct rtentry *rt) flefreehead = fle->f_next; count++; fs->ft_frees++; - fle_free(fle); + fle_free(fle, ft); } if (V_flowtable_debug && count) log(LOG_DEBUG, "freed %d flow entries\n", count); @@ -1518,7 +1574,7 @@ flowtable_cleaner(void) */ mtx_lock(&flowclean_lock); cv_broadcast(&flowclean_cv); - cv_timedwait(&flowclean_cv, &flowclean_lock, 10*hz); + cv_timedwait(&flowclean_cv, &flowclean_lock, flowclean_freq); mtx_unlock(&flowclean_lock); } } @@ -1548,6 +1604,7 @@ static void flowtable_init_vnet(const void *unused __unused) { + V_flowtable_nmbflows = 1024 + maxusers * 64 * mp_ncpus; V_flow_ipv4_zone = uma_zcreate("ip4flow", sizeof(struct flentry_v4), NULL, NULL, NULL, NULL, 64, UMA_ZONE_MAXBUCKET); V_flow_ipv6_zone = uma_zcreate("ip6flow", sizeof(struct flentry_v6), @@ -1556,7 +1613,7 @@ flowtable_init_vnet(const void *unused __unused) uma_zone_set_max(V_flow_ipv6_zone, V_flowtable_nmbflows); V_flowtable_ready = 1; } -VNET_SYSINIT(flowtable_init_vnet, SI_SUB_KTHREAD_INIT, SI_ORDER_MIDDLE, +VNET_SYSINIT(flowtable_init_vnet, SI_SUB_SMP, SI_ORDER_ANY, flowtable_init_vnet, NULL); static void @@ -1567,8 +1624,9 @@ flowtable_init(const void *unused __unused) mtx_init(&flowclean_lock, "flowclean lock", NULL, MTX_DEF); EVENTHANDLER_REGISTER(ifnet_departure_event, flowtable_flush, NULL, EVENTHANDLER_PRI_ANY); + flowclean_freq = 20*hz; } -SYSINIT(flowtable_init, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, +SYSINIT(flowtable_init, SI_SUB_SMP, SI_ORDER_MIDDLE, flowtable_init, NULL); diff --git a/sys/net/if_media.h b/sys/net/if_media.h index 1db27666e21..c93739276d2 100644 --- a/sys/net/if_media.h +++ b/sys/net/if_media.h @@ -462,6 +462,7 @@ struct ifmedia_description { { IFM_IEEE80211_OFDM3, "OFDM/3Mbps" }, \ { IFM_IEEE80211_OFDM4, "OFDM/4.5Mbps" }, \ { IFM_IEEE80211_OFDM27, "OFDM/27Mbps" }, \ + { IFM_IEEE80211_MCS, "MCS" }, \ { 0, NULL }, \ } @@ -500,6 +501,7 @@ struct ifmedia_description { { IFM_IEEE80211_OFDM3, "OFDM3" }, \ { IFM_IEEE80211_OFDM4, "OFDM4.5" }, \ { IFM_IEEE80211_OFDM27, "OFDM27" }, \ + { IFM_IEEE80211_MCS, "MCS" }, \ { 0, NULL }, \ } diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index f72e10b8414..8a50bc02076 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -404,6 +404,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, vap->iv_flags_ven = ic->ic_flags_ven; vap->iv_caps = ic->ic_caps &~ IEEE80211_C_OPMODE; vap->iv_htcaps = ic->ic_htcaps; + vap->iv_htextcaps = ic->ic_htextcaps; vap->iv_opmode = opmode; vap->iv_caps |= ieee80211_opcap[opmode]; switch (opmode) { diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index 8405b4f646b..63bcd3c9a14 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -883,6 +883,14 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) wh = mtod(m, struct ieee80211_frame *); wh->i_fc[1] &= ~IEEE80211_FC1_WEP; } + /* + * Pass the packet to radiotap before calling iv_recv_mgmt(). + * Otherwise iv_recv_mgmt() might pass another packet to + * radiotap, resulting in out of order packet captures. + */ + if (ieee80211_radiotap_active_vap(vap)) + ieee80211_radiotap_rx(vap, m); + need_tap = 0; vap->iv_recv_mgmt(ni, m, subtype, rssi, nf); goto out; diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index 4dbe9179437..2d44816a540 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -2346,7 +2346,7 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni) frm += 2; \ } while (0) struct ieee80211vap *vap = ni->ni_vap; - uint16_t caps; + uint16_t caps, extcaps; int rxmax, density; /* HT capabilities */ @@ -2404,8 +2404,17 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni) */ ieee80211_set_htrates(frm, &ieee80211_rateset_11n); - frm += sizeof(struct ieee80211_ie_htcap) - + frm += __offsetof(struct ieee80211_ie_htcap, hc_extcap) - __offsetof(struct ieee80211_ie_htcap, hc_mcsset); + + /* HT extended capabilities */ + extcaps = vap->iv_htextcaps & 0xffff; + + ADDSHORT(frm, extcaps); + + frm += sizeof(struct ieee80211_ie_htcap) - + __offsetof(struct ieee80211_ie_htcap, hc_txbf); + return frm; #undef ADDSHORT } diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index d6f3e6669ec..3916b6c0579 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -137,6 +137,7 @@ struct ieee80211com { uint32_t ic_flags_ven; /* vendor state flags */ uint32_t ic_caps; /* capabilities */ uint32_t ic_htcaps; /* HT capabilities */ + uint32_t ic_htextcaps; /* HT extended capabilities */ uint32_t ic_cryptocaps; /* crypto capabilities */ uint8_t ic_modecaps[2]; /* set of mode capabilities */ uint8_t ic_promisc; /* vap's needing promisc mode */ @@ -313,7 +314,8 @@ struct ieee80211com { int batimeout, int baseqctl); void (*ic_ampdu_rx_stop)(struct ieee80211_node *, struct ieee80211_rx_ampdu *); - uint64_t ic_spare[8]; + uint64_t ic_spare[7]; + uint32_t ic_spare2; }; struct ieee80211_aclator; @@ -340,6 +342,7 @@ struct ieee80211vap { uint32_t iv_flags_ven; /* vendor state flags */ uint32_t iv_caps; /* capabilities */ uint32_t iv_htcaps; /* HT capabilities */ + uint32_t iv_htextcaps; /* HT extended capabilities */ enum ieee80211_opmode iv_opmode; /* operation mode */ enum ieee80211_state iv_state; /* state machine state */ enum ieee80211_state iv_nstate; /* pending state */ diff --git a/sys/netgraph/netflow/ng_netflow.c b/sys/netgraph/netflow/ng_netflow.c index cacbd724b0d..8bf484502bf 100644 --- a/sys/netgraph/netflow/ng_netflow.c +++ b/sys/netgraph/netflow/ng_netflow.c @@ -286,15 +286,6 @@ ng_netflow_newhook(node_p node, hook_p hook, const char *name) priv->export = hook; -#if 0 /* TODO: profile & test first */ - /* - * We send export dgrams in interrupt handlers and in - * callout threads. We'd better queue data for later - * netgraph ISR processing. - */ - NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); -#endif - /* Exporter is ready. Let's schedule expiry. */ callout_reset(&priv->exp_callout, (1*hz), &ng_netflow_expire, (void *)priv); diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index d91bcb0e4be..8be51fb992d 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -327,8 +327,20 @@ ip_init(void) "error %d\n", __func__, i); #ifdef FLOWTABLE - TUNABLE_INT_FETCH("net.inet.ip.output_flowtable_size", - &V_ip_output_flowtable_size); + if (TUNABLE_INT_FETCH("net.inet.ip.output_flowtable_size", + &V_ip_output_flowtable_size)) { + if (V_ip_output_flowtable_size < 256) + V_ip_output_flowtable_size = 256; + if (!powerof2(V_ip_output_flowtable_size)) { + printf("flowtable must be power of 2 size\n"); + V_ip_output_flowtable_size = 2048; + } + } else { + /* + * round up to the next power of 2 + */ + V_ip_output_flowtable_size = 1 << fls((1024 + maxusers * 64)-1); + } V_ip_ft = flowtable_alloc("ipv4", V_ip_output_flowtable_size, FL_PCPU); #endif diff --git a/sys/netinet/ipfw/ip_dn_io.c b/sys/netinet/ipfw/ip_dn_io.c index 70f14ca65d7..ae168ce86b9 100644 --- a/sys/netinet/ipfw/ip_dn_io.c +++ b/sys/netinet/ipfw/ip_dn_io.c @@ -762,7 +762,11 @@ dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa) * */ if (/*dn_cfg.io_fast &&*/ m == *m0 && (dir & PROTO_LAYER2) == 0 ) { - /* fast io */ + /* fast io, rename the tag * to carry reinject info. */ + struct m_tag *tag = m_tag_first(m); + + tag->m_tag_cookie = MTAG_IPFW_RULE; + tag->m_tag_id = 0; io_pkt_fast++; if (m->m_nextpkt != NULL) { printf("dummynet: fast io: pkt chain detected!\n"); diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index cdb78aff0e0..243d773723d 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -46,24 +46,13 @@ __FBSDID("$FreeBSD$"); #include #define SCTP_CALC_TSN_TO_GAP(gap, tsn, mapping_tsn) do { \ - if ((compare_with_wrap(tsn, mapping_tsn, MAX_TSN)) || \ - (tsn == mapping_tsn)) { \ + if (tsn >= mapping_tsn) { \ gap = tsn - mapping_tsn; \ } else { \ gap = (MAX_TSN - mapping_tsn) + tsn + 1; \ } \ } while(0) -#define SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc) do { \ - if (asoc->mapping_array_base_tsn == asoc->nr_mapping_array_base_tsn) { \ - SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, nr_gap); \ - } else {\ - int lgap; \ - SCTP_CALC_TSN_TO_GAP(lgap, tsn, asoc->mapping_array_base_tsn); \ - SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, lgap); \ - } \ - } while(0) - /* * NOTES: On the outbound side of things I need to check the sack timer to * see if I should generate a sack into the chunk queue (if I have data to @@ -304,6 +293,44 @@ sctp_build_ctl_cchunk(struct sctp_inpcb *inp, return (buf); } +static void +sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn) +{ + uint32_t gap, i; + int fnd = 0; + + if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { + return; + } + SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn); +#ifdef INVARIANTS + if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { + printf("gap:%x tsn:%x\n", gap, tsn); + sctp_print_mapping_array(asoc); + panic("Things are really messed up now!!"); + } +#endif + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; + } + if (tsn == asoc->highest_tsn_inside_map) { + /* We must back down to see what the new highest is */ + for (i = tsn - 1; compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN); i--) { + SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn); + if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { + asoc->highest_tsn_inside_map = i; + fnd = 1; + break; + } + } + if (!fnd) { + asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1; + } + } +} + /* * We are delivering currently from the reassembly queue. We must continue to @@ -319,9 +346,6 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc) int end = 0; int cntDel; - /* EY if any out-of-order delivered, then tag it nr on nr_map */ - uint32_t nr_tsn, nr_gap; - struct sctp_queued_to_read *control, *ctl, *ctlat; if (stcb == NULL) @@ -430,39 +454,7 @@ abandon: } /* pull it we did it */ TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); - /* - * EY this is the chunk that should be tagged nr gapped - * calculate the gap and such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - /* - * EY!-TODO- this tsn should be tagged nr only if it is - * out-of-order, the if statement should be modified - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - nr_tsn = chk->rec.data.TSN_seq; - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY The 1st should never happen, as in - * process_a_data_chunk method this check - * should be done - */ - /* - * EY The 2nd should never happen, because - * nr_mapping_array is always expanded when - * mapping_array is expanded - */ - printf("Impossible nr_gap ack range failed\n"); - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - } + sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { asoc->fragmented_delivery_inprogress = 0; if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) { @@ -509,67 +501,11 @@ abandon: asoc->size_on_all_streams -= ctl->length; sctp_ucount_decr(asoc->cnt_on_all_streams); strm->last_sequence_delivered++; - /* - * EY will be used to - * calculate nr-gap - */ - nr_tsn = ctl->sinfo_tsn; sctp_add_to_readq(stcb->sctp_ep, stcb, ctl, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY -now something is - * delivered, calculate - * nr_gap and tag this tsn - * NR - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY The - * 1st - * should - * never - * happen, - * as in - * process_a_ - * data_chunk - * method - * this - * check - * should be - * done - */ - /* - * EY The - * 2nd - * should - * never - * happen, - * because - * nr_mapping - * _array is - * always - * expanded - * when - * mapping_ar - * ray is - * expanded - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, - asoc->highest_tsn_inside_nr_map, - MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - } + sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); ctl = ctlat; } else { break; @@ -618,9 +554,6 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, uint16_t nxt_todel; struct mbuf *oper; - /* EY- will be used to calculate nr-gap for a tsn */ - uint32_t nr_tsn, nr_gap; - queue_needed = 1; asoc->size_on_all_streams += control->length; sctp_ucount_incr(asoc->cnt_on_all_streams); @@ -682,41 +615,12 @@ protocol_error: asoc->size_on_all_streams -= control->length; sctp_ucount_decr(asoc->cnt_on_all_streams); strm->last_sequence_delivered++; - /* EY will be used to calculate nr-gap */ - nr_tsn = control->sinfo_tsn; + sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY this is the chunk that should be tagged nr gapped - * calculate the gap and such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - printf("Impossible nr_tsn set 2?\n"); - /* - * EY The 1st should never happen, as in - * process_a_data_chunk method this check - * should be done - */ - /* - * EY The 2nd should never happen, because - * nr_mapping_array is always expanded when - * mapping_array is expanded - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - } + sctp_mark_non_revokable(asoc, control->sinfo_tsn); control = TAILQ_FIRST(&strm->inqueue); while (control != NULL) { /* all delivered */ @@ -738,47 +642,12 @@ protocol_error: SCTP_STR_LOG_FROM_IMMED_DEL); } /* EY will be used to calculate nr-gap */ - nr_tsn = control->sinfo_tsn; sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY this is the chunk that should be - * tagged nr gapped calculate the gap and - * such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY The 1st should never - * happen, as in - * process_a_data_chunk - * method this check should - * be done - */ - /* - * EY The 2nd should never - * happen, because - * nr_mapping_array is - * always expanded when - * mapping_array is expanded - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - if (compare_with_wrap(nr_tsn, - asoc->highest_tsn_inside_nr_map, - MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - } + sctp_mark_non_revokable(asoc, control->sinfo_tsn); control = at; continue; } @@ -1586,9 +1455,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, /* struct sctp_tmit_chunk *chk; */ struct sctp_tmit_chunk *chk; uint32_t tsn, gap; - - /* EY - for nr_sack */ - uint32_t nr_gap; struct mbuf *dmbuf; int indx, the_len; int need_reasm_check = 0; @@ -1640,14 +1506,12 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, return (0); } } - /* EY - for nr_sack */ - nr_gap = gap; - if (compare_with_wrap(tsn, *high_tsn, MAX_TSN)) { *high_tsn = tsn; } /* See if we have received this one already */ - if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { + if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap) || + SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, gap)) { SCTP_STAT_INCR(sctps_recvdupdata); if (asoc->numduptsns < SCTP_MAX_DUP_TSNS) { /* Record a dup for the next outbound sack */ @@ -1714,7 +1578,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, #endif } /* now is it in the mapping array of what we have accepted? */ - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN) && + compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { /* Nope not in the valid range dump it */ sctp_set_rwnd(stcb, asoc); if ((asoc->cnt_on_all_streams + @@ -1758,23 +1623,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, } SCTP_STAT_INCR(sctps_badsid); SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); - /* EY set this tsn present in nr_sack's nr_mapping_array */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); - SCTP_REVERSE_OUT_TSN_PRES(gap, tsn, asoc); - } - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { - /* we have a new high score */ - asoc->highest_tsn_inside_map = tsn; - /* EY nr_sack version of the above */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) - asoc->highest_tsn_inside_nr_map = tsn; - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(0, 2, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); - } + + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; } if (tsn == (asoc->cumulative_tsn + 1)) { /* Update cum-ack */ @@ -1925,48 +1777,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY here I should check if this delivered tsn is - * out_of_order, if yes then update the nr_map - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - /* - * EY check if the mapping_array and nr_mapping - * array are consistent - */ - if (asoc->mapping_array_base_tsn != asoc->nr_mapping_array_base_tsn) - /* - * printf("EY-IN - * sctp_process_a_data_chunk(5): Something - * is wrong the map base tsn" "\nEY-and - * nr_map base tsn should be equal."); - */ - /* EY debugging block */ - { - /* - * printf("\nEY-Calculating an - * nr_gap!!\nmapping_array_size = %d - * nr_mapping_array_size = %d" - * "\nEY-mapping_array_base = %d - * nr_mapping_array_base = - * %d\nEY-highest_tsn_inside_map = %d" - * "highest_tsn_inside_nr_map = %d\nEY-TSN = - * %d nr_gap = %d",asoc->mapping_array_size, - * asoc->nr_mapping_array_size, - * asoc->mapping_array_base_tsn, - * asoc->nr_mapping_array_base_tsn, - * asoc->highest_tsn_inside_map, - * asoc->highest_tsn_inside_nr_map,tsn,nr_gap - * ); - */ - } - /* EY - not %100 sure about the lock thing */ - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc); - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = tsn; - } if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) { /* for ordered, bump what we delivered */ asoc->strmin[strmno].last_sequence_delivered++; @@ -1977,6 +1787,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTP_STR_LOG_FROM_EXPRS_DEL); } control = NULL; + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; + } goto finish_express_del; } failed_express_del: @@ -2012,39 +1826,9 @@ failed_express_del: SCTP_PRINTF("Append fails end:%d\n", end); goto failed_pdapi_express_del; } - /* - * EY It is appended to the read queue in prev if - * block here I should check if this delivered tsn - * is out_of_order, if yes then update the nr_map - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - /* EY debugging block */ - { - /* - * printf("\nEY-Calculating an - * nr_gap!!\nEY-mapping_array_size = - * %d nr_mapping_array_size = %d" - * "\nEY-mapping_array_base = %d - * nr_mapping_array_base = - * %d\nEY-highest_tsn_inside_map = - * %d" "highest_tsn_inside_nr_map = - * %d\nEY-TSN = %d nr_gap = - * %d",asoc->mapping_array_size, - * asoc->nr_mapping_array_size, - * asoc->mapping_array_base_tsn, - * asoc->nr_mapping_array_base_tsn, - * asoc->highest_tsn_inside_map, - * asoc->highest_tsn_inside_nr_map,ts - * n,nr_gap); - */ - } - /* EY - not %100 sure about the lock thing */ - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc); - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = tsn; + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; } SCTP_STAT_INCR(sctps_recvexpressm); control->sinfo_tsn = tsn; @@ -2069,12 +1853,27 @@ failed_express_del: need_reasm_check = 1; } } + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; + } control = NULL; goto finish_express_del; } } failed_pdapi_express_del: control = NULL; + if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; + } + } else { + SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { + asoc->highest_tsn_inside_map = tsn; + } + } if ((chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) { sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { @@ -2263,56 +2062,7 @@ failed_pdapi_express_del: sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY It is added to the read queue in prev if block - * here I should check if this delivered tsn is - * out_of_order, if yes then update the nr_map - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - /* - * EY check if the mapping_array and - * nr_mapping array are consistent - */ - if (asoc->mapping_array_base_tsn != asoc->nr_mapping_array_base_tsn) - /* - * printf("EY-IN - * sctp_process_a_data_chunk(6): - * Something is wrong the map base - * tsn" "\nEY-and nr_map base tsn - * should be equal."); - */ - /* - * EY - not %100 sure about the lock - * thing, i think we don't need the - * below, - */ - /* SCTP_TCB_LOCK_ASSERT(stcb); */ - { - /* - * printf("\nEY-Calculating an - * nr_gap!!\nEY-mapping_array_size = - * %d nr_mapping_array_size = %d" - * "\nEY-mapping_array_base = %d - * nr_mapping_array_base = - * %d\nEY-highest_tsn_inside_map = - * %d" "highest_tsn_inside_nr_map = - * %d\nEY-TSN = %d nr_gap = - * %d",asoc->mapping_array_size, - * asoc->nr_mapping_array_size, - * asoc->mapping_array_base_tsn, - * asoc->nr_mapping_array_base_tsn, - * asoc->highest_tsn_inside_map, - * asoc->highest_tsn_inside_nr_map,ts - * n,nr_gap); - */ - } - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc); - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = tsn; - } + } else { /* * Special check for when streams are resetting. We @@ -2384,13 +2134,6 @@ failed_pdapi_express_del: } } finish_express_del: - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { - /* we have a new high score */ - asoc->highest_tsn_inside_map = tsn; - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(0, 2, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); - } - } if (tsn == (asoc->cumulative_tsn + 1)) { /* Update cum-ack */ asoc->cumulative_tsn = tsn; @@ -2412,22 +2155,6 @@ finish_express_del: sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, asoc->highest_tsn_inside_map, SCTP_MAP_PREPARE_SLIDE); } - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); - - /* - * EY - set tsn present in nr-map if doing nr-sacks and the tsn is - * non-renegable - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack && - (SCTP_BASE_SYSCTL(sctp_do_drain) == 0)) { - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc); - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { - asoc->highest_tsn_inside_nr_map = tsn; - } - } /* check the special flag for stream resets */ if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) && ((compare_with_wrap(asoc->cumulative_tsn, liste->tsn, MAX_TSN)) || @@ -2532,7 +2259,6 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort */ struct sctp_association *asoc; int at; - uint8_t comb_byte; int last_all_ones = 0; int slide_from, slide_end, lgap, distance; @@ -2540,15 +2266,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort /* int nr_at; */ /* int nr_last_all_ones = 0; */ /* int nr_slide_from, nr_slide_end, nr_lgap, nr_distance; */ - - uint32_t old_cumack, old_base, old_highest; - unsigned char aux_array[64]; - - /* - * EY! Don't think this is required but I am immitating the code for - * map just to make sure - */ - unsigned char nr_aux_array[64]; + uint32_t old_cumack, old_base, old_highest, highest_tsn; asoc = &stcb->asoc; at = 0; @@ -2556,68 +2274,35 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort old_cumack = asoc->cumulative_tsn; old_base = asoc->mapping_array_base_tsn; old_highest = asoc->highest_tsn_inside_map; - if (asoc->mapping_array_size < 64) - memcpy(aux_array, asoc->mapping_array, - asoc->mapping_array_size); - else - memcpy(aux_array, asoc->mapping_array, 64); - /* EY do the same for nr_mapping_array */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - if (asoc->nr_mapping_array_size != asoc->mapping_array_size) { - /* - * printf("\nEY-IN sack_check method: \nEY-" "The - * size of map and nr_map are inconsitent") - */ ; - } - if (asoc->nr_mapping_array_base_tsn != asoc->mapping_array_base_tsn) { - /* - * printf("\nEY-IN sack_check method VERY CRUCIAL - * error: \nEY-" "The base tsns of map and nr_map - * are inconsitent") - */ ; - } - /* EY! just immitating the above code */ - if (asoc->nr_mapping_array_size < 64) - memcpy(nr_aux_array, asoc->nr_mapping_array, - asoc->nr_mapping_array_size); - else - memcpy(aux_array, asoc->nr_mapping_array, 64); - } /* * We could probably improve this a small bit by calculating the * offset of the current cum-ack as the starting point. */ at = 0; - for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) { - /* - * We must combine the renegable and non-renegable arrays - * here to form a unified view of what is acked right now - * (since they are kept separate - */ - comb_byte = asoc->mapping_array[slide_from] | asoc->nr_mapping_array[slide_from]; - if (comb_byte == 0xff) { + for (slide_from = 0; slide_from < stcb->asoc.nr_mapping_array_size; slide_from++) { + if (asoc->nr_mapping_array[slide_from] == 0xff) { at += 8; last_all_ones = 1; } else { /* there is a 0 bit */ - at += sctp_map_lookup_tab[comb_byte]; + at += sctp_map_lookup_tab[asoc->nr_mapping_array[slide_from]]; last_all_ones = 0; break; } } - asoc->cumulative_tsn = asoc->mapping_array_base_tsn + (at - last_all_ones); - /* at is one off, since in the table a embedded -1 is present */ + asoc->cumulative_tsn = asoc->nr_mapping_array_base_tsn + (at - last_all_ones); at++; - if (compare_with_wrap(asoc->cumulative_tsn, - asoc->highest_tsn_inside_map, - MAX_TSN)) { + if (compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_map, MAX_TSN) && + compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN) + ) { #ifdef INVARIANTS panic("huh, cumack 0x%x greater than high-tsn 0x%x in map", asoc->cumulative_tsn, asoc->highest_tsn_inside_map); #else SCTP_PRINTF("huh, cumack 0x%x greater than high-tsn 0x%x in map - should panic?\n", asoc->cumulative_tsn, asoc->highest_tsn_inside_map); + sctp_print_mapping_array(asoc); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { sctp_log_map(0, 6, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); } @@ -2625,37 +2310,29 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn; #endif } - if ((asoc->cumulative_tsn == asoc->highest_tsn_inside_map) && (at >= 8)) { + if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, + asoc->highest_tsn_inside_map, + MAX_TSN)) { + highest_tsn = asoc->highest_tsn_inside_nr_map; + } else { + highest_tsn = asoc->highest_tsn_inside_map; + } + if ((asoc->cumulative_tsn == highest_tsn) && (at >= 8)) { /* The complete array was completed by a single FR */ - /* higest becomes the cum-ack */ + /* highest becomes the cum-ack */ int clr; - asoc->cumulative_tsn = asoc->highest_tsn_inside_map; /* clear the array */ clr = (at >> 3) + 1; if (clr > asoc->mapping_array_size) { clr = asoc->mapping_array_size; } memset(asoc->mapping_array, 0, clr); - /* base becomes one ahead of the cum-ack */ + memset(asoc->nr_mapping_array, 0, clr); + asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1; - - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - - if (clr > asoc->nr_mapping_array_size) - clr = asoc->nr_mapping_array_size; - - memset(asoc->nr_mapping_array, 0, clr); - /* base becomes one ahead of the cum-ack */ - asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1; - asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn; - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(old_base, old_cumack, old_highest, - SCTP_MAP_PREPARE_SLIDE); - sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, - asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_CLEARED); - } + asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1; + asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map = asoc->cumulative_tsn; } else if (at >= 8) { /* we can slide the mapping array down */ /* slide_from holds where we hit the first NON 0xff byte */ @@ -2664,19 +2341,15 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort * now calculate the ceiling of the move using our highest * TSN value */ - if (asoc->highest_tsn_inside_map >= asoc->mapping_array_base_tsn) { - lgap = asoc->highest_tsn_inside_map - - asoc->mapping_array_base_tsn; - } else { - lgap = (MAX_TSN - asoc->mapping_array_base_tsn) + - asoc->highest_tsn_inside_map + 1; - } - slide_end = lgap >> 3; + SCTP_CALC_TSN_TO_GAP(lgap, highest_tsn, asoc->mapping_array_base_tsn); + slide_end = (lgap >> 3); if (slide_end < slide_from) { + sctp_print_mapping_array(asoc); #ifdef INVARIANTS panic("impossible slide"); #else - printf("impossible slide?\n"); + printf("impossible slide lgap:%x slide_end:%x slide_from:%x? at:%d\n", + lgap, slide_end, slide_from, at); return; #endif } @@ -2716,30 +2389,21 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort for (ii = 0; ii < distance; ii++) { asoc->mapping_array[ii] = asoc->mapping_array[slide_from + ii]; + asoc->nr_mapping_array[ii] = + asoc->nr_mapping_array[slide_from + ii]; + } for (ii = distance; ii <= slide_end; ii++) { asoc->mapping_array[ii] = 0; + asoc->nr_mapping_array[ii] = 0; } asoc->mapping_array_base_tsn += (slide_from << 3); + asoc->nr_mapping_array_base_tsn += (slide_from << 3); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); } - /* - * EY if doing nr_sacks then slide the - * nr_mapping_array accordingly please - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - for (ii = 0; ii < distance; ii++) { - asoc->nr_mapping_array[ii] = - asoc->nr_mapping_array[slide_from + ii]; - } - for (ii = distance; ii <= slide_end; ii++) { - asoc->nr_mapping_array[ii] = 0; - } - asoc->nr_mapping_array_base_tsn += (slide_from << 3); - } } } /* @@ -2770,8 +2434,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort int is_a_gap; /* is there a gap now ? */ - is_a_gap = compare_with_wrap(stcb->asoc.highest_tsn_inside_map, - stcb->asoc.cumulative_tsn, MAX_TSN); + is_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN); /* * CMT DAC algorithm: increase number of packets @@ -5776,9 +5439,6 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, struct sctp_association *asoc; int tt; - /* EY -used to calculate nr_gap information */ - uint32_t nr_tsn, nr_gap; - asoc = &stcb->asoc; tt = strmin->last_sequence_delivered; /* @@ -5798,82 +5458,10 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, /* deliver it to at least the delivery-q */ if (stcb->sctp_socket) { /* EY need the tsn info for calculating nr */ - nr_tsn = ctl->sinfo_tsn; sctp_add_to_readq(stcb->sctp_ep, stcb, ctl, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY this is the chunk that should be - * tagged nr gapped calculate the gap and - * such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY These should never - * happen- explained before - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, - asoc->highest_tsn_inside_nr_map, - MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, nr_gap)) - /* - * printf("In - * sctp_kick_prsctp_reorder_q - * ueue(7): Something wrong, - * the TSN to be tagged" - * "\nas NR is not even in - * the mapping_array, or map - * and nr_map are - * inconsistent"); - */ - /* - * EY - not %100 sure about - * the lock thing, don't - * think its required - */ - /* - * SCTP_TCB_LOCK_ASSERT(stcb) - * ; - */ - { - /* - * printf("\nCalculating an - * nr_gap!!\nmapping_array_si - * ze = %d - * nr_mapping_array_size = - * %d" "\nmapping_array_base - * = %d - * nr_mapping_array_base = - * %d\nhighest_tsn_inside_map - * = %d" - * "highest_tsn_inside_nr_map - * = %d\nTSN = %d nr_gap = - * %d",asoc->mapping_array_si - * ze, - * asoc->nr_mapping_array_siz - * e, - * asoc->mapping_array_base_t - * sn, - * asoc->nr_mapping_array_bas - * e_tsn, - * asoc->highest_tsn_inside_m - * ap, - * asoc->highest_tsn_inside_n - * r_map,tsn,nr_gap); - */ - } - } + sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); } } else { /* no more delivery now. */ @@ -5898,82 +5486,11 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, /* deliver it to at least the delivery-q */ strmin->last_sequence_delivered = ctl->sinfo_ssn; if (stcb->sctp_socket) { - /* EY */ - nr_tsn = ctl->sinfo_tsn; sctp_add_to_readq(stcb->sctp_ep, stcb, ctl, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY this is the chunk that should be - * tagged nr gapped calculate the gap and - * such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY These should never - * happen, explained before - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, - MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, nr_gap)) - /* - * printf("In - * sctp_kick_prsctp_reorder_q - * ueue(8): Something wrong, - * the TSN to be tagged" - * "\nas NR is not even in - * the mapping_array, or map - * and nr_map are - * inconsistent"); - */ - /* - * EY - not %100 sure about - * the lock thing, don't - * think its required - */ - /* - * SCTP_TCB_LOCK_ASSERT(stcb) - * ; - */ - { - /* - * printf("\nCalculating an - * nr_gap!!\nmapping_array_si - * ze = %d - * nr_mapping_array_size = - * %d" "\nmapping_array_base - * = %d - * nr_mapping_array_base = - * %d\nhighest_tsn_inside_map - * = %d" - * "highest_tsn_inside_nr_map - * = %d\nTSN = %d nr_gap = - * %d",asoc->mapping_array_si - * ze, - * asoc->nr_mapping_array_siz - * e, - * asoc->mapping_array_base_t - * sn, - * asoc->nr_mapping_array_bas - * e_tsn, - * asoc->highest_tsn_inside_m - * ap, - * asoc->highest_tsn_inside_n - * r_map,tsn,nr_gap); - */ - } - } + sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); + } tt = strmin->last_sequence_delivered + 1; } else { @@ -6130,25 +5647,19 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { asoc->highest_tsn_inside_map = new_cum_tsn; - /* EY nr_mapping_array version of the above */ - /* - * if(SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - * asoc->peer_supports_nr_sack) - */ + + } + if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_nr_map, + MAX_TSN)) { asoc->highest_tsn_inside_nr_map = new_cum_tsn; - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(0, 0, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); - } } /* * now we know the new TSN is more advanced, let's find the actual * gap */ - SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->mapping_array_base_tsn); + SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->nr_mapping_array_base_tsn); + asoc->cumulative_tsn = new_cum_tsn; if (gap >= m_size) { - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(0, 0, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); - } if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) { struct mbuf *oper; @@ -6181,23 +5692,15 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, return; } SCTP_STAT_INCR(sctps_fwdtsn_map_over); + memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); - cumack_set_flag = 1; asoc->mapping_array_base_tsn = new_cum_tsn + 1; - asoc->cumulative_tsn = asoc->highest_tsn_inside_map = new_cum_tsn; - /* EY - nr_sack: nr_mapping_array version of the above */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); - asoc->nr_mapping_array_base_tsn = new_cum_tsn + 1; - asoc->highest_tsn_inside_nr_map = new_cum_tsn; - if (asoc->nr_mapping_array_size != asoc->mapping_array_size) { - /* - * printf("IN sctp_handle_forward_tsn: - * Something is wrong the size of" "map and - * nr_map should be equal!") - */ ; - } - } + asoc->highest_tsn_inside_map = new_cum_tsn; + + memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); + asoc->nr_mapping_array_base_tsn = new_cum_tsn + 1; + asoc->highest_tsn_inside_nr_map = new_cum_tsn; + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); } @@ -6205,12 +5708,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, } else { SCTP_TCB_LOCK_ASSERT(stcb); for (i = 0; i <= gap; i++) { - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack - && SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i); - } else { - SCTP_SET_TSN_PRESENT(asoc->mapping_array, i); - } + SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, i); + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i); } /* * Now after marking all, slide thing forward but no sack diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index ef187377b95..07518e42cf9 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -1860,9 +1860,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, memset(asoc->mapping_array, 0, asoc->mapping_array_size); } - /* EY 05/13/08 - nr_sack version of the above if statement */ - if (asoc->nr_mapping_array && SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) - && asoc->peer_supports_nr_sack) { + if (asoc->nr_mapping_array) { memset(asoc->nr_mapping_array, 0, asoc->nr_mapping_array_size); } @@ -3515,16 +3513,10 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn); memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); - /* - * EY 05/13/08 - nr_sack: to keep - * nr_mapping array be consistent - * with mapping_array - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack) { - stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; - stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.mapping_array_base_tsn; - memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); - } + stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; + stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.mapping_array_base_tsn; + memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); + stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn); stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn; @@ -3631,15 +3623,9 @@ sctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb, stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; stcb->asoc.mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1; memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); - /* - * EY 05/13/08 -nr_sack: to keep nr_mapping array consistent - * with mapping array - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack) { - stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; - stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1; - memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); - } + stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; + stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1; + memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); atomic_add_int(&stcb->asoc.sending_seq, 1); /* save off historical data for retrans */ stcb->asoc.last_sending_seq[1] = stcb->asoc.last_sending_seq[0]; diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index be4c3a8633f..b3e5781ff52 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -7871,19 +7871,8 @@ again_one_more_time: pf_hbflag = 1; } /* remove these chunks at the end */ - if (chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) { - /* turn off the timer */ - if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { - sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - inp, stcb, net, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_1); - } - } - /* - * EY -Nr-sack version of the above - * if statement - */ - if ((SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) && - (chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK)) { /* EY !?! */ + if ((chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) || + (chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK)) { /* turn off the timer */ if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, @@ -9885,6 +9874,7 @@ sctp_send_sack(struct sctp_tcb *stcb) unsigned int num_gap_blocks = 0, space; int num_dups = 0; int space_req; + uint32_t highest_tsn; a_chk = NULL; asoc = &stcb->asoc; @@ -9970,7 +9960,12 @@ sctp_send_sack(struct sctp_tcb *stcb) if (a_chk->whoTo) { atomic_add_int(&a_chk->whoTo->ref_count, 1); } - if (asoc->highest_tsn_inside_map == asoc->cumulative_tsn) { + if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + highest_tsn = asoc->highest_tsn_inside_map; + } else { + highest_tsn = asoc->highest_tsn_inside_nr_map; + } + if (highest_tsn == asoc->cumulative_tsn) { /* no gaps */ space_req = sizeof(struct sctp_sack_chunk); } else { @@ -10043,10 +10038,10 @@ sctp_send_sack(struct sctp_tcb *stcb) gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)sack + sizeof(struct sctp_sack_chunk)); - if (asoc->highest_tsn_inside_map > asoc->mapping_array_base_tsn) - siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8; + if (highest_tsn > asoc->mapping_array_base_tsn) + siz = (((highest_tsn - asoc->mapping_array_base_tsn) + 1) + 7) / 8; else - siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_map + 7) / 8; + siz = (((MAX_TSN - highest_tsn) + 1) + highest_tsn + 7) / 8; if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) { offset = 1; @@ -10063,10 +10058,10 @@ sctp_send_sack(struct sctp_tcb *stcb) */ jstart = 1; } - if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->cumulative_tsn, MAX_TSN)) { + if (compare_with_wrap(highest_tsn, asoc->cumulative_tsn, MAX_TSN)) { /* we have a gap .. maybe */ for (i = 0; i < siz; i++) { - selector = &sack_array[asoc->mapping_array[i]]; + selector = &sack_array[(asoc->mapping_array[i] | asoc->nr_mapping_array[i])]; if (mergeable && selector->right_edge) { /* * Backup, left and right edges were ok to @@ -10120,8 +10115,6 @@ sctp_send_sack(struct sctp_tcb *stcb) */ int abort_flag = 0; - asoc->cumulative_tsn = asoc->highest_tsn_inside_map; - sack->sack.cum_tsn_ack = htonl(asoc->cumulative_tsn); sctp_sack_check(stcb, 0, 0, &abort_flag); } } @@ -10180,13 +10173,13 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) int mergeable = 0; int offset; caddr_t limit; - uint32_t *dup; + uint32_t *dup, highest_tsn; int limit_reached = 0; + int seen_non_zero = 0; unsigned int i, jstart, siz, j; unsigned int num_gap_blocks = 0, num_nr_gap_blocks = 0, space; int num_dups = 0; int space_req; - unsigned int reserved = 0; a_chk = NULL; asoc = &stcb->asoc; @@ -10272,7 +10265,12 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) if (a_chk->whoTo) { atomic_add_int(&a_chk->whoTo->ref_count, 1); } - if (asoc->highest_tsn_inside_map == asoc->cumulative_tsn) { + if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + highest_tsn = asoc->highest_tsn_inside_map; + } else { + highest_tsn = asoc->highest_tsn_inside_nr_map; + } + if (highest_tsn == asoc->cumulative_tsn) { /* no gaps */ space_req = sizeof(struct sctp_nr_sack_chunk); } else { @@ -10371,6 +10369,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->cumulative_tsn, MAX_TSN)) { /* we have a gap .. maybe */ for (i = 0; i < siz; i++) { + seen_non_zero = 1; selector = &sack_array[asoc->mapping_array[i]]; if (mergeable && selector->right_edge) { /* @@ -10418,22 +10417,8 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) jstart = 0; offset += 8; } - if (num_gap_blocks == 0) { - /* - * slide not yet happened, and somehow we got called - * to send a sack. Cumack needs to move up. - */ - int abort_flag = 0; - - asoc->cumulative_tsn = asoc->highest_tsn_inside_map; - nr_sack->nr_sack.cum_tsn_ack = htonl(asoc->cumulative_tsn); - sctp_sack_check(stcb, 0, 0, &abort_flag); - } } - /*---------------------------------------------------------filling the nr_gap_ack blocks----------------------------------------------------*/ - - /* EY - there will be gaps + nr_gaps if draining is possible */ - if ((SCTP_BASE_SYSCTL(sctp_do_drain)) && (limit_reached == 0)) { + if (limit_reached == 0) { mergeable = 0; @@ -10510,9 +10495,6 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) } } } - /*---------------------------------------------End of---filling the nr_gap_ack blocks----------------------------------------------------*/ - - /* now we must add any dups we are going to report. */ if ((limit_reached == 0) && (asoc->numduptsns)) { dup = (uint32_t *) gap_descriptor; for (i = 0; i < asoc->numduptsns; i++) { @@ -10530,10 +10512,6 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) * now that the chunk is prepared queue it to the control chunk * queue. */ - if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { - num_nr_gap_blocks = num_gap_blocks; - num_gap_blocks = 0; - } a_chk->send_size = sizeof(struct sctp_nr_sack_chunk) + (num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) + num_dups * sizeof(int32_t); @@ -10542,7 +10520,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) nr_sack->nr_sack.num_gap_ack_blks = htons(num_gap_blocks); nr_sack->nr_sack.num_nr_gap_ack_blks = htons(num_nr_gap_blocks); nr_sack->nr_sack.num_dup_tsns = htons(num_dups); - nr_sack->nr_sack.reserved = htons(reserved); + nr_sack->nr_sack.reserved = 0; nr_sack->ch.chunk_length = htons(a_chk->send_size); TAILQ_INSERT_TAIL(&asoc->control_send_queue, a_chk, sctp_next); asoc->ctrl_queue_cnt++; diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 73e7991c659..fa188249a96 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -5425,8 +5425,13 @@ sctp_pcb_init() bzero(&SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log)); #endif (void)SCTP_GETTIME_TIMEVAL(&tv); +#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) + SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_sec = (uint32_t) tv.tv_sec; + SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_usec = (uint32_t) tv.tv_usec; +#else SCTP_BASE_STAT(sctps_discontinuitytime).tv_sec = (uint32_t) tv.tv_sec; SCTP_BASE_STAT(sctps_discontinuitytime).tv_usec = (uint32_t) tv.tv_usec; +#endif /* init the empty list of (All) Endpoints */ LIST_INIT(&SCTP_BASE_INFO(listhead)); diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index d9e1db6dc05..bf14175cac3 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -246,7 +246,11 @@ struct sctp_base_info { * All static structures that anchor the system must be here. */ struct sctp_epinfo sctppcbinfo; +#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) + struct sctpstat sctpstat[MAXCPU]; +#else struct sctpstat sctpstat; +#endif struct sctp_sysctl sctpsysctl; uint8_t first_time; char sctp_pcb_initialized; diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index b4023c68213..c9967eae065 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include /* * sysctl tunable variables @@ -627,7 +628,158 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS) return (error); } +#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) +static int +sysctl_stat_get(SYSCTL_HANDLER_ARGS) +{ + int cpu, error; + struct sctpstat sb, *sarry; + memset(&sb, 0, sizeof(sb)); + for (cpu = 0; cpu < mp_ncpus; cpu++) { + sarry = &SCTP_BASE_STATS[cpu]; + if (sarry->sctps_discontinuitytime.tv_sec > sb.sctps_discontinuitytime.tv_sec) { + sb.sctps_discontinuitytime.tv_sec = sarry->sctps_discontinuitytime.tv_sec; + sb.sctps_discontinuitytime.tv_usec = sarry->sctps_discontinuitytime.tv_usec; + } + sb.sctps_currestab += sarry->sctps_currestab; + sb.sctps_activeestab += sarry->sctps_activeestab; + sb.sctps_restartestab += sarry->sctps_restartestab; + sb.sctps_collisionestab += sarry->sctps_collisionestab; + sb.sctps_passiveestab += sarry->sctps_passiveestab; + sb.sctps_aborted += sarry->sctps_aborted; + sb.sctps_shutdown += sarry->sctps_shutdown; + sb.sctps_outoftheblue += sarry->sctps_outoftheblue; + sb.sctps_checksumerrors += sarry->sctps_checksumerrors; + sb.sctps_outcontrolchunks += sarry->sctps_outcontrolchunks; + sb.sctps_outorderchunks += sarry->sctps_outorderchunks; + sb.sctps_outunorderchunks += sarry->sctps_outunorderchunks; + sb.sctps_incontrolchunks += sarry->sctps_incontrolchunks; + sb.sctps_inorderchunks += sarry->sctps_inorderchunks; + sb.sctps_inunorderchunks += sarry->sctps_inunorderchunks; + sb.sctps_fragusrmsgs += sarry->sctps_fragusrmsgs; + sb.sctps_reasmusrmsgs += sarry->sctps_reasmusrmsgs; + sb.sctps_outpackets += sarry->sctps_outpackets; + sb.sctps_inpackets += sarry->sctps_inpackets; + sb.sctps_recvpackets += sarry->sctps_recvpackets; + sb.sctps_recvdatagrams += sarry->sctps_recvdatagrams; + sb.sctps_recvpktwithdata += sarry->sctps_recvpktwithdata; + sb.sctps_recvsacks += sarry->sctps_recvsacks; + sb.sctps_recvdata += sarry->sctps_recvdata; + sb.sctps_recvdupdata += sarry->sctps_recvdupdata; + sb.sctps_recvheartbeat += sarry->sctps_recvheartbeat; + sb.sctps_recvheartbeatack += sarry->sctps_recvheartbeatack; + sb.sctps_recvecne += sarry->sctps_recvecne; + sb.sctps_recvauth += sarry->sctps_recvauth; + sb.sctps_recvauthmissing += sarry->sctps_recvauthmissing; + sb.sctps_recvivalhmacid += sarry->sctps_recvivalhmacid; + sb.sctps_recvivalkeyid += sarry->sctps_recvivalkeyid; + sb.sctps_recvauthfailed += sarry->sctps_recvauthfailed; + sb.sctps_recvexpress += sarry->sctps_recvexpress; + sb.sctps_recvexpressm += sarry->sctps_recvexpressm; + sb.sctps_recvnocrc += sarry->sctps_recvnocrc; + sb.sctps_recvswcrc += sarry->sctps_recvswcrc; + sb.sctps_recvhwcrc += sarry->sctps_recvhwcrc; + sb.sctps_sendpackets += sarry->sctps_sendpackets; + sb.sctps_sendsacks += sarry->sctps_sendsacks; + sb.sctps_senddata += sarry->sctps_senddata; + sb.sctps_sendretransdata += sarry->sctps_sendretransdata; + sb.sctps_sendfastretrans += sarry->sctps_sendfastretrans; + sb.sctps_sendmultfastretrans += sarry->sctps_sendmultfastretrans; + sb.sctps_sendheartbeat += sarry->sctps_sendheartbeat; + sb.sctps_sendecne += sarry->sctps_sendecne; + sb.sctps_sendauth += sarry->sctps_sendauth; + sb.sctps_senderrors += sarry->sctps_senderrors; + sb.sctps_sendnocrc += sarry->sctps_sendnocrc; + sb.sctps_sendswcrc += sarry->sctps_sendswcrc; + sb.sctps_sendhwcrc += sarry->sctps_sendhwcrc; + sb.sctps_pdrpfmbox += sarry->sctps_pdrpfmbox; + sb.sctps_pdrpfehos += sarry->sctps_pdrpfehos; + sb.sctps_pdrpmbda += sarry->sctps_pdrpmbda; + sb.sctps_pdrpmbct += sarry->sctps_pdrpmbct; + sb.sctps_pdrpbwrpt += sarry->sctps_pdrpbwrpt; + sb.sctps_pdrpcrupt += sarry->sctps_pdrpcrupt; + sb.sctps_pdrpnedat += sarry->sctps_pdrpnedat; + sb.sctps_pdrppdbrk += sarry->sctps_pdrppdbrk; + sb.sctps_pdrptsnnf += sarry->sctps_pdrptsnnf; + sb.sctps_pdrpdnfnd += sarry->sctps_pdrpdnfnd; + sb.sctps_pdrpdiwnp += sarry->sctps_pdrpdiwnp; + sb.sctps_pdrpdizrw += sarry->sctps_pdrpdizrw; + sb.sctps_pdrpbadd += sarry->sctps_pdrpbadd; + sb.sctps_pdrpmark += sarry->sctps_pdrpmark; + sb.sctps_timoiterator += sarry->sctps_timoiterator; + sb.sctps_timodata += sarry->sctps_timodata; + sb.sctps_timowindowprobe += sarry->sctps_timowindowprobe; + sb.sctps_timoinit += sarry->sctps_timoinit; + sb.sctps_timosack += sarry->sctps_timosack; + sb.sctps_timoshutdown += sarry->sctps_timoshutdown; + sb.sctps_timoheartbeat += sarry->sctps_timoheartbeat; + sb.sctps_timocookie += sarry->sctps_timocookie; + sb.sctps_timosecret += sarry->sctps_timosecret; + sb.sctps_timopathmtu += sarry->sctps_timopathmtu; + sb.sctps_timoshutdownack += sarry->sctps_timoshutdownack; + sb.sctps_timoshutdownguard += sarry->sctps_timoshutdownguard; + sb.sctps_timostrmrst += sarry->sctps_timostrmrst; + sb.sctps_timoearlyfr += sarry->sctps_timoearlyfr; + sb.sctps_timoasconf += sarry->sctps_timoasconf; + sb.sctps_timodelprim += sarry->sctps_timodelprim; + sb.sctps_timoautoclose += sarry->sctps_timoautoclose; + sb.sctps_timoassockill += sarry->sctps_timoassockill; + sb.sctps_timoinpkill += sarry->sctps_timoinpkill; + sb.sctps_earlyfrstart += sarry->sctps_earlyfrstart; + sb.sctps_earlyfrstop += sarry->sctps_earlyfrstop; + sb.sctps_earlyfrmrkretrans += sarry->sctps_earlyfrmrkretrans; + sb.sctps_earlyfrstpout += sarry->sctps_earlyfrstpout; + sb.sctps_earlyfrstpidsck1 += sarry->sctps_earlyfrstpidsck1; + sb.sctps_earlyfrstpidsck2 += sarry->sctps_earlyfrstpidsck2; + sb.sctps_earlyfrstpidsck3 += sarry->sctps_earlyfrstpidsck3; + sb.sctps_earlyfrstpidsck4 += sarry->sctps_earlyfrstpidsck4; + sb.sctps_earlyfrstrid += sarry->sctps_earlyfrstrid; + sb.sctps_earlyfrstrout += sarry->sctps_earlyfrstrout; + sb.sctps_earlyfrstrtmr += sarry->sctps_earlyfrstrtmr; + sb.sctps_hdrops += sarry->sctps_hdrops; + sb.sctps_badsum += sarry->sctps_badsum; + sb.sctps_noport += sarry->sctps_noport; + sb.sctps_badvtag += sarry->sctps_badvtag; + sb.sctps_badsid += sarry->sctps_badsid; + sb.sctps_nomem += sarry->sctps_nomem; + sb.sctps_fastretransinrtt += sarry->sctps_fastretransinrtt; + sb.sctps_markedretrans += sarry->sctps_markedretrans; + sb.sctps_naglesent += sarry->sctps_naglesent; + sb.sctps_naglequeued += sarry->sctps_naglequeued; + sb.sctps_maxburstqueued += sarry->sctps_maxburstqueued; + sb.sctps_ifnomemqueued += sarry->sctps_ifnomemqueued; + sb.sctps_windowprobed += sarry->sctps_windowprobed; + sb.sctps_lowlevelerr += sarry->sctps_lowlevelerr; + sb.sctps_lowlevelerrusr += sarry->sctps_lowlevelerrusr; + sb.sctps_datadropchklmt += sarry->sctps_datadropchklmt; + sb.sctps_datadroprwnd += sarry->sctps_datadroprwnd; + sb.sctps_ecnereducedcwnd += sarry->sctps_ecnereducedcwnd; + sb.sctps_vtagexpress += sarry->sctps_vtagexpress; + sb.sctps_vtagbogus += sarry->sctps_vtagbogus; + sb.sctps_primary_randry += sarry->sctps_primary_randry; + sb.sctps_cmt_randry += sarry->sctps_cmt_randry; + sb.sctps_slowpath_sack += sarry->sctps_slowpath_sack; + sb.sctps_wu_sacks_sent += sarry->sctps_wu_sacks_sent; + sb.sctps_sends_with_flags += sarry->sctps_sends_with_flags; + sb.sctps_sends_with_unord += sarry->sctps_sends_with_unord; + sb.sctps_sends_with_eof += sarry->sctps_sends_with_eof; + sb.sctps_sends_with_abort += sarry->sctps_sends_with_abort; + sb.sctps_protocol_drain_calls += sarry->sctps_protocol_drain_calls; + sb.sctps_protocol_drains_done += sarry->sctps_protocol_drains_done; + sb.sctps_read_peeks += sarry->sctps_read_peeks; + sb.sctps_cached_chk += sarry->sctps_cached_chk; + sb.sctps_cached_strmoq += sarry->sctps_cached_strmoq; + sb.sctps_left_abandon += sarry->sctps_left_abandon; + sb.sctps_send_burst_avoid += sarry->sctps_send_burst_avoid; + sb.sctps_send_cwnd_avoid += sarry->sctps_send_cwnd_avoid; + sb.sctps_fwdtsn_map_over += sarry->sctps_fwdtsn_map_over; + } + error = SYSCTL_OUT(req, &sb, sizeof(sb)); + return (error); +} + +#endif #if defined(SCTP_LOCAL_TRACE_BUF) static int @@ -916,10 +1068,16 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, output_unlocked, CTLTYPE_INT | CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_output_unlocked), 0, sysctl_sctp_check, "IU", SCTPCTL_OUTPUT_UNLOCKED_DESC); #endif - +#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) +SYSCTL_PROC(_net_inet_sctp, OID_AUTO, stats, + CTLTYPE_STRUCT | CTLFLAG_RD, + 0, 0, sysctl_stat_get, "S,sctpstat", + "SCTP statistics (struct sctp_stat)"); +#else SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW, &SCTP_BASE_STATS_SYSCTL, sctpstat, "SCTP statistics (struct sctp_stat)"); +#endif SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD, 0, 0, sctp_assoclist, diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index 19089301411..e3fbc3e6d50 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -957,9 +957,13 @@ struct sctpstat { #define SCTP_STAT_INCR(_x) SCTP_STAT_INCR_BY(_x,1) #define SCTP_STAT_DECR(_x) SCTP_STAT_DECR_BY(_x,1) +#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) +#define SCTP_STAT_INCR_BY(_x,_d) (SCTP_BASE_STATS[PCPU_GET(cpuid)]._x += _d) +#define SCTP_STAT_DECR_BY(_x,_d) (SCTP_BASE_STATS[PCPU_GET(cpuid)]._x -= _d) +#else #define SCTP_STAT_INCR_BY(_x,_d) atomic_add_int(&SCTP_BASE_STAT(_x), _d) #define SCTP_STAT_DECR_BY(_x,_d) atomic_subtract_int(&SCTP_BASE_STAT(_x), _d) - +#endif /* The following macros are for handling MIB values, */ #define SCTP_STAT_INCR_COUNTER32(_x) SCTP_STAT_INCR(_x) #define SCTP_STAT_INCR_COUNTER64(_x) SCTP_STAT_INCR(_x) diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 658dc555710..e9f5aecb998 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1175,11 +1175,60 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, asoc->discontinuity_time = asoc->start_time; /* * sa_ignore MEMLEAK {memory is put in the assoc mapping array and - * freed later whe the association is freed. + * freed later when the association is freed. */ return (0); } +void +sctp_print_mapping_array(struct sctp_association *asoc) +{ + int i, limit; + + printf("Mapping size:%d baseTSN:%8.8x cumAck:%8.8x highestTSN:%8.8x\n", + asoc->mapping_array_size, + asoc->mapping_array_base_tsn, + asoc->cumulative_tsn, + asoc->highest_tsn_inside_map + ); + limit = asoc->mapping_array_size; + for (i = asoc->mapping_array_size; i >= 0; i--) { + if (asoc->mapping_array[i]) { + limit = i; + break; + } + } + if (limit == 0) + limit = 1; + for (i = 0; i < limit; i++) { + printf("%2.2x ", asoc->mapping_array[i]); + if (((i + 1) % 16) == 0) + printf("\n"); + } + printf("\n"); + printf("NR Mapping size:%d baseTSN:%8.8x highestTSN:%8.8x\n", + asoc->nr_mapping_array_size, + asoc->nr_mapping_array_base_tsn, + asoc->highest_tsn_inside_nr_map + ); + limit = asoc->nr_mapping_array_size; + for (i = asoc->nr_mapping_array_size; i >= 0; i--) { + if (asoc->nr_mapping_array[i]) { + limit = i; + break; + } + } + if (limit == 0) + limit = 1; + + for (i = 0; i < limit; i++) { + printf("%2.2x ", asoc->nr_mapping_array[i]); + if (((i + 1) % 16) == 0) + printf("\n"); + } + printf("\n"); +} + int sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed) { @@ -1187,7 +1236,9 @@ sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed) uint8_t *new_array; uint32_t new_size; + new_size = asoc->mapping_array_size + ((needed + 7) / 8 + SCTP_MAPPING_ARRAY_INCR); + SCTP_MALLOC(new_array, uint8_t *, new_size, SCTP_M_MAP); if (new_array == NULL) { /* can't get more, forget it */ @@ -1200,21 +1251,19 @@ sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed) SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); asoc->mapping_array = new_array; asoc->mapping_array_size = new_size; - if (asoc->peer_supports_nr_sack) { - new_size = asoc->nr_mapping_array_size + ((needed + 7) / 8 + SCTP_NR_MAPPING_ARRAY_INCR); - SCTP_MALLOC(new_array, uint8_t *, new_size, SCTP_M_MAP); - if (new_array == NULL) { - /* can't get more, forget it */ - SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", - new_size); - return (-1); - } - memset(new_array, 0, new_size); - memcpy(new_array, asoc->nr_mapping_array, asoc->nr_mapping_array_size); - SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); - asoc->nr_mapping_array = new_array; - asoc->nr_mapping_array_size = new_size; + new_size = asoc->nr_mapping_array_size + ((needed + 7) / 8 + SCTP_NR_MAPPING_ARRAY_INCR); + SCTP_MALLOC(new_array, uint8_t *, new_size, SCTP_M_MAP); + if (new_array == NULL) { + /* can't get more, forget it */ + SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", + new_size); + return (-1); } + memset(new_array, 0, new_size); + memcpy(new_array, asoc->nr_mapping_array, asoc->nr_mapping_array_size); + SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); + asoc->nr_mapping_array = new_array; + asoc->nr_mapping_array_size = new_size; return (0); } diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h index f3a731ea1a0..8a6ee6fb213 100644 --- a/sys/netinet/sctputil.h +++ b/sys/netinet/sctputil.h @@ -169,8 +169,6 @@ sctp_report_all_outbound(struct sctp_tcb *, int, int int sctp_expand_mapping_array(struct sctp_association *, uint32_t); -/* EY nr_sack version of the above method, expands nr_mapping_array */ -int sctp_expand_nr_mapping_array(struct sctp_association *, uint32_t); void sctp_abort_notification(struct sctp_tcb *, int, int #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) @@ -376,7 +374,7 @@ int sctp_fill_stat_log(void *, size_t *); void sctp_log_fr(uint32_t, uint32_t, uint32_t, int); void sctp_log_sack(uint32_t, uint32_t, uint32_t, uint16_t, uint16_t, int); void sctp_log_map(uint32_t, uint32_t, uint32_t, int); - +void sctp_print_mapping_array(struct sctp_association *asoc); void sctp_clr_stat_log(void); diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index a32539b8972..5c250f4417b 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1168,7 +1168,7 @@ nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force) ln->ln_state = ND6_LLINFO_REACHABLE; if (!ND6_LLINFO_PERMANENT(ln)) { - nd6_llinfo_settimer(ln, + nd6_llinfo_settimer_locked(ln, (long)ND_IFINFO(rt->rt_ifp)->reachable * hz); } done: diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index c5aa4b78ba8..e3a61aced00 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -7779,7 +7779,8 @@ void key_destroy(void) { struct secpolicy *sp, *nextsp; - struct secspacq *acq, *nextacq; + struct secacq *acq, *nextacq; + struct secspacq *spacq, *nextspacq; struct secashead *sah, *nextsah; struct secreg *reg; int i; @@ -7820,7 +7821,7 @@ key_destroy(void) REGTREE_UNLOCK(); ACQ_LOCK(); - for (acq = LIST_FIRST(&V_spacqtree); acq != NULL; acq = nextacq) { + for (acq = LIST_FIRST(&V_acqtree); acq != NULL; acq = nextacq) { nextacq = LIST_NEXT(acq, chain); if (__LIST_CHAINED(acq)) { LIST_REMOVE(acq, chain); @@ -7830,11 +7831,12 @@ key_destroy(void) ACQ_UNLOCK(); SPACQ_LOCK(); - for (acq = LIST_FIRST(&V_spacqtree); acq != NULL; acq = nextacq) { - nextacq = LIST_NEXT(acq, chain); - if (__LIST_CHAINED(acq)) { - LIST_REMOVE(acq, chain); - free(acq, M_IPSEC_SAQ); + for (spacq = LIST_FIRST(&V_spacqtree); spacq != NULL; + spacq = nextspacq) { + nextspacq = LIST_NEXT(spacq, chain); + if (__LIST_CHAINED(spacq)) { + LIST_REMOVE(spacq, chain); + free(spacq, M_IPSEC_SAQ); } } SPACQ_UNLOCK(); diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c index d84261e8249..f2e9d510e01 100644 --- a/sys/nfsserver/nfs_srvsubs.c +++ b/sys/nfsserver/nfs_srvsubs.c @@ -1128,6 +1128,9 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp, } } error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); + if (error != 0) + /* Make sure the server replies ESTALE to the client. */ + error = ESTALE; vfs_unbusy(mp); if (error) goto out; diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index f17874820b0..f470b5ef5ef 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -1172,11 +1172,7 @@ void (*cpu_idle_hook)(void) = cpu_idle_default; * Reset registers to default values on exec. */ void -exec_setregs(td, entry, stack, ps_strings) - struct thread *td; - u_long entry; - u_long stack; - u_long ps_strings; +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *regs = td->td_frame; struct pcb *pcb = td->td_pcb; @@ -1192,7 +1188,7 @@ exec_setregs(td, entry, stack, ps_strings) mtx_unlock_spin(&dt_lock); bzero((char *)regs, sizeof(struct trapframe)); - regs->tf_eip = entry; + regs->tf_eip = imgp->entry_addr; regs->tf_esp = stack; regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T); regs->tf_ss = _udatasel; @@ -1202,7 +1198,7 @@ exec_setregs(td, entry, stack, ps_strings) regs->tf_cs = _ucodesel; /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ - regs->tf_ebx = ps_strings; + regs->tf_ebx = imgp->ps_strings; /* * Reset the hardware debug registers if they were in use. diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index a9cf051b57f..49aae27cfe6 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -951,7 +951,7 @@ cpu_idle_wakeup(int cpu) * Set set up registers on exec. */ void -exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *tf; struct ps_strings arginfo; @@ -995,7 +995,7 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) tf->fixreg[7] = 0; /* termination vector */ tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ - tf->srr0 = entry; + tf->srr0 = imgp->entry_addr; tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; td->td_pcb->pcb_flags = 0; } diff --git a/sys/powerpc/aim/nexus.c b/sys/powerpc/aim/nexus.c index d92090b9cf4..54567b135c6 100644 --- a/sys/powerpc/aim/nexus.c +++ b/sys/powerpc/aim/nexus.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -74,7 +73,6 @@ #include -#include "clock_if.h" #include "ofw_bus_if.h" #include "pic_if.h" @@ -142,12 +140,6 @@ static const char *nexus_ofw_get_name(device_t, device_t); static const char *nexus_ofw_get_type(device_t, device_t); static const char *nexus_ofw_get_compat(device_t, device_t); -/* - * Clock interface. - */ -static int nexus_gettime(device_t, struct timespec *); -static int nexus_settime(device_t, struct timespec *); - /* * Local routines */ @@ -181,10 +173,6 @@ static device_method_t nexus_methods[] = { DEVMETHOD(ofw_bus_get_type, nexus_ofw_get_type), DEVMETHOD(ofw_bus_get_compat, nexus_ofw_get_compat), - /* Clock interface */ - DEVMETHOD(clock_gettime, nexus_gettime), - DEVMETHOD(clock_settime, nexus_settime), - { 0, 0 } }; @@ -240,7 +228,6 @@ nexus_attach(device_t dev) } - clock_register(dev, 1000); return (bus_generic_attach(dev)); } @@ -512,50 +499,3 @@ nexus_ofw_get_compat(device_t bus, device_t dev) return (dinfo->ndi_compatible); } -#define DIFF19041970 2082844800 - -static int -nexus_gettime(device_t dev, struct timespec *ts) -{ - char path[128]; - ihandle_t ih; - phandle_t ph; - u_int rtc; - - ph = OF_finddevice("rtc"); - if (ph == -1) - return (ENOENT); - - OF_package_to_path(ph, path, sizeof(path)); - ih = OF_open(path); - if (ih == -1) - return (ENXIO); - - if (OF_call_method("read-rtc", ih, 0, 1, &rtc)) - return (EIO); - - ts->tv_sec = rtc - DIFF19041970; - ts->tv_nsec = 0; - return (0); -} - -static int -nexus_settime(device_t dev, struct timespec *ts) -{ - char path[128]; - ihandle_t ih; - phandle_t ph; - u_int rtc; - - ph = OF_finddevice("rtc"); - if (ph == -1) - return (ENOENT); - - OF_package_to_path(ph, path, sizeof(path)); - ih = OF_open(path); - if (ih == -1) - return (ENXIO); - - rtc = ts->tv_sec + DIFF19041970; - return ((OF_call_method("write-rtc", ih, 1, 0, rtc) != 0) ? EIO : 0); -} diff --git a/sys/powerpc/aim/ofw_machdep.c b/sys/powerpc/aim/ofw_machdep.c index 6e276970edd..6e98f3e4fba 100644 --- a/sys/powerpc/aim/ofw_machdep.c +++ b/sys/powerpc/aim/ofw_machdep.c @@ -63,6 +63,8 @@ __FBSDID("$FreeBSD$"); static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3]; static struct mem_region OFfree[OFMEM_REGIONS + 3]; +static struct mtx ofw_mutex; + struct mem_region64 { vm_offset_t mr_start_hi; vm_offset_t mr_start_lo; @@ -281,6 +283,8 @@ OF_bootstrap() { boolean_t status = FALSE; + mtx_init(&ofw_mutex, "open firmware", NULL, MTX_DEF); + if (ofwcall != NULL) { if (ofw_real_mode) status = OF_install(OFW_STD_REAL, 0); @@ -314,6 +318,8 @@ openfirmware(void *args) if (pmap_bootstrapped && ofw_real_mode) args = (void *)pmap_kextract((vm_offset_t)args); + mtx_lock(&ofw_mutex); + __asm __volatile( "\t" "sync\n\t" "mfmsr %0\n\t" @@ -366,6 +372,8 @@ openfirmware(void *args) : : "r" (oldmsr) ); + mtx_unlock(&ofw_mutex); + return (result); } diff --git a/sys/powerpc/booke/interrupt.c b/sys/powerpc/booke/interrupt.c index 2367bf94b33..91ceeb7bf1d 100644 --- a/sys/powerpc/booke/interrupt.c +++ b/sys/powerpc/booke/interrupt.c @@ -123,6 +123,7 @@ powerpc_decr_interrupt(struct trapframe *framep) decr_intr(framep); atomic_subtract_int(&td->td_intr_nesting_level, 1); critical_exit(); + framep->srr1 &= ~PSL_WE; } /* @@ -135,4 +136,5 @@ powerpc_extr_interrupt(struct trapframe *framep) critical_enter(); PIC_DISPATCH(pic, framep); critical_exit(); + framep->srr1 &= ~PSL_WE; } diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c index d2e25e79ded..8a53b7355f9 100644 --- a/sys/powerpc/booke/machdep.c +++ b/sys/powerpc/booke/machdep.c @@ -509,7 +509,7 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) /* Set set up registers on exec. */ void -exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *tf; struct ps_strings arginfo; @@ -553,7 +553,7 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) tf->fixreg[7] = 0; /* termination vector */ tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ - tf->srr0 = entry; + tf->srr0 = imgp->entry_addr; tf->srr1 = PSL_USERSET; td->td_pcb->pcb_flags = 0; } @@ -706,6 +706,7 @@ cpu_idle (int busy) register_t msr; msr = mfmsr(); + #ifdef INVARIANTS if ((msr & PSL_EE) != PSL_EE) { struct thread *td = curthread; @@ -713,19 +714,10 @@ cpu_idle (int busy) panic("ints disabled in idleproc!"); } #endif -#if 0 - /* - * Freescale E500 core RM section 6.4.1 - */ - msr = msr | PSL_WE; - __asm__(" msync;" - " mtmsr %0;" - " isync;" - "loop: b loop" : - /* no output */ : - "r" (msr)); -#endif + /* Freescale E500 core RM section 6.4.1. */ + msr = msr | PSL_WE; + __asm __volatile("msync; mtmsr %0; isync" :: "r" (msr)); } int diff --git a/sys/powerpc/booke/trap_subr.S b/sys/powerpc/booke/trap_subr.S index 2e67725dc4f..b71f4bdb790 100644 --- a/sys/powerpc/booke/trap_subr.S +++ b/sys/powerpc/booke/trap_subr.S @@ -441,6 +441,7 @@ INTERRUPT(int_instr_storage) INTERRUPT(int_external_input) STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_EXI) + addi %r3, %r1, 8 bl CNAME(powerpc_extr_interrupt) b trapexit diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c index 2adec47b25b..6c6515e4be6 100644 --- a/sys/powerpc/mpc85xx/ocpbus.c +++ b/sys/powerpc/mpc85xx/ocpbus.c @@ -152,6 +152,10 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp) addr = 0xA0000000; size = 0x10000000; break; + case OCP85XX_TGTIF_PCI3: + addr = 0xB0000000; + size = 0x10000000; + break; default: return (EINVAL); } @@ -170,6 +174,10 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp) addr = 0xfee20000; size = 0x00010000; break; + case OCP85XX_TGTIF_PCI3: + addr = 0xfee30000; + size = 0x00010000; + break; default: return (EINVAL); } @@ -188,7 +196,7 @@ static int ocpbus_probe(device_t dev) { - device_set_desc(dev, "On-Chip Peripherals bus"); + device_set_desc(dev, "Freescale on-chip peripherals bus"); return (BUS_PROBE_DEFAULT); } @@ -210,6 +218,7 @@ ocpbus_attach(device_t dev) ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 0); ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 1); ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 2); + ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 3); ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 0); ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 1); ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 2); @@ -338,6 +347,10 @@ const struct ocp_resource mpc8555_resources[] = { OCP85XX_PCI_SIZE}, {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI2}, {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI2}, + {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_MEMORY, 0, OCP85XX_PCI3_OFF, + OCP85XX_PCI_SIZE}, + {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI3}, + {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI3}, {OCPBUS_DEVTYPE_LBC, 0, SYS_RES_MEMORY, 0, OCP85XX_LBC_OFF, OCP85XX_LBC_SIZE}, diff --git a/sys/powerpc/mpc85xx/ocpbus.h b/sys/powerpc/mpc85xx/ocpbus.h index 6aa6de3b063..fb715da5af1 100644 --- a/sys/powerpc/mpc85xx/ocpbus.h +++ b/sys/powerpc/mpc85xx/ocpbus.h @@ -50,6 +50,7 @@ #define OCP85XX_TGTIF_PCI0 0 #define OCP85XX_TGTIF_PCI1 1 #define OCP85XX_TGTIF_PCI2 2 +#define OCP85XX_TGTIF_PCI3 3 #define OCP85XX_TGTIF_LBC 4 #define OCP85XX_TGTIF_RAM_INTL 11 #define OCP85XX_TGTIF_RIO 12 @@ -86,6 +87,7 @@ #define OCP85XX_PCI0_OFF 0x08000 #define OCP85XX_PCI1_OFF 0x09000 #define OCP85XX_PCI2_OFF 0x0A000 +#define OCP85XX_PCI3_OFF 0x0B000 #define OCP85XX_PCI_SIZE 0x1000 #define OCP85XX_TSEC0_OFF 0x24000 #define OCP85XX_TSEC1_OFF 0x25000 diff --git a/sys/powerpc/mpc85xx/pci_ocp.c b/sys/powerpc/mpc85xx/pci_ocp.c index eba3f50d501..cdcf986b940 100644 --- a/sys/powerpc/mpc85xx/pci_ocp.c +++ b/sys/powerpc/mpc85xx/pci_ocp.c @@ -264,7 +264,7 @@ pci_ocp_maxslots(device_t dev) { struct pci_ocp_softc *sc = device_get_softc(dev); - return ((sc->sc_pcie_cap) ? 0 : 30); + return ((sc->sc_pcie_cap) ? 0 : 31); } static uint32_t @@ -328,6 +328,7 @@ pci_ocp_probe(device_t dev) return (ENXIO); sc = device_get_softc(dev); + sc->sc_dev = dev; sc->sc_rid = 0; sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, @@ -492,7 +493,7 @@ pci_ocp_route_int(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func, } static int -pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) +pci_ocp_init(struct pci_ocp_softc *sc, int bus, int nslots) { int secbus, slot; int func, maxfunc; @@ -502,7 +503,7 @@ pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) uint8_t intline, intpin; secbus = bus; - for (slot = 0; slot < maxslot; slot++) { + for (slot = 0; slot < nslots; slot++) { maxfunc = 0; for (func = 0; func <= maxfunc; func++) { hdrtype = pci_ocp_read_config(sc->sc_dev, bus, slot, @@ -599,7 +600,7 @@ pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) PCIR_SUBBUS_1, 0xff, 1); secbus = pci_ocp_init(sc, secbus, - (subclass == PCIS_BRIDGE_PCI) ? 31 : 1); + (subclass == PCIS_BRIDGE_PCI) ? 32 : 1); pci_ocp_write_config(sc->sc_dev, bus, slot, func, PCIR_SUBBUS_1, secbus, 1); @@ -721,7 +722,7 @@ pci_ocp_attach(device_t dev) { struct pci_ocp_softc *sc; uint32_t cfgreg; - int error, maxslot; + int error, nslots; sc = device_get_softc(dev); sc->sc_dev = dev; @@ -765,8 +766,8 @@ pci_ocp_attach(device_t dev) return (0); } - maxslot = (sc->sc_pcie_cap) ? 1 : 31; - pci_ocp_init(sc, sc->sc_busnr, maxslot); + nslots = (sc->sc_pcie_cap) ? 1 : 32; + pci_ocp_init(sc, sc->sc_busnr, nslots); device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); diff --git a/sys/powerpc/ofw/ofw_real.c b/sys/powerpc/ofw/ofw_real.c index a65ee91cf1b..094025c4194 100644 --- a/sys/powerpc/ofw/ofw_real.c +++ b/sys/powerpc/ofw/ofw_real.c @@ -273,7 +273,7 @@ ofw_real_init(ofw_t ofw, void *openfirm) static int ofw_real_test(ofw_t ofw, const char *name) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -304,7 +304,7 @@ ofw_real_test(ofw_t ofw, const char *name) static phandle_t ofw_real_peer(ofw_t ofw, phandle_t node) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -326,7 +326,7 @@ ofw_real_peer(ofw_t ofw, phandle_t node) static phandle_t ofw_real_child(ofw_t ofw, phandle_t node) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -348,7 +348,7 @@ ofw_real_child(ofw_t ofw, phandle_t node) static phandle_t ofw_real_parent(ofw_t ofw, phandle_t node) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -370,7 +370,7 @@ ofw_real_parent(ofw_t ofw, phandle_t node) static phandle_t ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -392,7 +392,7 @@ ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) static ssize_t ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -422,7 +422,7 @@ static ssize_t ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, size_t buflen) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -458,7 +458,7 @@ static int ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf, size_t size) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -493,7 +493,7 @@ static int ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, const void *buf, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -526,7 +526,7 @@ ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, static ssize_t ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -559,7 +559,7 @@ ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) static phandle_t ofw_real_finddevice(ofw_t ofw, const char *device) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -586,7 +586,7 @@ ofw_real_finddevice(ofw_t ofw, const char *device) static ssize_t ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -619,7 +619,7 @@ ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) static ssize_t ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -653,7 +653,7 @@ static int ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, int nargs, int nreturns, unsigned long *args_and_returns) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -701,7 +701,7 @@ ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, static ihandle_t ofw_real_open(ofw_t ofw, const char *device) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -729,7 +729,7 @@ ofw_real_open(ofw_t ofw, const char *device) static void ofw_real_close(ofw_t ofw, ihandle_t instance) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -747,7 +747,7 @@ ofw_real_close(ofw_t ofw, ihandle_t instance) static ssize_t ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -780,7 +780,7 @@ ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) static ssize_t ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -811,7 +811,7 @@ ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) static int ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -841,7 +841,7 @@ ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) static caddr_t ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -867,7 +867,7 @@ ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) static void ofw_real_release(ofw_t ofw, void *virt, size_t size) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -891,7 +891,7 @@ ofw_real_release(ofw_t ofw, void *virt, size_t size) static void ofw_real_enter(ofw_t ofw) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; @@ -907,7 +907,7 @@ ofw_real_enter(ofw_t ofw) static void ofw_real_exit(ofw_t ofw) { - static struct { + struct { cell_t name; cell_t nargs; cell_t nreturns; diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c index 56d0ca8da1d..d85cee55920 100644 --- a/sys/powerpc/ofw/ofw_syscons.c +++ b/sys/powerpc/ofw/ofw_syscons.c @@ -55,10 +55,10 @@ __FBSDID("$FreeBSD$"); #include #include -static int ofwfb_ignore_mmap_checks; +static int ofwfb_ignore_mmap_checks = 1; SYSCTL_NODE(_hw, OID_AUTO, ofwfb, CTLFLAG_RD, 0, "ofwfb"); SYSCTL_INT(_hw_ofwfb, OID_AUTO, relax_mmap, CTLFLAG_RW, - &ofwfb_ignore_mmap_checks, 0, "relax mmap bounds checking"); + &ofwfb_ignore_mmap_checks, 0, "relaxed mmap bounds checking"); extern u_char dflt_font_16[]; extern u_char dflt_font_14[]; diff --git a/sys/powerpc/powermac/cuda.c b/sys/powerpc/powermac/cuda.c index 203889c5675..230298e35c4 100644 --- a/sys/powerpc/powermac/cuda.c +++ b/sys/powerpc/powermac/cuda.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -55,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include +#include "clock_if.h" #include "cudavar.h" #include "viareg.h" @@ -72,6 +74,12 @@ static u_int cuda_poll(device_t dev); static void cuda_send_inbound(struct cuda_softc *sc); static void cuda_send_outbound(struct cuda_softc *sc); +/* + * Clock interface + */ +static int cuda_gettime(device_t dev, struct timespec *ts); +static int cuda_settime(device_t dev, struct timespec *ts); + static device_method_t cuda_methods[] = { /* Device interface */ DEVMETHOD(device_probe, cuda_probe), @@ -90,6 +98,10 @@ static device_method_t cuda_methods[] = { DEVMETHOD(adb_hb_controller_poll, cuda_poll), DEVMETHOD(adb_hb_set_autopoll_mask, cuda_adb_autopoll), + /* Clock interface */ + DEVMETHOD(clock_gettime, cuda_gettime), + DEVMETHOD(clock_settime, cuda_settime), + { 0, 0 }, }; @@ -173,6 +185,7 @@ cuda_attach(device_t dev) sc->sc_polling = 0; sc->sc_state = CUDA_NOTREADY; sc->sc_autopoll = 0; + sc->sc_rtc = -1; STAILQ_INIT(&sc->sc_inq); STAILQ_INIT(&sc->sc_outq); @@ -236,6 +249,8 @@ cuda_attach(device_t dev) } } + clock_register(dev, 1000); + return (bus_generic_attach(dev)); } @@ -444,8 +459,18 @@ cuda_send_inbound(struct cuda_softc *sc) break; case CUDA_PSEUDO: mtx_lock(&sc->sc_mutex); - if (pkt->data[0] == CMD_AUTOPOLL) + switch (pkt->data[1]) { + case CMD_AUTOPOLL: sc->sc_autopoll = 1; + break; + case CMD_READ_RTC: + memcpy(&sc->sc_rtc, &pkt->data[2], + sizeof(sc->sc_rtc)); + wakeup(&sc->sc_rtc); + break; + case CMD_WRITE_RTC: + break; + } mtx_unlock(&sc->sc_mutex); break; case CUDA_ERROR: @@ -715,3 +740,41 @@ cuda_adb_autopoll(device_t dev, uint16_t mask) { return (0); } +#define DIFF19041970 2082844800 + +static int +cuda_gettime(device_t dev, struct timespec *ts) +{ + struct cuda_softc *sc = device_get_softc(dev); + uint8_t cmd[] = {CUDA_PSEUDO, CMD_READ_RTC}; + + mtx_lock(&sc->sc_mutex); + sc->sc_rtc = -1; + cuda_send(sc, 1, 2, cmd); + if (sc->sc_rtc == -1) + mtx_sleep(&sc->sc_rtc, &sc->sc_mutex, 0, "rtc", 100); + + ts->tv_sec = sc->sc_rtc - DIFF19041970; + ts->tv_nsec = 0; + mtx_unlock(&sc->sc_mutex); + + return (0); +} + +static int +cuda_settime(device_t dev, struct timespec *ts) +{ + struct cuda_softc *sc = device_get_softc(dev); + uint8_t cmd[] = {CUDA_PSEUDO, CMD_WRITE_RTC, 0, 0, 0, 0}; + uint32_t sec; + + sec = ts->tv_sec + DIFF19041970; + memcpy(&cmd[2], &sec, sizeof(sec)); + + mtx_lock(&sc->sc_mutex); + cuda_send(sc, 0, 6, cmd); + mtx_unlock(&sc->sc_mutex); + + return (0); +} + diff --git a/sys/powerpc/powermac/cudavar.h b/sys/powerpc/powermac/cudavar.h index 02791cb08ed..225446494cd 100644 --- a/sys/powerpc/powermac/cudavar.h +++ b/sys/powerpc/powermac/cudavar.h @@ -90,6 +90,7 @@ struct cuda_softc { int sc_polling; int sc_iic_done; volatile int sc_autopoll; + uint32_t sc_rtc; int sc_i2c_read_len; diff --git a/sys/powerpc/powermac/pmu.c b/sys/powerpc/powermac/pmu.c index 9ddba9e055f..a980622e0d1 100644 --- a/sys/powerpc/powermac/pmu.c +++ b/sys/powerpc/powermac/pmu.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -55,16 +56,27 @@ __FBSDID("$FreeBSD$"); #include +#include "clock_if.h" #include "pmuvar.h" #include "viareg.h" /* - * MacIO interface + * Bus interface */ static int pmu_probe(device_t); static int pmu_attach(device_t); static int pmu_detach(device_t); +/* + * Clock interface + */ +static int pmu_gettime(device_t dev, struct timespec *ts); +static int pmu_settime(device_t dev, struct timespec *ts); + +/* + * ADB Interface + */ + static u_int pmu_adb_send(device_t dev, u_char command_byte, int len, u_char *data, u_char poll); static u_int pmu_adb_autopoll(device_t dev, uint16_t mask); @@ -110,6 +122,10 @@ static device_method_t pmu_methods[] = { DEVMETHOD(adb_hb_controller_poll, pmu_poll), DEVMETHOD(adb_hb_set_autopoll_mask, pmu_adb_autopoll), + /* Clock interface */ + DEVMETHOD(clock_gettime, pmu_gettime), + DEVMETHOD(clock_settime, pmu_settime), + { 0, 0 }, }; @@ -453,6 +469,12 @@ pmu_attach(device_t dev) sc->sc_leddev = led_create(pmu_set_sleepled, sc, "sleepled"); + /* + * Register RTC + */ + + clock_register(dev, 1000); + return (bus_generic_attach(dev)); } @@ -926,3 +948,38 @@ pmu_battquery_sysctl(SYSCTL_HANDLER_ARGS) return (error); } +#define DIFF19041970 2082844800 + +static int +pmu_gettime(device_t dev, struct timespec *ts) +{ + struct pmu_softc *sc = device_get_softc(dev); + uint8_t resp[16]; + uint32_t sec; + + mtx_lock(&sc->sc_mutex); + pmu_send(sc, PMU_READ_RTC, 0, NULL, 16, resp); + mtx_unlock(&sc->sc_mutex); + + memcpy(&sec, &resp[1], 4); + ts->tv_sec = sec - DIFF19041970; + ts->tv_nsec = 0; + + return (0); +} + +static int +pmu_settime(device_t dev, struct timespec *ts) +{ + struct pmu_softc *sc = device_get_softc(dev); + uint32_t sec; + + sec = ts->tv_sec + DIFF19041970; + + mtx_lock(&sc->sc_mutex); + pmu_send(sc, PMU_SET_RTC, sizeof(sec), (uint8_t *)&sec, 0, NULL); + mtx_unlock(&sc->sc_mutex); + + return (0); +} + diff --git a/sys/powerpc/powermac/smu.c b/sys/powerpc/powermac/smu.c index 6754b3ba7d1..10018767881 100644 --- a/sys/powerpc/powermac/smu.c +++ b/sys/powerpc/powermac/smu.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -51,6 +52,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include "clock_if.h" + struct smu_cmd { volatile uint8_t cmd; uint8_t len; @@ -140,6 +143,10 @@ static int smu_attach(device_t); static void smu_cpufreq_pre_change(device_t, const struct cf_level *level); static void smu_cpufreq_post_change(device_t, const struct cf_level *level); +/* clock interface */ +static int smu_gettime(device_t dev, struct timespec *ts); +static int smu_settime(device_t dev, struct timespec *ts); + /* utility functions */ static int smu_run_cmd(device_t dev, struct smu_cmd *cmd, int wait); static int smu_get_datablock(device_t dev, int8_t id, uint8_t *buf, @@ -160,6 +167,10 @@ static device_method_t smu_methods[] = { /* Device interface */ DEVMETHOD(device_probe, smu_probe), DEVMETHOD(device_attach, smu_attach), + + /* Clock interface */ + DEVMETHOD(clock_gettime, smu_gettime), + DEVMETHOD(clock_settime, smu_settime), { 0, 0 }, }; @@ -192,6 +203,9 @@ MALLOC_DEFINE(M_SMU, "smu", "SMU Sensor Information"); #define SMU_PWR_GET_POWERUP 0x00 #define SMU_PWR_SET_POWERUP 0x01 #define SMU_PWR_CLR_POWERUP 0x02 +#define SMU_RTC 0x8e +#define SMU_RTC_GET 0x81 +#define SMU_RTC_SET 0x80 /* Power event types */ #define SMU_WAKEUP_KEYPRESS 0x01 @@ -349,6 +363,11 @@ smu_attach(device_t dev) powerpc_config_intr(rman_get_start(sc->sc_doorbellirq), INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); + /* + * Connect RTC interface. + */ + clock_register(dev, 1000); + return (0); } @@ -1043,3 +1062,51 @@ smu_server_mode(SYSCTL_HANDLER_ARGS) return (smu_run_cmd(smu, &cmd, 1)); } +static int +smu_gettime(device_t dev, struct timespec *ts) +{ + struct smu_cmd cmd; + struct clocktime ct; + + cmd.cmd = SMU_RTC; + cmd.len = 1; + cmd.data[0] = SMU_RTC_GET; + + if (smu_run_cmd(dev, &cmd, 1) != 0) + return (ENXIO); + + ct.nsec = 0; + ct.sec = bcd2bin(cmd.data[0]); + ct.min = bcd2bin(cmd.data[1]); + ct.hour = bcd2bin(cmd.data[2]); + ct.dow = bcd2bin(cmd.data[3]); + ct.day = bcd2bin(cmd.data[4]); + ct.mon = bcd2bin(cmd.data[5]); + ct.year = bcd2bin(cmd.data[6]) + 2000; + + return (clock_ct_to_ts(&ct, ts)); +} + +static int +smu_settime(device_t dev, struct timespec *ts) +{ + struct smu_cmd cmd; + struct clocktime ct; + + cmd.cmd = SMU_RTC; + cmd.len = 8; + cmd.data[0] = SMU_RTC_SET; + + clock_ts_to_ct(ts, &ct); + + cmd.data[1] = bin2bcd(ct.sec); + cmd.data[2] = bin2bcd(ct.min); + cmd.data[3] = bin2bcd(ct.hour); + cmd.data[4] = bin2bcd(ct.dow); + cmd.data[5] = bin2bcd(ct.day); + cmd.data[6] = bin2bcd(ct.mon); + cmd.data[7] = bin2bcd(ct.year - 2000); + + return (smu_run_cmd(dev, &cmd, 1)); +} + diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c index d02c15687fc..555172a5e33 100644 --- a/sys/powerpc/powerpc/cpu.c +++ b/sys/powerpc/powerpc/cpu.c @@ -433,6 +433,13 @@ cpu_e500_setup(int cpuid, uint16_t vers) register_t hid0; hid0 = mfspr(SPR_HID0); + + /* Programe power-management mode. */ + hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); + hid0 |= HID0_DOZE; + + mtspr(SPR_HID0, hid0); + printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK); } diff --git a/sys/rpc/svc.c b/sys/rpc/svc.c index a59489457f6..8678a18a3a5 100644 --- a/sys/rpc/svc.c +++ b/sys/rpc/svc.c @@ -819,9 +819,11 @@ svc_getreq(SVCXPRT *xprt, struct svc_req **rqstp_ret) free(r->rq_addr, M_SONAME); r->rq_addr = NULL; } + m_freem(args); goto call_done; default: + m_freem(args); goto call_done; } } diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 9eab20fce39..a020fb8038f 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -969,7 +969,7 @@ ptrace_clear_single_step(struct thread *td) } void -exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *tf; struct pcb *pcb; @@ -992,8 +992,8 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) tf->tf_out[0] = stack; tf->tf_out[3] = p->p_sysent->sv_psstrings; tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); - tf->tf_tnpc = entry + 4; - tf->tf_tpc = entry; + tf->tf_tnpc = imgp->entry_addr + 4; + tf->tf_tpc = imgp->entry_addr; tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; td->td_retval[0] = tf->tf_out[0]; diff --git a/sys/sun4v/sun4v/machdep.c b/sys/sun4v/sun4v/machdep.c index 3913d35ca02..e14eebd9f8c 100644 --- a/sys/sun4v/sun4v/machdep.c +++ b/sys/sun4v/sun4v/machdep.c @@ -869,7 +869,7 @@ ptrace_clear_single_step(struct thread *td) } void -exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *tf; struct pcb *pcb; @@ -897,8 +897,8 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) tf->tf_out[3] = p->p_sysent->sv_psstrings; tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); - tf->tf_tnpc = entry + 4; - tf->tf_tpc = entry; + tf->tf_tnpc = imgp->entry_addr + 4; + tf->tf_tpc = imgp->entry_addr; tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; td->td_retval[0] = tf->tf_out[0]; diff --git a/sys/sys/_timespec.h b/sys/sys/_timespec.h index 9dcd5f8910d..d51559c2a41 100644 --- a/sys/sys/_timespec.h +++ b/sys/sys/_timespec.h @@ -31,26 +31,18 @@ * $FreeBSD$ */ -/* - * Prerequisite: - * - * This file must be kept synchronized with . - * It defines a structure which must be a type pun for - * `struct timespec'; this structure is used in header files where - * the ABI uses a `struct timespec' but standards prohibit its - * definition. (Currently only .) - * - * XXX should just declare struct __timespec as necessary. It's simple, - * so is easy to keep synchronized, and hopefully not needed in as many - * places as struct timespec, so we don't need this extra header. - * Perhaps we don't need timespec.h either. - */ - #ifndef _SYS__TIMESPEC_H_ #define _SYS__TIMESPEC_H_ -struct __timespec { - __time_t tv_sec; /* seconds */ +#include + +#ifndef _TIME_T_DECLARED +typedef __time_t time_t; +#define _TIME_T_DECLARED +#endif + +struct timespec { + time_t tv_sec; /* seconds */ long tv_nsec; /* and nanoseconds */ }; diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 79b389ebe38..1d1e3619e0e 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -56,6 +56,7 @@ struct image_params { struct vattr *attr; /* attributes of file */ const char *image_header; /* head of file to exec */ unsigned long entry_addr; /* entry address of target executable */ + unsigned long reloc_base; /* load address of image */ char vmspace_destroyed; /* flag - we've blown away original vm space */ char interpreted; /* flag - this executable is interpreted */ char opened; /* flag - we have opened executable vnode */ @@ -80,7 +81,7 @@ struct thread; int exec_check_permissions(struct image_params *); register_t *exec_copyout_strings(struct image_params *); int exec_new_vmspace(struct image_params *, struct sysentvec *); -void exec_setregs(struct thread *, u_long, u_long, u_long); +void exec_setregs(struct thread *, struct image_params *, u_long); int exec_shell_imgact(struct image_params *); int exec_copyin_args(struct image_args *, char *, enum uio_seg, char **, char **); diff --git a/sys/sys/param.h b/sys/sys/param.h index 11e3fa673b6..9f87ee2c21c 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 900009 /* Master, propagated to newvers */ +#define __FreeBSD_version 900010 /* Master, propagated to newvers */ #ifndef LOCORE #include diff --git a/sys/sys/stat.h b/sys/sys/stat.h index 856d674046d..1b03bd26c60 100644 --- a/sys/sys/stat.h +++ b/sys/sys/stat.h @@ -39,6 +39,7 @@ #define _SYS_STAT_H_ #include +#include #include #ifndef _BLKSIZE_T_DECLARED @@ -86,11 +87,6 @@ typedef __off_t off_t; #define _OFF_T_DECLARED #endif -#ifndef _TIME_T_DECLARED -typedef __time_t time_t; -#define _TIME_T_DECLARED -#endif - #ifndef _UID_T_DECLARED typedef __uid_t uid_t; #define _UID_T_DECLARED @@ -98,16 +94,11 @@ typedef __uid_t uid_t; #if !defined(_KERNEL) && __BSD_VISIBLE /* - * XXX we need this for struct timespec. We get miscellaneous namespace - * pollution with it. + * XXX We get miscellaneous namespace pollution with this. */ #include #endif -#if !__BSD_VISIBLE -#include -#endif - #if __BSD_VISIBLE struct ostat { __uint16_t st_dev; /* inode's device */ @@ -118,9 +109,9 @@ struct ostat { __uint16_t st_gid; /* group ID of the file's group */ __uint16_t st_rdev; /* device type */ __int32_t st_size; /* file size, in bytes */ - struct timespec st_atimespec; /* time of last access */ - struct timespec st_mtimespec; /* time of last data modification */ - struct timespec st_ctimespec; /* time of last file status change */ + struct timespec st_atim; /* time of last access */ + struct timespec st_mtim; /* time of last data modification */ + struct timespec st_ctim; /* time of last file status change */ __int32_t st_blksize; /* optimal blocksize for I/O */ __int32_t st_blocks; /* blocks allocated for file */ fflags_t st_flags; /* user defined flags for file */ @@ -136,28 +127,18 @@ struct stat { uid_t st_uid; /* user ID of the file's owner */ gid_t st_gid; /* group ID of the file's group */ __dev_t st_rdev; /* device type */ -#if __BSD_VISIBLE - struct timespec st_atimespec; /* time of last access */ - struct timespec st_mtimespec; /* time of last data modification */ - struct timespec st_ctimespec; /* time of last file status change */ -#else - time_t st_atime; /* time of last access */ - long __st_atimensec; /* nsec of last access */ - time_t st_mtime; /* time of last data modification */ - long __st_mtimensec; /* nsec of last data modification */ - time_t st_ctime; /* time of last file status change */ - long __st_ctimensec; /* nsec of last file status change */ -#endif + struct timespec st_atim; /* time of last access */ + struct timespec st_mtim; /* time of last data modification */ + struct timespec st_ctim; /* time of last file status change */ off_t st_size; /* file size, in bytes */ blkcnt_t st_blocks; /* blocks allocated for file */ blksize_t st_blksize; /* optimal blocksize for I/O */ fflags_t st_flags; /* user defined flags for file */ __uint32_t st_gen; /* file generation number */ __int32_t st_lspare; -#if __BSD_VISIBLE - struct timespec st_birthtimespec; /* time of file creation */ + struct timespec st_birthtim; /* time of file creation */ /* - * Explicitly pad st_birthtimespec to 16 bytes so that the size of + * Explicitly pad st_birthtim to 16 bytes so that the size of * struct stat is backwards compatible. We use bitfields instead * of an array of chars so that this doesn't require a C99 compiler * to compile if the size of the padding is 0. We use 2 bitfields @@ -166,12 +147,6 @@ struct stat { */ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec)); unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec)); -#else - time_t st_birthtime; /* time of file creation */ - long st_birthtimensec; /* nsec of file creation */ - unsigned int :(8 / 2) * (16 - (int)sizeof(struct __timespec)); - unsigned int :(8 / 2) * (16 - (int)sizeof(struct __timespec)); -#endif }; #if __BSD_VISIBLE @@ -183,15 +158,15 @@ struct nstat { uid_t st_uid; /* user ID of the file's owner */ gid_t st_gid; /* group ID of the file's group */ __dev_t st_rdev; /* device type */ - struct timespec st_atimespec; /* time of last access */ - struct timespec st_mtimespec; /* time of last data modification */ - struct timespec st_ctimespec; /* time of last file status change */ + struct timespec st_atim; /* time of last access */ + struct timespec st_mtim; /* time of last data modification */ + struct timespec st_ctim; /* time of last file status change */ off_t st_size; /* file size, in bytes */ blkcnt_t st_blocks; /* blocks allocated for file */ blksize_t st_blksize; /* optimal blocksize for I/O */ fflags_t st_flags; /* user defined flags for file */ __uint32_t st_gen; /* file generation number */ - struct timespec st_birthtimespec; /* time of file creation */ + struct timespec st_birthtim; /* time of file creation */ /* * See above about the following padding. */ @@ -200,13 +175,23 @@ struct nstat { }; #endif +#ifndef _KERNEL +#define st_atime st_atim.tv_sec +#define st_mtime st_mtim.tv_sec +#define st_ctime st_ctim.tv_sec #if __BSD_VISIBLE -#define st_atime st_atimespec.tv_sec -#define st_mtime st_mtimespec.tv_sec -#define st_ctime st_ctimespec.tv_sec -#define st_birthtime st_birthtimespec.tv_sec +#define st_birthtime st_birthtim.tv_sec #endif +/* For compatibility. */ +#if __BSD_VISIBLE +#define st_atimespec st_atim +#define st_mtimespec st_mtim +#define st_ctimespec st_ctim +#define st_birthtimespec st_birthtim +#endif +#endif /* !_KERNEL */ + #define S_ISUID 0004000 /* set user id on execution */ #define S_ISGID 0002000 /* set group id on execution */ #if __BSD_VISIBLE diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index 707c00bc444..c3a19d82d16 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -98,7 +98,8 @@ struct sysentvec { vm_offset_t sv_psstrings; /* PS_STRINGS */ int sv_stackprot; /* vm protection for stack */ register_t *(*sv_copyout_strings)(struct image_params *); - void (*sv_setregs)(struct thread *, u_long, u_long, u_long); + void (*sv_setregs)(struct thread *, struct image_params *, + u_long); void (*sv_fixlimit)(struct rlimit *, int); u_long *sv_maxssiz; u_int sv_flags; diff --git a/sys/sys/timespec.h b/sys/sys/timespec.h index 8986c094c6a..2505cef893e 100644 --- a/sys/sys/timespec.h +++ b/sys/sys/timespec.h @@ -31,22 +31,11 @@ * $FreeBSD$ */ -/* - * Prerequisites: , - */ - #ifndef _SYS_TIMESPEC_H_ #define _SYS_TIMESPEC_H_ -#ifndef _TIME_T_DECLARED -typedef __time_t time_t; -#define _TIME_T_DECLARED -#endif - -struct timespec { - time_t tv_sec; /* seconds */ - long tv_nsec; /* and nanoseconds */ -}; +#include +#include #if __BSD_VISIBLE #define TIMEVAL_TO_TIMESPEC(tv, ts) \ diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h index e04dd39afa3..27396ea077d 100644 --- a/sys/vm/uma_int.h +++ b/sys/vm/uma_int.h @@ -162,7 +162,11 @@ struct uma_hash { /* * align field or structure to cache line */ +#if defined(__amd64__) +#define UMA_ALIGN __aligned(CACHE_LINE_SIZE) +#else #define UMA_ALIGN +#endif /* * Structures for per cpu queues. @@ -173,7 +177,7 @@ struct uma_bucket { int16_t ub_cnt; /* Count of free items. */ int16_t ub_entries; /* Max items. */ void *ub_bucket[]; /* actual allocation storage */ -} UMA_ALIGN; +}; typedef struct uma_bucket * uma_bucket_t; @@ -330,7 +334,7 @@ struct uma_zone { * This HAS to be the last item because we adjust the zone size * based on NCPU and then allocate the space for the zones. */ - struct uma_cache uz_cpu[1] UMA_ALIGN; /* Per cpu caches */ + struct uma_cache uz_cpu[1]; /* Per cpu caches */ }; /* diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 4963a603833..a47cd6a0f88 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -233,7 +233,7 @@ mmap(td, uap) /* Make sure mapping fits into numeric range, etc. */ if ((uap->len == 0 && !SV_CURPROC_FLAG(SV_AOUT) && curproc->p_osrel >= 800104) || - ((flags & MAP_ANON) && uap->fd != -1)) + ((flags & MAP_ANON) && (uap->fd != -1 || pos != 0))) return (EINVAL); if (flags & MAP_STACK) { @@ -300,7 +300,6 @@ mmap(td, uap) handle = NULL; handle_type = OBJT_DEFAULT; maxprot = VM_PROT_ALL; - pos = 0; } else { /* * Mapping file, get fp for validation and