From 8233242d6d1b2b1fea14579e58464041fe56623d Mon Sep 17 00:00:00 2001 From: arybchik Date: Wed, 27 May 2015 08:57:48 +0000 Subject: [PATCH 01/65] sfxge: mask ifmedia options (pauses) when looking for matching mode Sponsored by: Solarflare Communications, Inc. MFC after: 2 days Differential Revision: https://reviews.freebsd.org/D2656 --- sys/dev/sfxge/sfxge_port.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/dev/sfxge/sfxge_port.c b/sys/dev/sfxge/sfxge_port.c index 7ee102ce361d..412f477254fd 100644 --- a/sys/dev/sfxge/sfxge_port.c +++ b/sys/dev/sfxge/sfxge_port.c @@ -822,6 +822,8 @@ sfxge_link_mode_to_phy_cap(efx_link_mode_t mode) static int sfxge_phy_cap_mask(struct sfxge_softc *sc, int ifmedia, uint32_t *phy_cap_mask) { + /* Get global options (duplex), type and subtype bits */ + int ifmedia_masked = ifmedia & (IFM_GMASK | IFM_NMASK | IFM_TMASK); efx_phy_media_type_t medium_type; boolean_t mode_found = B_FALSE; uint32_t cap_mask, mode_cap_mask; @@ -837,7 +839,7 @@ sfxge_phy_cap_mask(struct sfxge_softc *sc, int ifmedia, uint32_t *phy_cap_mask) efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask); for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) { - if (ifmedia == sfxge_link_mode[medium_type][mode]) { + if (ifmedia_masked == sfxge_link_mode[medium_type][mode]) { mode_found = B_TRUE; break; } @@ -848,8 +850,8 @@ sfxge_phy_cap_mask(struct sfxge_softc *sc, int ifmedia, uint32_t *phy_cap_mask) * If media is not in the table, it must be IFM_AUTO. */ KASSERT((cap_mask & (1 << EFX_PHY_CAP_AN)) && - ifmedia == (IFM_ETHER | IFM_AUTO), - ("%s: no mode for media %d", __func__, ifmedia)); + ifmedia_masked == (IFM_ETHER | IFM_AUTO), + ("%s: no mode for media %#x", __func__, ifmedia)); *phy_cap_mask = (cap_mask & ~(1 << EFX_PHY_CAP_ASYM)); return (0); } From ff588ae9b0b26872b719b8804f3ff9b0b2f3ca3e Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 27 May 2015 09:20:42 +0000 Subject: [PATCH 02/65] Currently, softupdate code detects overstepping on the workitems limits in the code which is deep in the call stack, and owns several critical system resources, like vnode locks. Attempt to wait while the per-mount softupdate thread cleans up the backlog may deadlock, because the thread might need to lock the same vnode which is owned by the waiting thread. Instead of synchronously waiting for the worker, perform the worker' tickle and pause until the backlog is cleaned, at the safe point during return from kernel to usermode. A new ast request to call softdep_ast_cleanup() is created, the SU code now only checks the size of queue and schedules ast. There is no ast delivery for the kernel threads, so they are exempted from the mechanism, except NFS daemon threads. NFS server loop explicitely checks for the request, and informs the schedule_cleanup() that it is capable of handling the requests by the process P2_AST_SU flag. This is needed because nfsd may be the sole cause of the SU workqueue overflow. But, to not cause nsfd to spawn additional threads just because we slow down existing workers, only tickle su threads, without waiting for the backlog cleanup. Reviewed by: jhb, mckusick Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/fs/nfsserver/nfs_nfsdkrpc.c | 10 +++ sys/kern/kern_exit.c | 6 ++ sys/kern/subr_trap.c | 7 ++ sys/sys/proc.h | 2 + sys/sys/systm.h | 2 + sys/ufs/ffs/ffs_softdep.c | 118 ++++++++++++++++++++++++++++---- 6 files changed, 131 insertions(+), 14 deletions(-) diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c index f9b8eb8e92e1..0f60686703f7 100644 --- a/sys/fs/nfsserver/nfs_nfsdkrpc.c +++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c @@ -294,6 +294,8 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) svc_freereq(rqst); out: + if (softdep_ast_cleanup != NULL) + softdep_ast_cleanup(); NFSEXITCODE(0); } @@ -464,6 +466,7 @@ int nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) { char principal[MAXHOSTNAMELEN + 5]; + struct proc *p; int error = 0; bool_t ret2, ret3, ret4; @@ -481,6 +484,10 @@ nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) */ NFSD_LOCK(); if (newnfs_numnfsd == 0) { + p = td->td_proc; + PROC_LOCK(p); + p->p_flag2 |= P2_AST_SU; + PROC_UNLOCK(p); newnfs_numnfsd++; NFSD_UNLOCK(); @@ -512,6 +519,9 @@ nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) NFSD_LOCK(); newnfs_numnfsd--; nfsrvd_init(1); + PROC_LOCK(p); + p->p_flag2 &= ~P2_AST_SU; + PROC_UNLOCK(p); } NFSD_UNLOCK(); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index caf31d7018a9..a2742c2cb8e3 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -204,6 +204,12 @@ exit1(struct thread *td, int rv) panic("Going nowhere without my init!"); } + /* + * Deref SU mp, since the thread does not return to userspace. + */ + if (softdep_ast_cleanup != NULL) + softdep_ast_cleanup(); + /* * MUST abort all other threads before proceeding past here. */ diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 93f7557aef63..82387c2d2d1e 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -86,6 +86,8 @@ __FBSDID("$FreeBSD$"); #include +void (*softdep_ast_cleanup)(void); + /* * Define the code needed before returning to user mode, for trap and * syscall. @@ -114,6 +116,9 @@ userret(struct thread *td, struct trapframe *frame) #ifdef KTRACE KTRUSERRET(td); #endif + if (softdep_ast_cleanup != NULL) + softdep_ast_cleanup(); + /* * If this thread tickled GEOM, we need to wait for the giggling to * stop before we return to userland @@ -157,6 +162,8 @@ userret(struct thread *td, struct trapframe *frame) ("userret: Returning while holding vnode reservation")); KASSERT((td->td_flags & TDF_SBDRY) == 0, ("userret: Returning with stop signals deferred")); + KASSERT(td->td_su == NULL, + ("userret: Returning with SU cleanup request not handled")); #ifdef VIMAGE /* Unfortunately td_vnet_lpush needs VNET_DEBUG. */ VNET_ASSERT(curvnet == NULL, diff --git a/sys/sys/proc.h b/sys/sys/proc.h index b44d8f1ca7c1..018b595fa9cc 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -277,6 +277,7 @@ struct thread { u_int td_vp_reserv; /* (k) Count of reserved vnodes. */ int td_no_sleeping; /* (k) Sleeping disabled count. */ int td_dom_rr_idx; /* (k) RR Numa domain selection. */ + void *td_su; /* (k) FFS SU private */ #define td_endzero td_sigmask /* Copied during fork1() or create_thread(). */ @@ -677,6 +678,7 @@ struct proc { #define P2_INHERIT_PROTECTED 0x00000001 /* New children get P_PROTECTED. */ #define P2_NOTRACE 0x00000002 /* No ptrace(2) attach or coredumps. */ #define P2_NOTRACE_EXEC 0x00000004 /* Keep P2_NOPTRACE on exec(2). */ +#define P2_AST_SU 0x00000008 /* Handles SU ast for kthreads. */ /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index acea565c0ab2..cb05a00008e7 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -431,4 +431,6 @@ void free_unr(struct unrhdr *uh, u_int item); void intr_prof_stack_use(struct thread *td, struct trapframe *frame); +extern void (*softdep_ast_cleanup)(void); + #endif /* !_SYS_SYSTM_H_ */ diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index ab2bd413820c..dc5d98ef9dc2 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -900,6 +900,8 @@ static int pagedep_find(struct pagedep_hashhead *, ino_t, ufs_lbn_t, struct pagedep **); static void pause_timer(void *); static int request_cleanup(struct mount *, int); +static void schedule_cleanup(struct mount *); +static void softdep_ast_cleanup_proc(void); static int process_worklist_item(struct mount *, int, int); static void process_removes(struct vnode *); static void process_truncates(struct vnode *); @@ -921,6 +923,8 @@ static int journal_unsuspend(struct ufsmount *ump); static void softdep_prelink(struct vnode *, struct vnode *); static void add_to_journal(struct worklist *); static void remove_from_journal(struct worklist *); +static bool softdep_excess_inodes(struct ufsmount *); +static bool softdep_excess_dirrem(struct ufsmount *); static void softdep_process_journal(struct mount *, struct worklist *, int); static struct jremref *newjremref(struct dirrem *, struct inode *, struct inode *ip, off_t, nlink_t); @@ -2209,12 +2213,10 @@ inodedep_lookup(mp, inum, flags, inodedeppp) * responsible for more than our share of that usage and * we are not in a rush, request some inodedep cleanup. */ - while (dep_current[D_INODEDEP] > max_softdeps && - (flags & NODELAY) == 0 && - ump->softdep_curdeps[D_INODEDEP] > - max_softdeps / stat_flush_threads) - request_cleanup(mp, FLUSH_INODES); - FREE_LOCK(ump); + if (softdep_excess_inodes(ump)) + schedule_cleanup(mp); + else + FREE_LOCK(ump); inodedep = malloc(sizeof(struct inodedep), M_INODEDEP, M_SOFTDEP_FLAGS); workitem_alloc(&inodedep->id_list, D_INODEDEP, mp); @@ -2412,6 +2414,7 @@ softdep_initialize() bioops.io_complete = softdep_disk_write_complete; bioops.io_deallocate = softdep_deallocate_dependencies; bioops.io_countdeps = softdep_count_dependencies; + softdep_ast_cleanup = softdep_ast_cleanup_proc; /* Initialize the callout with an mtx. */ callout_init_mtx(&softdep_callout, &lk, 0); @@ -2430,6 +2433,7 @@ softdep_uninitialize() bioops.io_complete = NULL; bioops.io_deallocate = NULL; bioops.io_countdeps = NULL; + softdep_ast_cleanup = NULL; callout_drain(&softdep_callout); } @@ -9126,13 +9130,12 @@ newdirrem(bp, dp, ip, isrmdir, prevdirremp) * the number of freefile and freeblks structures. */ ACQUIRE_LOCK(ip->i_ump); - while (!IS_SNAPSHOT(ip) && dep_current[D_DIRREM] > max_softdeps / 2 && - ip->i_ump->softdep_curdeps[D_DIRREM] > - (max_softdeps / 2) / stat_flush_threads) - (void) request_cleanup(ITOV(dp)->v_mount, FLUSH_BLOCKS); - FREE_LOCK(ip->i_ump); - dirrem = malloc(sizeof(struct dirrem), - M_DIRREM, M_SOFTDEP_FLAGS|M_ZERO); + if (!IS_SNAPSHOT(ip) && softdep_excess_dirrem(ip->i_ump)) + schedule_cleanup(ITOV(dp)->v_mount); + else + FREE_LOCK(ip->i_ump); + dirrem = malloc(sizeof(struct dirrem), M_DIRREM, M_SOFTDEP_FLAGS | + M_ZERO); workitem_alloc(&dirrem->dm_list, D_DIRREM, dvp->v_mount); LIST_INIT(&dirrem->dm_jremrefhd); LIST_INIT(&dirrem->dm_jwork); @@ -13269,6 +13272,92 @@ retry: return (1); } +static bool +softdep_excess_inodes(struct ufsmount *ump) +{ + + return (dep_current[D_INODEDEP] > max_softdeps && + ump->softdep_curdeps[D_INODEDEP] > max_softdeps / + stat_flush_threads); +} + +static bool +softdep_excess_dirrem(struct ufsmount *ump) +{ + + return (dep_current[D_DIRREM] > max_softdeps / 2 && + ump->softdep_curdeps[D_DIRREM] > (max_softdeps / 2) / + stat_flush_threads); +} + +static void +schedule_cleanup(struct mount *mp) +{ + struct ufsmount *ump; + struct thread *td; + + ump = VFSTOUFS(mp); + LOCK_OWNED(ump); + FREE_LOCK(ump); + td = curthread; + if ((td->td_pflags & TDP_KTHREAD) != 0 && + (td->td_proc->p_flag2 & P2_AST_SU) == 0) { + /* + * No ast is delivered to kernel threads, so nobody + * would deref the mp. Some kernel threads + * explicitely check for AST, e.g. NFS daemon does + * this in the serving loop. + */ + return; + } + if (td->td_su != NULL) + vfs_rel(td->td_su); + vfs_ref(mp); + td->td_su = mp; + thread_lock(td); + td->td_flags |= TDF_ASTPENDING; + thread_unlock(td); +} + +static void +softdep_ast_cleanup_proc(void) +{ + struct thread *td; + struct mount *mp; + struct ufsmount *ump; + int error; + bool req; + + td = curthread; + mp = td->td_su; + if (mp == NULL) + return; + td->td_su = NULL; + error = vfs_busy(mp, MBF_NOWAIT); + vfs_rel(mp); + if (error != 0) + return; + if (ffs_own_mount(mp) && MOUNTEDSOFTDEP(mp)) { + ump = VFSTOUFS(mp); + for (;;) { + req = false; + ACQUIRE_LOCK(ump); + if (softdep_excess_inodes(ump)) { + req = true; + request_cleanup(mp, FLUSH_INODES); + } + if (softdep_excess_dirrem(ump)) { + req = true; + request_cleanup(mp, FLUSH_BLOCKS); + } + FREE_LOCK(ump); + if ((td->td_pflags & TDP_KTHREAD) != 0 || !req) + break; + } + } + vfs_unbusy(mp); +} + /* * If memory utilization has gotten too high, deliberately slow things * down and speed up the I/O processing. @@ -13355,7 +13444,8 @@ request_cleanup(mp, resource) callout_reset(&softdep_callout, tickdelay > 2 ? tickdelay : 2, pause_timer, 0); - msleep((caddr_t)&proc_waiting, &lk, PPAUSE, "softupdate", 0); + if ((td->td_pflags & TDP_KTHREAD) == 0) + msleep((caddr_t)&proc_waiting, &lk, PPAUSE, "softupdate", 0); proc_waiting -= 1; FREE_GBLLOCK(&lk); ACQUIRE_LOCK(ump); From 260b7bb2591a59fccbee5832cc083c39d7cf2bba Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 27 May 2015 09:21:47 +0000 Subject: [PATCH 03/65] Add V_MNTREF flag to the vn_start_write(9) and vn_start_secondary_write(9) functions. The flag indicates that the caller already owns a reference on the mount point, and the functions can consume it. The reference is released by vn_finished_write(9) and vn_finished_secondary_write(9) in due course. Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/kern/vfs_vnops.c | 28 ++++++++++++++++------------ sys/sys/vnode.h | 1 + 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 01d448edf698..a00da5151b48 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1646,16 +1646,18 @@ unlock: } int -vn_start_write(vp, mpp, flags) - struct vnode *vp; - struct mount **mpp; - int flags; +vn_start_write(struct vnode *vp, struct mount **mpp, int flags) { struct mount *mp; int error; - if (!vn_suspendable(vp, mpp)) + KASSERT((flags & V_MNTREF) == 0 || (*mpp != NULL && vp == NULL), + ("V_MNTREF requires mp")); + if (!vn_suspendable(vp, mpp)) { + if ((flags & V_MNTREF) != 0) + vfs_rel(*mpp); return (0); + } error = 0; /* @@ -1681,7 +1683,7 @@ vn_start_write(vp, mpp, flags) * emulate a vfs_ref(). */ MNT_ILOCK(mp); - if (vp == NULL) + if (vp == NULL && (flags & V_MNTREF) == 0) MNT_REF(mp); return (vn_start_write_locked(mp, flags)); @@ -1695,16 +1697,18 @@ vn_start_write(vp, mpp, flags) * time, these operations are halted until the suspension is over. */ int -vn_start_secondary_write(vp, mpp, flags) - struct vnode *vp; - struct mount **mpp; - int flags; +vn_start_secondary_write(struct vnode *vp, struct mount **mpp, int flags) { struct mount *mp; int error; - if (!vn_suspendable(vp, mpp)) + KASSERT((flags & V_MNTREF) == 0 || (*mpp != NULL && vp == NULL), + ("V_MNTREF requires mp")); + if (!vn_suspendable(vp, mpp)) { + if ((flags & V_MNTREF) != 0) + vfs_rel(*mpp); return (0); + } retry: if (vp != NULL) { @@ -1730,7 +1734,7 @@ vn_start_secondary_write(vp, mpp, flags) * emulate a vfs_ref(). */ MNT_ILOCK(mp); - if (vp == NULL) + if (vp == NULL && (flags & V_MNTREF) == 0) MNT_REF(mp); if ((mp->mnt_kern_flag & (MNTK_SUSPENDED | MNTK_SUSPEND2)) == 0) { mp->mnt_secondary_writes++; diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index d70aa579c1b1..a30130fe4b79 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -397,6 +397,7 @@ extern int vttoif_tab[]; #define V_WAIT 0x0001 /* vn_start_write: sleep for suspend */ #define V_NOWAIT 0x0002 /* vn_start_write: don't sleep for suspend */ #define V_XSLEEP 0x0004 /* vn_start_write: just return after sleep */ +#define V_MNTREF 0x0010 /* vn_start_write: mp is already ref-ed */ #define VR_START_WRITE 0x0001 /* vfs_write_resume: start write atomically */ #define VR_NO_SUSPCLR 0x0002 /* vfs_write_resume: do not clear suspension */ From d77dbf3761f318998d4f01063cea23ad73dc7bdf Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 27 May 2015 09:22:50 +0000 Subject: [PATCH 04/65] Right now, dounmount() is called with unreferenced mount point. Nothing stops a parallel unmount to suceed before the given call to dounmount() checks and locks the covered vnode. Prevent dounmount() from acting on the freed (although type-stable) memory by changing the interface to require the mount point to be referenced. dounmount() consumes the reference on return, regardless of the sucessfull or erronous result. Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- .../uts/common/fs/zfs/zfs_ctldir.c | 1 + .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 1 + .../uts/common/fs/zfs/zfs_vfsops.c | 1 + sys/kern/vfs_mount.c | 30 +++++++++---------- sys/kern/vfs_subr.c | 3 +- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c index 9e0b8a0998c3..c2dd020b4c0d 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c @@ -697,6 +697,7 @@ zfsctl_unmount_snap(zfs_snapentry_t *sep, int fflags, cred_t *cr) return (0); #else + vfs_ref(vn_mountedvfs(svp)); return (dounmount(vn_mountedvfs(svp), fflags, curthread)); #endif } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index d4291ec8d30d..5800db0c310b 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -3481,6 +3481,7 @@ zfs_unmount_snap(const char *snapname) #ifdef illumos (void) dounmount(vfsp, MS_FORCE, kcred); #else + vfs_ref(vfsp); (void) dounmount(vfsp, MS_FORCE, curthread); #endif return (0); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index 5824828c7a07..c44516f175fd 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -2315,6 +2315,7 @@ bail: * unmount this file system. */ if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) + vfs_ref(zfsvfs->z_vfs); (void) dounmount(zfsvfs->z_vfs, MS_FORCE, curthread); } return (err); diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 09fa7ed071bf..c86259b11637 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1128,12 +1128,7 @@ struct unmount_args { #endif /* ARGSUSED */ int -sys_unmount(td, uap) - struct thread *td; - register struct unmount_args /* { - char *path; - int flags; - } */ *uap; +sys_unmount(struct thread *td, struct unmount_args *uap) { struct nameidata nd; struct mount *mp; @@ -1164,8 +1159,10 @@ sys_unmount(td, uap) mtx_lock(&mountlist_mtx); TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) { if (mp->mnt_stat.f_fsid.val[0] == id0 && - mp->mnt_stat.f_fsid.val[1] == id1) + mp->mnt_stat.f_fsid.val[1] == id1) { + vfs_ref(mp); break; + } } mtx_unlock(&mountlist_mtx); } else { @@ -1183,8 +1180,10 @@ sys_unmount(td, uap) } mtx_lock(&mountlist_mtx); TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) { - if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0) + if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0) { + vfs_ref(mp); break; + } } mtx_unlock(&mountlist_mtx); } @@ -1202,8 +1201,10 @@ sys_unmount(td, uap) /* * Don't allow unmounting the root filesystem. */ - if (mp->mnt_flag & MNT_ROOTFS) + if (mp->mnt_flag & MNT_ROOTFS) { + vfs_rel(mp); return (EINVAL); + } error = dounmount(mp, uap->flags, td); return (error); } @@ -1212,10 +1213,7 @@ sys_unmount(td, uap) * Do the actual filesystem unmount. */ int -dounmount(mp, flags, td) - struct mount *mp; - int flags; - struct thread *td; +dounmount(struct mount *mp, int flags, struct thread *td) { struct vnode *coveredvp, *fsrootvp; int error; @@ -1235,6 +1233,7 @@ dounmount(mp, flags, td) if (coveredvp->v_mountedhere != mp || coveredvp->v_mountedhere->mnt_gen != mnt_gen_r) { VOP_UNLOCK(coveredvp, 0); + vfs_rel(mp); return (EBUSY); } } @@ -1243,13 +1242,14 @@ dounmount(mp, flags, td) * original mount is permitted to unmount this filesystem. */ error = vfs_suser(mp, td); - if (error) { + if (error != 0) { if (coveredvp) VOP_UNLOCK(coveredvp, 0); + vfs_rel(mp); return (error); } - vn_start_write(NULL, &mp, V_WAIT); + vn_start_write(NULL, &mp, V_WAIT | V_MNTREF); MNT_ILOCK(mp); if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 || !TAILQ_EMPTY(&mp->mnt_uppers)) { diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 8e34456621ca..625d193b2c1b 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -3502,8 +3502,9 @@ vfs_unmountall(void) */ while(!TAILQ_EMPTY(&mountlist)) { mp = TAILQ_LAST(&mountlist, mntlist); + vfs_ref(mp); error = dounmount(mp, MNT_FORCE, td); - if (error) { + if (error != 0) { TAILQ_REMOVE(&mountlist, mp, mnt_list); /* * XXX: Due to the way in which we mount the root From b5e9f683a34cfae11787f6a95077454b1af3d30c Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 27 May 2015 09:49:04 +0000 Subject: [PATCH 05/65] After r283600, NODELAY flag to inodedep_lookup() function is unused. Eliminate it, and simplify code by removing the local dflags variable always initialized to DEPALLOC. Noted by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ffs/ffs_softdep.c | 55 ++++++++++++--------------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index dc5d98ef9dc2..b0005f1d2b2c 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -2063,7 +2063,6 @@ retry_flush: * allocates a new structure if an existing one is not found. */ #define DEPALLOC 0x0001 /* allocate structure if lookup fails */ -#define NODELAY 0x0002 /* cannot do background work */ /* * Structures and routines associated with pagedep caching. @@ -4635,14 +4634,10 @@ inodedep_lookup_ip(ip) struct inode *ip; { struct inodedep *inodedep; - int dflags; KASSERT(ip->i_nlink >= ip->i_effnlink, ("inodedep_lookup_ip: bad delta")); - dflags = DEPALLOC; - if (IS_SNAPSHOT(ip)) - dflags |= NODELAY; - (void) inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, dflags, + (void) inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, DEPALLOC, &inodedep); inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink; KASSERT((inodedep->id_state & UNLINKED) == 0, ("inode unlinked")); @@ -5042,7 +5037,7 @@ softdep_setup_inomapdep(bp, ip, newinum, mode) M_BMSAFEMAP, M_SOFTDEP_FLAGS); workitem_alloc(&bmsafemap->sm_list, D_BMSAFEMAP, mp); ACQUIRE_LOCK(ip->i_ump); - if ((inodedep_lookup(mp, newinum, DEPALLOC | NODELAY, &inodedep))) + if ((inodedep_lookup(mp, newinum, DEPALLOC, &inodedep))) panic("softdep_setup_inomapdep: dependency %p for new" "inode already exists", inodedep); bmsafemap = bmsafemap_lookup(mp, bp, ino_to_cg(fs, newinum), bmsafemap); @@ -5339,7 +5334,7 @@ softdep_setup_allocdirect(ip, off, newblkno, oldblkno, newsize, oldsize, bp) if (freefrag && freefrag->ff_jdep != NULL && freefrag->ff_jdep->wk_type == D_JFREEFRAG) add_to_journal(freefrag->ff_jdep); - inodedep_lookup(mp, ip->i_number, DEPALLOC | NODELAY, &inodedep); + inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep); adp->ad_inodedep = inodedep; WORKLIST_INSERT(&bp->b_dep, &newblk->nb_list); @@ -5697,7 +5692,7 @@ softdep_setup_allocext(ip, off, newblkno, oldblkno, newsize, oldsize, bp) if (freefrag && freefrag->ff_jdep != NULL && freefrag->ff_jdep->wk_type == D_JFREEFRAG) add_to_journal(freefrag->ff_jdep); - inodedep_lookup(mp, ip->i_number, DEPALLOC | NODELAY, &inodedep); + inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep); adp->ad_inodedep = inodedep; WORKLIST_INSERT(&bp->b_dep, &newblk->nb_list); @@ -5822,7 +5817,6 @@ softdep_setup_allocindir_page(ip, lbn, bp, ptrno, newblkno, oldblkno, nbp) struct allocindir *aip; struct pagedep *pagedep; struct mount *mp; - int dflags; mp = UFSTOVFS(ip->i_ump); KASSERT(MOUNTEDSOFTDEP(mp) != 0, @@ -5835,10 +5829,7 @@ softdep_setup_allocindir_page(ip, lbn, bp, ptrno, newblkno, oldblkno, nbp) "lbn %jd", ip->i_number, newblkno, oldblkno, lbn); ASSERT_VOP_LOCKED(ITOV(ip), "softdep_setup_allocindir_page"); aip = newallocindir(ip, ptrno, newblkno, oldblkno, lbn); - dflags = DEPALLOC; - if (IS_SNAPSHOT(ip)) - dflags |= NODELAY; - (void) inodedep_lookup(mp, ip->i_number, dflags, &inodedep); + (void) inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep); /* * If we are allocating a directory page, then we must * allocate an associated pagedep to track additions and @@ -5868,7 +5859,6 @@ softdep_setup_allocindir_meta(nbp, ip, bp, ptrno, newblkno) struct inodedep *inodedep; struct allocindir *aip; ufs_lbn_t lbn; - int dflags; KASSERT(MOUNTEDSOFTDEP(UFSTOVFS(ip->i_ump)) != 0, ("softdep_setup_allocindir_meta called on non-softdep filesystem")); @@ -5878,10 +5868,8 @@ softdep_setup_allocindir_meta(nbp, ip, bp, ptrno, newblkno) lbn = nbp->b_lblkno; ASSERT_VOP_LOCKED(ITOV(ip), "softdep_setup_allocindir_meta"); aip = newallocindir(ip, ptrno, newblkno, 0, lbn); - dflags = DEPALLOC; - if (IS_SNAPSHOT(ip)) - dflags |= NODELAY; - inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, dflags, &inodedep); + inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, DEPALLOC, + &inodedep); WORKLIST_INSERT(&nbp->b_dep, &aip->ai_block.nb_list); if (setup_allocindir_phase2(bp, ip, inodedep, aip, lbn)) panic("softdep_setup_allocindir_meta: Block already existed"); @@ -6494,7 +6482,7 @@ softdep_journal_freeblocks(ip, cred, length, flags) struct mount *mp; ufs2_daddr_t extblocks, datablocks; ufs_lbn_t tmpval, lbn, lastlbn; - int frags, lastoff, iboff, allocblock, needj, dflags, error, i; + int frags, lastoff, iboff, allocblock, needj, error, i; fs = ip->i_fs; ump = ip->i_ump; @@ -6515,10 +6503,7 @@ softdep_journal_freeblocks(ip, cred, length, flags) * we don't need to journal the block frees. The canceled journals * for the allocations will suffice. */ - dflags = DEPALLOC; - if (IS_SNAPSHOT(ip)) - dflags |= NODELAY; - inodedep_lookup(mp, ip->i_number, dflags, &inodedep); + inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep); if ((inodedep->id_state & (UNLINKED | DEPCOMPLETE)) == UNLINKED && length == 0) needj = 0; @@ -6648,7 +6633,7 @@ softdep_journal_freeblocks(ip, cred, length, flags) *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2; ACQUIRE_LOCK(ump); - (void) inodedep_lookup(mp, ip->i_number, dflags, &inodedep); + (void) inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep); if ((inodedep->id_state & IOSTARTED) != 0) panic("softdep_setup_freeblocks: inode busy"); /* @@ -6741,7 +6726,7 @@ softdep_journal_freeblocks(ip, cred, length, flags) } ACQUIRE_LOCK(ump); - inodedep_lookup(mp, ip->i_number, dflags, &inodedep); + inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep); TAILQ_INSERT_TAIL(&inodedep->id_freeblklst, freeblks, fb_next); freeblks->fb_state |= DEPCOMPLETE | ONDEPLIST; /* @@ -6832,7 +6817,7 @@ softdep_setup_freeblocks(ip, length, flags) struct fs *fs; ufs2_daddr_t extblocks, datablocks; struct mount *mp; - int i, delay, error, dflags; + int i, delay, error; ufs_lbn_t tmpval; ufs_lbn_t lbn; @@ -6901,10 +6886,7 @@ softdep_setup_freeblocks(ip, length, flags) * Find and eliminate any inode dependencies. */ ACQUIRE_LOCK(ump); - dflags = DEPALLOC; - if (IS_SNAPSHOT(ip)) - dflags |= NODELAY; - (void) inodedep_lookup(mp, ip->i_number, dflags, &inodedep); + (void) inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep); if ((inodedep->id_state & IOSTARTED) != 0) panic("softdep_setup_freeblocks: inode busy"); /* @@ -8510,7 +8492,7 @@ softdep_setup_directory_add(bp, dp, diroffset, newinum, newdirbp, isnewblk) dap->da_pagedep = pagedep; LIST_INSERT_HEAD(&pagedep->pd_diraddhd[DIRADDHASH(offset)], dap, da_pdlist); - inodedep_lookup(mp, newinum, DEPALLOC | NODELAY, &inodedep); + inodedep_lookup(mp, newinum, DEPALLOC, &inodedep); /* * If we're journaling, link the diradd into the jaddref so it * may be completed after the journal entry is written. Otherwise, @@ -9371,7 +9353,7 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir) * inode is not yet written. If it is written, do the post-inode * write processing to put it on the id_pendinghd list. */ - inodedep_lookup(mp, newinum, DEPALLOC | NODELAY, &inodedep); + inodedep_lookup(mp, newinum, DEPALLOC, &inodedep); if (MOUNTEDSUJ(mp)) { jaddref = (struct jaddref *)TAILQ_LAST(&inodedep->id_inoreflst, inoreflst); @@ -9413,15 +9395,12 @@ softdep_change_linkcnt(ip) struct inode *ip; /* the inode with the increased link count */ { struct inodedep *inodedep; - int dflags; KASSERT(MOUNTEDSOFTDEP(UFSTOVFS(ip->i_ump)) != 0, ("softdep_change_linkcnt called on non-softdep filesystem")); ACQUIRE_LOCK(ip->i_ump); - dflags = DEPALLOC; - if (IS_SNAPSHOT(ip)) - dflags |= NODELAY; - inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, dflags, &inodedep); + inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, DEPALLOC, + &inodedep); if (ip->i_nlink < ip->i_effnlink) panic("softdep_change_linkcnt: bad delta"); inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink; From 167672d7cdaca94e84f6790d7675eb001622191e Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 27 May 2015 09:50:18 +0000 Subject: [PATCH 06/65] Enabled rewritten PCID support by default. Sponsored by: The FreeBSD Foundation MFC after: 1 month --- sys/amd64/amd64/pmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 118bb340594c..5f9ee9166286 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -381,7 +381,7 @@ caddr_t CADDR1 = 0; static int pmap_flags = PMAP_PDE_SUPERPAGE; /* flags for x86 pmaps */ -int pmap_pcid_enabled = 0; +int pmap_pcid_enabled = 1; SYSCTL_INT(_vm_pmap, OID_AUTO, pcid_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &pmap_pcid_enabled, 0, "Is TLB Context ID enabled ?"); int invpcid_works = 0; From f05af1ea393c55377e4f0cf63101a0e54c38e5ec Mon Sep 17 00:00:00 2001 From: pluknet Date: Wed, 27 May 2015 10:08:31 +0000 Subject: [PATCH 07/65] Document recent p_flag2 additions. --- bin/ps/ps.1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index 369e1d72b56a..c777a6be2800 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -29,7 +29,7 @@ .\" @(#)ps.1 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd May 22, 2015 +.Dd May 27, 2015 .Dt PS 1 .Os .Sh NAME @@ -350,6 +350,9 @@ the include file .In sys/proc.h : .Bl -column P2_INHERIT_PROTECTED 0x00000001 .It Dv "P2_INHERIT_PROTECTED" Ta No "0x00000001" Ta "New children get P_PROTECTED" +.It Dv "P2_NOTRACE" Ta No "0x00000002" Ta "No ptrace(2) attach or coredumps" +.It Dv "P2_NOTRACE_EXEC" Ta No "0x00000004" Ta "Keep P2_NOPTRACE on exec(2)" +.It Dv "P2_AST_SU" Ta No "0x00000008" Ta "Handles SU ast for kthreads" .El .It Cm label The MAC label of the process. From 30a2ce21019a342bd31ce1cf566642567c284a0c Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 27 May 2015 13:42:28 +0000 Subject: [PATCH 08/65] Add SIOCGI2C ioctl support to the driver. Would work only on ConnectX-3 with fresh firmware. The low level code is based on code provided by Mellanox. Thanks to Mellanox and their distributor Must (http://mustcompany.ru) for providing hardware. In collaboration with: Andre Melkoumian Reviewed by: hselasky Sponsored by: Netflix Sponsored by: Nginx, Inc. --- sys/ofed/drivers/net/mlx4/en_netdev.c | 23 ++++ sys/ofed/drivers/net/mlx4/port.c | 157 ++++++++++++++++++++++++++ sys/ofed/include/linux/mlx4/device.h | 23 ++++ 3 files changed, 203 insertions(+) diff --git a/sys/ofed/drivers/net/mlx4/en_netdev.c b/sys/ofed/drivers/net/mlx4/en_netdev.c index 5988c0da4c59..d8b2f4fbdea0 100644 --- a/sys/ofed/drivers/net/mlx4/en_netdev.c +++ b/sys/ofed/drivers/net/mlx4/en_netdev.c @@ -1967,6 +1967,29 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data) mutex_unlock(&mdev->state_lock); VLAN_CAPABILITIES(dev); break; + case SIOCGI2C: { + struct ifi2creq i2c; + + error = copyin(ifr->ifr_data, &i2c, sizeof(i2c)); + if (error) + break; + if (i2c.len > sizeof(i2c.data)) { + error = EINVAL; + break; + } + /* + * Note that we ignore i2c.addr here. The driver hardcodes + * the address to 0x50, while standard expects it to be 0xA0. + */ + error = mlx4_get_module_info(mdev->dev, priv->port, + i2c.offset, i2c.len, i2c.data); + if (error < 0) { + error = -error; + break; + } + error = copyout(&i2c, ifr->ifr_data, sizeof(i2c)); + break; + } default: error = ether_ioctl(dev, command, data); break; diff --git a/sys/ofed/drivers/net/mlx4/port.c b/sys/ofed/drivers/net/mlx4/port.c index c653d4ba35c2..4d7aa0ba90e5 100644 --- a/sys/ofed/drivers/net/mlx4/port.c +++ b/sys/ofed/drivers/net/mlx4/port.c @@ -1058,3 +1058,160 @@ int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id, u } EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave); +/* Cable Module Info */ +#define MODULE_INFO_MAX_READ 48 + +#define I2C_ADDR_LOW 0x50 +#define I2C_ADDR_HIGH 0x51 +#define I2C_PAGE_SIZE 256 + +/* Module Info Data */ +struct mlx4_cable_info { + u8 i2c_addr; + u8 page_num; + __be16 dev_mem_address; + __be16 reserved1; + __be16 size; + __be32 reserved2[2]; + u8 data[MODULE_INFO_MAX_READ]; +}; + +enum cable_info_err { + CABLE_INF_INV_PORT = 0x1, + CABLE_INF_OP_NOSUP = 0x2, + CABLE_INF_NOT_CONN = 0x3, + CABLE_INF_NO_EEPRM = 0x4, + CABLE_INF_PAGE_ERR = 0x5, + CABLE_INF_INV_ADDR = 0x6, + CABLE_INF_I2C_ADDR = 0x7, + CABLE_INF_QSFP_VIO = 0x8, + CABLE_INF_I2C_BUSY = 0x9, +}; + +#define MAD_STATUS_2_CABLE_ERR(mad_status) ((mad_status >> 8) & 0xFF) + +#ifdef DEBUG +static inline const char *cable_info_mad_err_str(u16 mad_status) +{ + u8 err = MAD_STATUS_2_CABLE_ERR(mad_status); + + switch (err) { + case CABLE_INF_INV_PORT: + return "invalid port selected"; + case CABLE_INF_OP_NOSUP: + return "operation not supported for this port (the port is of type CX4 or internal)"; + case CABLE_INF_NOT_CONN: + return "cable is not connected"; + case CABLE_INF_NO_EEPRM: + return "the connected cable has no EPROM (passive copper cable)"; + case CABLE_INF_PAGE_ERR: + return "page number is greater than 15"; + case CABLE_INF_INV_ADDR: + return "invalid device_address or size (that is, size equals 0 or address+size is greater than 256)"; + case CABLE_INF_I2C_ADDR: + return "invalid I2C slave address"; + case CABLE_INF_QSFP_VIO: + return "at least one cable violates the QSFP specification and ignores the modsel signal"; + case CABLE_INF_I2C_BUSY: + return "I2C bus is constantly busy"; + } + return "Unknown Error"; +} +#endif /* DEBUG */ + +/** + * mlx4_get_module_info - Read cable module eeprom data + * @dev: mlx4_dev. + * @port: port number. + * @offset: byte offset in eeprom to start reading data from. + * @size: num of bytes to read. + * @data: output buffer to put the requested data into. + * + * Reads cable module eeprom data, puts the outcome data into + * data pointer paramer. + * Returns num of read bytes on success or a negative error + * code. + */ +int mlx4_get_module_info(struct mlx4_dev *dev, u8 port, u16 offset, + u16 size, u8 *data) +{ + struct mlx4_cmd_mailbox *inbox, *outbox; + struct mlx4_mad_ifc *inmad, *outmad; + struct mlx4_cable_info *cable_info; + u16 i2c_addr; + int ret; + + if (size > MODULE_INFO_MAX_READ) + size = MODULE_INFO_MAX_READ; + + inbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(inbox)) + return PTR_ERR(inbox); + + outbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(outbox)) { + mlx4_free_cmd_mailbox(dev, inbox); + return PTR_ERR(outbox); + } + + inmad = (struct mlx4_mad_ifc *)(inbox->buf); + outmad = (struct mlx4_mad_ifc *)(outbox->buf); + + inmad->method = 0x1; /* Get */ + inmad->class_version = 0x1; + inmad->mgmt_class = 0x1; + inmad->base_version = 0x1; + inmad->attr_id = cpu_to_be16(0xFF60); /* Module Info */ + + if (offset < I2C_PAGE_SIZE && offset + size > I2C_PAGE_SIZE) + /* Cross pages reads are not allowed + * read until offset 256 in low page + */ + size -= offset + size - I2C_PAGE_SIZE; + + i2c_addr = I2C_ADDR_LOW; + if (offset >= I2C_PAGE_SIZE) { + /* Reset offset to high page */ + i2c_addr = I2C_ADDR_HIGH; + offset -= I2C_PAGE_SIZE; + } + + cable_info = (struct mlx4_cable_info *)inmad->data; + cable_info->dev_mem_address = cpu_to_be16(offset); + cable_info->page_num = 0; + cable_info->i2c_addr = i2c_addr; + cable_info->size = cpu_to_be16(size); + + ret = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3, + MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); + if (ret) + goto out; + + if (be16_to_cpu(outmad->status)) { + /* Mad returned with bad status */ + ret = be16_to_cpu(outmad->status); +#ifdef DEBUG + mlx4_warn(dev, "MLX4_CMD_MAD_IFC Get Module info attr(%x) " + "port(%d) i2c_addr(%x) offset(%d) size(%d): Response " + "Mad Status(%x) - %s\n", 0xFF60, port, i2c_addr, offset, + size, ret, cable_info_mad_err_str(ret)); +#endif + if (i2c_addr == I2C_ADDR_HIGH && + MAD_STATUS_2_CABLE_ERR(ret) == CABLE_INF_I2C_ADDR) + /* Some SFP cables do not support i2c slave + * address 0x51 (high page), abort silently. + */ + ret = 0; + else + ret = -ret; + goto out; + } + cable_info = (struct mlx4_cable_info *)outmad->data; + memcpy(data, cable_info->data, size); + ret = size; +out: + mlx4_free_cmd_mailbox(dev, inbox); + mlx4_free_cmd_mailbox(dev, outbox); + return ret; +} +EXPORT_SYMBOL(mlx4_get_module_info); diff --git a/sys/ofed/include/linux/mlx4/device.h b/sys/ofed/include/linux/mlx4/device.h index 8c0db91f49ac..536c421132c7 100644 --- a/sys/ofed/include/linux/mlx4/device.h +++ b/sys/ofed/include/linux/mlx4/device.h @@ -892,6 +892,26 @@ struct mlx4_init_port_param { u64 si_guid; }; +#define MAD_IFC_DATA_SZ 192 +/* MAD IFC Mailbox */ +struct mlx4_mad_ifc { + u8 base_version; + u8 mgmt_class; + u8 class_version; + u8 method; + __be16 status; + __be16 class_specific; + __be64 tid; + __be16 attr_id; + __be16 resv; + __be32 attr_mod; + __be64 mkey; + __be16 dr_slid; + __be16 dr_dlid; + u8 reserved[28]; + u8 data[MAD_IFC_DATA_SZ]; +} __packed; + #define mlx4_foreach_port(port, dev, type) \ for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \ if ((type) == (dev)->caps.port_mask[(port)]) @@ -1294,4 +1314,7 @@ int mlx4_read_clock(struct mlx4_dev *dev); int mlx4_get_internal_clock_params(struct mlx4_dev *dev, struct mlx4_clock_params *params); +int mlx4_get_module_info(struct mlx4_dev *dev, u8 port, + u16 offset, u16 size, u8 *data); + #endif /* MLX4_DEVICE_H */ From f9f0a47b0f607509ca1264cb71eb3cfdcfeef403 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 27 May 2015 13:54:37 +0000 Subject: [PATCH 09/65] Use the cpuset API more consistently: - Fetch the root set from cpuset_getaffinity() instead of assuming all CPUs from 0 to hw.ncpu are the root set. - Use CPU_SETSIZE and CPU_FFS. - The original notion of halted CPUs the manpage and code refers to is gone. Use the term "available" instead. Differential Revision: https://reviews.freebsd.org/D2491 Reviewed by: emaste MFC after: 1 week --- usr.sbin/pmcstat/pmcstat.8 | 6 ++--- usr.sbin/pmcstat/pmcstat.c | 45 +++++++++++++++----------------------- 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/usr.sbin/pmcstat/pmcstat.8 b/usr.sbin/pmcstat/pmcstat.8 index 647824101cbc..25ff7a6d9ffd 100644 --- a/usr.sbin/pmcstat/pmcstat.8 +++ b/usr.sbin/pmcstat/pmcstat.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 8, 2015 +.Dd May 27, 2015 .Dt PMCSTAT 8 .Os .Sh NAME @@ -246,8 +246,8 @@ Argument .Ar cpu-spec is a comma separated list of CPU numbers, or the literal .Sq * -denoting all unhalted CPUs. -The default is to allocate system mode PMCs on all unhalted +denoting all available CPUs. +The default is to allocate system mode PMCs on all available CPUs. .It Fl d Toggle between process mode PMCs measuring events for the target diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c index c7f36bc6f26a..c51c5fa6daf0 100644 --- a/usr.sbin/pmcstat/pmcstat.c +++ b/usr.sbin/pmcstat/pmcstat.c @@ -116,11 +116,10 @@ struct pmcstat_args args; static void pmcstat_clone_event_descriptor(struct pmcstat_ev *ev, const cpuset_t *cpumask) { - int cpu, mcpu; + int cpu; struct pmcstat_ev *ev_clone; - mcpu = sizeof(*cpumask) * NBBY; - for (cpu = 0; cpu < mcpu; cpu++) { + for (cpu = 0; cpu < CPU_SETSIZE; cpu++) { if (!CPU_ISSET(cpu, cpumask)) continue; @@ -161,6 +160,7 @@ pmcstat_get_cpumask(const char *cpuspec, cpuset_t *cpumask) CPU_SET(cpu, cpumask); s = end + strspn(end, ", \t"); } while (*s); + assert(!CPU_EMPTY(cpumask)); } void @@ -550,10 +550,10 @@ pmcstat_topexit(void) int main(int argc, char **argv) { - cpuset_t cpumask; + cpuset_t cpumask, rootmask; double interval; double duration; - int hcpu, option, npmc, ncpu; + int option, npmc; int c, check_driver_stats, current_sampling_count; int do_callchain, do_descendants, do_logproccsw, do_logprocexit; int do_print, do_read; @@ -618,14 +618,13 @@ main(int argc, char **argv) err(EX_OSERR, "ERROR: Cannot determine path of running kernel"); /* - * The initial CPU mask specifies all non-halted CPUS in the - * system. + * The initial CPU mask specifies the root mask of this process + * which is usually all CPUs in the system. */ - len = sizeof(int); - if (sysctlbyname("hw.ncpu", &ncpu, &len, NULL, 0) < 0) - err(EX_OSERR, "ERROR: Cannot determine the number of CPUs"); - for (hcpu = 0; hcpu < ncpu; hcpu++) - CPU_SET(hcpu, &cpumask); + if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1, + sizeof(rootmask), &rootmask) == -1) + err(EX_OSERR, "ERROR: Cannot determine the root set of CPUs"); + CPU_COPY(&rootmask, &cpumask); while ((option = getopt(argc, argv, "CD:EF:G:M:NO:P:R:S:TWa:c:df:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1) @@ -642,11 +641,9 @@ main(int argc, char **argv) break; case 'c': /* CPU */ - - if (optarg[0] == '*' && optarg[1] == '\0') { - for (hcpu = 0; hcpu < ncpu; hcpu++) - CPU_SET(hcpu, &cpumask); - } else + if (optarg[0] == '*' && optarg[1] == '\0') + CPU_COPY(&rootmask, &cpumask); + else pmcstat_get_cpumask(optarg, &cpumask); args.pa_flags |= FLAGS_HAS_CPUMASK; @@ -771,13 +768,9 @@ main(int argc, char **argv) else ev->ev_count = -1; - if (option == 'S' || option == 's') { - hcpu = sizeof(cpumask) * NBBY; - for (hcpu--; hcpu >= 0; hcpu--) - if (CPU_ISSET(hcpu, &cpumask)) - break; - ev->ev_cpu = hcpu; - } else + if (option == 'S' || option == 's') + ev->ev_cpu = CPU_FFS(&cpumask); + else ev->ev_cpu = PMC_CPU_ANY; ev->ev_flags = 0; @@ -804,11 +797,9 @@ main(int argc, char **argv) STAILQ_INSERT_TAIL(&args.pa_events, ev, ev_next); if (option == 's' || option == 'S') { - hcpu = CPU_ISSET(ev->ev_cpu, &cpumask); CPU_CLR(ev->ev_cpu, &cpumask); pmcstat_clone_event_descriptor(ev, &cpumask); - if (hcpu != 0) - CPU_SET(ev->ev_cpu, &cpumask); + CPU_SET(ev->ev_cpu, &cpumask); } break; From abf78a3a279a4db8cb4d6cc74dae9ae4c35003e4 Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 27 May 2015 14:05:46 +0000 Subject: [PATCH 10/65] Move counter.h include into ieee80211_freebsd.h. Should fix build. Submitted by: Zilvinas Valinskas --- sys/net80211/ieee80211_crypto.c | 2 -- sys/net80211/ieee80211_crypto_ccmp.c | 1 - sys/net80211/ieee80211_crypto_none.c | 3 +-- sys/net80211/ieee80211_crypto_tkip.c | 1 - sys/net80211/ieee80211_crypto_wep.c | 1 - sys/net80211/ieee80211_freebsd.h | 4 +++- sys/net80211/ieee80211_hwmp.c | 1 - sys/net80211/ieee80211_ratectl_none.c | 1 - 8 files changed, 4 insertions(+), 10 deletions(-) diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c index e4656cc42bac..d338506edafd 100644 --- a/sys/net80211/ieee80211_crypto.c +++ b/sys/net80211/ieee80211_crypto.c @@ -33,8 +33,6 @@ __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include -#include -#include #include #include #include diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c index e005a6564af0..89ca6d07e8e7 100644 --- a/sys/net80211/ieee80211_crypto_ccmp.c +++ b/sys/net80211/ieee80211_crypto_ccmp.c @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/net80211/ieee80211_crypto_none.c b/sys/net80211/ieee80211_crypto_none.c index b28b7db050ee..b1ffbb48aa48 100644 --- a/sys/net80211/ieee80211_crypto_none.c +++ b/sys/net80211/ieee80211_crypto_none.c @@ -32,9 +32,8 @@ __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include -#include -#include #include +#include #include #include diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c index c10dfd524075..c6d2f541c87a 100644 --- a/sys/net80211/ieee80211_crypto_tkip.c +++ b/sys/net80211/ieee80211_crypto_tkip.c @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/net80211/ieee80211_crypto_wep.c b/sys/net80211/ieee80211_crypto_wep.c index 675bb80df0dc..587cf39ce35d 100644 --- a/sys/net80211/ieee80211_crypto_wep.c +++ b/sys/net80211/ieee80211_crypto_wep.c @@ -33,7 +33,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index f9517da78006..0241720f7916 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -28,7 +28,9 @@ #define _NET80211_IEEE80211_FREEBSD_H_ #ifdef _KERNEL -#include +#include +#include +#include #include #include #include diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 436ccd87671a..6bbc32c634dc 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/net80211/ieee80211_ratectl_none.c b/sys/net80211/ieee80211_ratectl_none.c index de7195d7264f..5a45a74ea7a3 100644 --- a/sys/net80211/ieee80211_ratectl_none.c +++ b/sys/net80211/ieee80211_ratectl_none.c @@ -30,7 +30,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include From aa01a21e0c7d20fb276cc0628a159a595e0e617e Mon Sep 17 00:00:00 2001 From: emaste Date: Wed, 27 May 2015 14:28:19 +0000 Subject: [PATCH 11/65] Update to ELF Tool Chain r3223 Highlights (upstream revisions): - Fix SHT_GROUP handling in elfcopy/strip (3206 3220 3221) - Misc elfcopy / strip bug fixes (3215 3216 3217) - Many C++ demangler improvements (3199 3200 3201 3202 3203 3204 3205 3208 3210 3211 3212) - Improve GNU binutils compatibility in elfcopy / strip (3213 3214) - Add -g option to readelf(1): dump contents of section groups (3219) - Add EM_IAMCU 32-bit Intel MCU (3198) Also add a compat #define for building with older FreeBSD ELF headers. The GRP_COMDAT flag was added to elf_common.h in r283110, but it's not available during the bootstrap build. It is also convenient to be able to build on older hosts. Thanks to antoine@ for tracking down issues through multiple exp-runs and to kaiw@ for fixing. PR: 198611 (exp-run), 200350 Sponsored by: The FreeBSD Foundation --- contrib/elftoolchain/common/_elftc.h | 5 +- contrib/elftoolchain/common/elfdefinitions.h | 3 +- contrib/elftoolchain/elfcopy/elfcopy.h | 3 +- contrib/elftoolchain/elfcopy/main.c | 20 +- contrib/elftoolchain/elfcopy/sections.c | 81 ++- contrib/elftoolchain/elfcopy/symbols.c | 94 +++- .../elftoolchain/libdwarf/libdwarf_reloc.c | 3 +- .../elftoolchain/libelftc/libelftc_dem_gnu3.c | 480 ++++++++++++++++-- contrib/elftoolchain/libelftc/os.Linux.mk | 4 +- contrib/elftoolchain/readelf/readelf.1 | 4 +- contrib/elftoolchain/readelf/readelf.c | 71 ++- lib/libelftc/elftc_version.c | 2 +- 12 files changed, 692 insertions(+), 78 deletions(-) diff --git a/contrib/elftoolchain/common/_elftc.h b/contrib/elftoolchain/common/_elftc.h index 45f0abd80774..6769519a16d6 100644 --- a/contrib/elftoolchain/common/_elftc.h +++ b/contrib/elftoolchain/common/_elftc.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _elftc.h 3175 2015-03-27 17:21:24Z emaste $ + * $Id: _elftc.h 3209 2015-05-17 13:40:46Z kaiwang27 $ */ /** @@ -342,12 +342,13 @@ struct name { \ #if defined(__GLIBC__) || defined(__linux__) - +#ifndef _GNU_SOURCE /* * GLIBC based systems have a global 'char *' pointer referencing * the executable's name. */ extern const char *program_invocation_short_name; +#endif /* !_GNU_SOURCE */ #define ELFTC_GETPROGNAME() program_invocation_short_name diff --git a/contrib/elftoolchain/common/elfdefinitions.h b/contrib/elftoolchain/common/elfdefinitions.h index a53acde8b6ce..58554fef2ebf 100644 --- a/contrib/elftoolchain/common/elfdefinitions.h +++ b/contrib/elftoolchain/common/elfdefinitions.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elfdefinitions.h 3178 2015-03-30 18:29:13Z emaste $ + * $Id: elfdefinitions.h 3198 2015-05-14 18:36:19Z emaste $ */ /* @@ -565,6 +565,7 @@ _ELF_DEFINE_EM(EM_SPARC, 2, "SPARC") \ _ELF_DEFINE_EM(EM_386, 3, "Intel 80386") \ _ELF_DEFINE_EM(EM_68K, 4, "Motorola 68000") \ _ELF_DEFINE_EM(EM_88K, 5, "Motorola 88000") \ +_ELF_DEFINE_EM(EM_IAMCU, 6, "Intel MCU") \ _ELF_DEFINE_EM(EM_860, 7, "Intel 80860") \ _ELF_DEFINE_EM(EM_MIPS, 8, "MIPS I Architecture") \ _ELF_DEFINE_EM(EM_S370, 9, "IBM System/370 Processor") \ diff --git a/contrib/elftoolchain/elfcopy/elfcopy.h b/contrib/elftoolchain/elfcopy/elfcopy.h index b750246d850d..48574b55c65b 100644 --- a/contrib/elftoolchain/elfcopy/elfcopy.h +++ b/contrib/elftoolchain/elfcopy/elfcopy.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elfcopy.h 3173 2015-03-27 16:46:13Z emaste $ + * $Id: elfcopy.h 3221 2015-05-24 23:42:43Z kaiwang27 $ */ #include @@ -237,6 +237,7 @@ struct elfcopy { uint64_t *secndx; /* section index map. */ uint64_t *symndx; /* symbol index map. */ unsigned char *v_rel; /* symbols needed by relocation. */ + unsigned char *v_grp; /* symbols refered by section group. */ unsigned char *v_secsym; /* sections with section symbol. */ STAILQ_HEAD(, segment) v_seg; /* list of segments. */ STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */ diff --git a/contrib/elftoolchain/elfcopy/main.c b/contrib/elftoolchain/elfcopy/main.c index a48aea589748..cbd48d3fc4b9 100644 --- a/contrib/elftoolchain/elfcopy/main.c +++ b/contrib/elftoolchain/elfcopy/main.c @@ -39,7 +39,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: main.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: main.c 3216 2015-05-23 21:16:36Z kaiwang27 $"); enum options { @@ -404,8 +404,19 @@ create_elf(struct elfcopy *ecp) * Insert SHDR table into the internal section list as a "pseudo" * section, so later it will get sorted and resynced just as "normal" * sections. + * + * Under FreeBSD, Binutils objcopy always put the section header + * at the end of all the sections. We want to do the same here. + * + * However, note that the behaviour is still different with Binutils: + * elfcopy checks the FreeBSD OSABI tag to tell whether it needs to + * move the section headers, while Binutils is probably configured + * this way when it's compiled on FreeBSD. */ - shtab = insert_shtab(ecp, 0); + if (oeh.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) + shtab = insert_shtab(ecp, 1); + else + shtab = insert_shtab(ecp, 0); /* * Resync section offsets in the output object. This is needed @@ -485,6 +496,11 @@ free_elf(struct elfcopy *ecp) free(sec); } } + + if (ecp->secndx != NULL) { + free(ecp->secndx); + ecp->secndx = NULL; + } } /* Create a temporary file. */ diff --git a/contrib/elftoolchain/elfcopy/sections.c b/contrib/elftoolchain/elfcopy/sections.c index 7c43a3577f2f..a407a4274718 100644 --- a/contrib/elftoolchain/elfcopy/sections.c +++ b/contrib/elftoolchain/elfcopy/sections.c @@ -34,7 +34,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: sections.c 3185 2015-04-11 08:56:34Z kaiwang27 $"); +ELFTC_VCSID("$Id: sections.c 3220 2015-05-24 23:42:39Z kaiwang27 $"); static void add_gnu_debuglink(struct elfcopy *ecp); static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); @@ -56,6 +56,7 @@ static void print_data(const char *d, size_t sz); static void print_section(struct section *s); static void *read_section(struct section *s, size_t *size); static void update_reloc(struct elfcopy *ecp, struct section *s); +static void update_section_group(struct elfcopy *ecp, struct section *s); int is_remove_section(struct elfcopy *ecp, const char *name) @@ -552,6 +553,14 @@ copy_content(struct elfcopy *ecp) (s->type == SHT_REL || s->type == SHT_RELA)) filter_reloc(ecp, s); + /* + * The section indices in the SHT_GROUP section needs + * to be updated since we might have stripped some + * sections and changed section numbering. + */ + if (s->type == SHT_GROUP) + update_section_group(ecp, s); + if (is_modify_section(ecp, s->name)) modify_section(ecp, s); @@ -571,6 +580,71 @@ copy_content(struct elfcopy *ecp) } } + +/* + * Update section group section. The section indices in the SHT_GROUP + * section need update after section numbering changed. + */ +static void +update_section_group(struct elfcopy *ecp, struct section *s) +{ + GElf_Shdr ish; + Elf_Data *id; + uint32_t *ws, *wd; + uint64_t n; + size_t ishnum; + int i, j; + + if (!elf_getshnum(ecp->ein, &ishnum)) + errx(EXIT_FAILURE, "elf_getshnum failed: %s", + elf_errmsg(-1)); + + if (gelf_getshdr(s->is, &ish) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + if ((id = elf_getdata(s->is, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_getdata() failed: %s", + elf_errmsg(-1)); + + if (ish.sh_size == 0) + return; + + if (ish.sh_entsize == 0) + ish.sh_entsize = 4; + + ws = id->d_buf; + + /* We only support COMDAT section. */ +#ifndef GRP_COMDAT +#define GRP_COMDAT 0x1 +#endif + if ((*ws & GRP_COMDAT) == 0) + return; + + if ((s->buf = malloc(ish.sh_size)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + + s->sz = ish.sh_size; + + wd = s->buf; + + /* Copy the flag word as-is. */ + *wd = *ws; + + /* Update the section indices. */ + n = ish.sh_size / ish.sh_entsize; + for(i = 1, j = 1; (uint64_t)i < n; i++) { + if (ws[i] != SHN_UNDEF && ws[i] < ishnum && + ecp->secndx[ws[i]] != 0) + wd[j++] = ecp->secndx[ws[i]]; + else + s->sz -= 4; + } + + s->nocopy = 1; +} + /* * Filter relocation entries, only keep those entries whose * symbol is in the keep list. @@ -1028,8 +1102,11 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, osh.sh_flags |= SHF_WRITE; if (sec_flags & SF_CODE) osh.sh_flags |= SHF_EXECINSTR; - } else + } else { osh.sh_flags = ish.sh_flags; + if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) + osh.sh_flags |= SHF_INFO_LINK; + } } if (name == NULL) diff --git a/contrib/elftoolchain/elfcopy/symbols.c b/contrib/elftoolchain/elfcopy/symbols.c index 4a7d38a10812..05bcd7a8e2f8 100644 --- a/contrib/elftoolchain/elfcopy/symbols.c +++ b/contrib/elftoolchain/elfcopy/symbols.c @@ -33,7 +33,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: symbols.c 3191 2015-05-04 17:07:01Z jkoshy $"); +ELFTC_VCSID("$Id: symbols.c 3222 2015-05-24 23:47:23Z kaiwang27 $"); /* Symbol table buffer structure. */ struct symbuf { @@ -77,7 +77,8 @@ static int is_weak_symbol(unsigned char st_info); static int lookup_exact_string(hash_head *hash, const char *buf, const char *s); static int generate_symbols(struct elfcopy *ecp); -static void mark_symbols(struct elfcopy *ecp, size_t sc); +static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc); +static void mark_section_group_symbols(struct elfcopy *ecp, size_t sc); static int match_wildcard(const char *name, const char *pattern); uint32_t str_hash(const char *s); @@ -160,6 +161,10 @@ is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s) if (BIT_ISSET(ecp->v_rel, i)) return (1); + /* Symbols refered by COMDAT sections are needed. */ + if (BIT_ISSET(ecp->v_grp, i)) + return (1); + /* * For relocatable files (.o files), global and weak symbols * are needed. @@ -207,7 +212,10 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, return (1); if (ecp->v_rel == NULL) - mark_symbols(ecp, sc); + mark_reloc_symbols(ecp, sc); + + if (ecp->v_grp == NULL) + mark_section_group_symbols(ecp, sc); if (is_needed_symbol(ecp, i, s)) return (0); @@ -233,7 +241,7 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, * Mark symbols refered by relocation entries. */ static void -mark_symbols(struct elfcopy *ecp, size_t sc) +mark_reloc_symbols(struct elfcopy *ecp, size_t sc) { const char *name; Elf_Data *d; @@ -311,6 +319,49 @@ mark_symbols(struct elfcopy *ecp, size_t sc) elf_errmsg(elferr)); } +static void +mark_section_group_symbols(struct elfcopy *ecp, size_t sc) +{ + const char *name; + Elf_Scn *s; + GElf_Shdr sh; + size_t indx; + int elferr; + + ecp->v_grp = calloc((sc + 7) / 8, 1); + if (ecp->v_grp == NULL) + err(EXIT_FAILURE, "calloc failed"); + + if (elf_getshstrndx(ecp->ein, &indx) == 0) + errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", + elf_errmsg(-1)); + + s = NULL; + while ((s = elf_nextscn(ecp->ein, s)) != NULL) { + if (gelf_getshdr(s, &sh) != &sh) + errx(EXIT_FAILURE, "elf_getshdr failed: %s", + elf_errmsg(-1)); + + if (sh.sh_type != SHT_GROUP) + continue; + + if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + if (is_remove_section(ecp, name)) + continue; + + if (sh.sh_info > 0 && sh.sh_info < sc) + BIT_SET(ecp->v_grp, sh.sh_info); + else if (sh.sh_info != 0) + warnx("invalid symbox index"); + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_nextscn failed: %s", + elf_errmsg(elferr)); +} + static int generate_symbols(struct elfcopy *ecp) { @@ -351,6 +402,8 @@ generate_symbols(struct elfcopy *ecp) ecp->symtab->buf = sy_buf; ecp->strtab->buf = st_buf; + gsym = NULL; + /* * Create bit vector v_secsym, which is used to mark sections * that already have corresponding STT_SECTION symbols. @@ -384,7 +437,7 @@ generate_symbols(struct elfcopy *ecp) /* Symbol table should exist if this function is called. */ if (symndx == 0) { warnx("can't find .strtab section"); - return (0); + goto clean; } /* Locate .symtab of input object. */ @@ -413,7 +466,6 @@ generate_symbols(struct elfcopy *ecp) * output object, it is used by update_reloc() later to update * relocation information. */ - gsym = NULL; sc = ish.sh_size / ish.sh_entsize; if (sc > 0) { ecp->symndx = calloc(sc, sizeof(*ecp->symndx)); @@ -427,7 +479,7 @@ generate_symbols(struct elfcopy *ecp) if (elferr != 0) errx(EXIT_FAILURE, "elf_getdata failed: %s", elf_errmsg(elferr)); - return (0); + goto clean; } } else return (0); @@ -523,7 +575,7 @@ generate_symbols(struct elfcopy *ecp) * check if that only local symbol is the reserved symbol. */ if (sy_buf->nls <= 1 && sy_buf->ngs == 0) - return (0); + goto clean; /* * Create STT_SECTION symbols for sections that do not already @@ -550,6 +602,7 @@ generate_symbols(struct elfcopy *ecp) sym.st_value = s->vma; sym.st_size = 0; sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION); + sym.st_other = STV_DEFAULT; /* * Don't let add_to_symtab() touch sym.st_shndx. * In this case, we know the index already. @@ -583,6 +636,12 @@ generate_symbols(struct elfcopy *ecp) } return (1); + +clean: + free(gsym); + free_symtab(ecp); + + return (0); } void @@ -624,7 +683,9 @@ create_symtab(struct elfcopy *ecp) if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) { TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list); TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list); + free(ecp->symtab->buf); free(ecp->symtab); + free(ecp->strtab->buf); free(ecp->strtab); ecp->symtab = NULL; ecp->strtab = NULL; @@ -697,6 +758,23 @@ free_symtab(struct elfcopy *ecp) } } } + + if (ecp->symndx != NULL) { + free(ecp->symndx); + ecp->symndx = NULL; + } + if (ecp->v_rel != NULL) { + free(ecp->v_rel); + ecp->v_rel = NULL; + } + if (ecp->v_grp != NULL) { + free(ecp->v_grp); + ecp->v_grp = NULL; + } + if (ecp->v_secsym != NULL) { + free(ecp->v_secsym); + ecp->v_secsym = NULL; + } } void diff --git a/contrib/elftoolchain/libdwarf/libdwarf_reloc.c b/contrib/elftoolchain/libdwarf/libdwarf_reloc.c index 96bb785845fe..4ae8f5c3eb70 100644 --- a/contrib/elftoolchain/libdwarf/libdwarf_reloc.c +++ b/contrib/elftoolchain/libdwarf/libdwarf_reloc.c @@ -26,7 +26,7 @@ #include "_libdwarf.h" -ELFTC_VCSID("$Id: libdwarf_reloc.c 3149 2015-02-15 19:00:06Z emaste $"); +ELFTC_VCSID("$Id: libdwarf_reloc.c 3198 2015-05-14 18:36:19Z emaste $"); Dwarf_Unsigned _dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64) @@ -75,6 +75,7 @@ _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type) return (4); break; case EM_386: + case EM_IAMCU: if (rel_type == R_386_32) return (4); break; diff --git a/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c index 1cdb0e7d4d29..e8fd78fe0ded 100644 --- a/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c +++ b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c @@ -36,7 +36,7 @@ #include "_libelftc.h" -ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $"); +ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3212 2015-05-17 13:40:55Z kaiwang27 $"); /** * @file cpp_demangle.c @@ -50,7 +50,7 @@ ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $"); enum type_qualifier { TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT, - TYPE_CST + TYPE_CST, TYPE_VEC }; struct vector_type_qualifier { @@ -84,6 +84,7 @@ struct cpp_demangle_data { int func_type; const char *cur; /* current mangled name ptr */ const char *last_sname; /* last source name */ + int push_head; }; #define CPP_DEMANGLE_TRY_LIMIT 128 @@ -112,6 +113,8 @@ static int cpp_demangle_read_array(struct cpp_demangle_data *); static int cpp_demangle_read_encoding(struct cpp_demangle_data *); static int cpp_demangle_read_expr_primary(struct cpp_demangle_data *); static int cpp_demangle_read_expression(struct cpp_demangle_data *); +static int cpp_demangle_read_expression_flat(struct cpp_demangle_data *, + char **); static int cpp_demangle_read_expression_binary(struct cpp_demangle_data *, const char *, size_t); static int cpp_demangle_read_expression_unary(struct cpp_demangle_data *, @@ -123,8 +126,12 @@ static int cpp_demangle_read_function(struct cpp_demangle_data *, int *, static int cpp_demangle_local_source_name(struct cpp_demangle_data *ddata); static int cpp_demangle_read_local_name(struct cpp_demangle_data *); static int cpp_demangle_read_name(struct cpp_demangle_data *); +static int cpp_demangle_read_name_flat(struct cpp_demangle_data *, + char**); static int cpp_demangle_read_nested_name(struct cpp_demangle_data *); static int cpp_demangle_read_number(struct cpp_demangle_data *, long *); +static int cpp_demangle_read_number_as_string(struct cpp_demangle_data *, + char **); static int cpp_demangle_read_nv_offset(struct cpp_demangle_data *); static int cpp_demangle_read_offset(struct cpp_demangle_data *); static int cpp_demangle_read_offset_number(struct cpp_demangle_data *); @@ -138,6 +145,8 @@ static int cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *); static int cpp_demangle_read_tmpl_args(struct cpp_demangle_data *); static int cpp_demangle_read_tmpl_param(struct cpp_demangle_data *); static int cpp_demangle_read_type(struct cpp_demangle_data *, int); +static int cpp_demangle_read_type_flat(struct cpp_demangle_data *, + char **); static int cpp_demangle_read_uqname(struct cpp_demangle_data *); static int cpp_demangle_read_v_offset(struct cpp_demangle_data *); static char *decode_fp_to_double(const char *, size_t); @@ -156,8 +165,6 @@ static int vector_type_qualifier_init(struct vector_type_qualifier *); static int vector_type_qualifier_push(struct vector_type_qualifier *, enum type_qualifier); -static int cpp_demangle_gnu3_push_head; - /** * @brief Decode the input string by IA-64 C++ ABI style. * @@ -190,7 +197,6 @@ cpp_demangle_gnu3(const char *org) if (!cpp_demangle_data_init(&ddata, org + 2)) return (NULL); - cpp_demangle_gnu3_push_head = 0; rtn = NULL; if (!cpp_demangle_read_encoding(&ddata)) @@ -277,6 +283,7 @@ cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur) d->func_type = 0; d->cur = cur; d->last_sname = NULL; + d->push_head = 0; return (1); @@ -309,7 +316,6 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata, fp = ddata->cur; while (*ddata->cur != 'E') ++ddata->cur; - ++ddata->cur; if ((f = decoder(fp, ddata->cur - fp)) == NULL) return (0); @@ -320,6 +326,8 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata, free(f); + ++ddata->cur; + return (rtn); } @@ -331,7 +339,7 @@ cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str, if (ddata == NULL || str == NULL || len == 0) return (0); - if (cpp_demangle_gnu3_push_head > 0) + if (ddata->push_head > 0) return (vector_str_push(&ddata->output_tmp, str, len)); return (vector_str_push(&ddata->output, str, len)); @@ -403,7 +411,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, if (type_str != NULL) { if (!vector_str_push(&subst_v, "*", 1)) goto clean; - if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) goto clean; } break; @@ -414,7 +423,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, if (type_str != NULL) { if (!vector_str_push(&subst_v, "&", 1)) goto clean; - if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) goto clean; } break; @@ -425,7 +435,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, if (type_str != NULL) { if (!vector_str_push(&subst_v, " complex", 8)) goto clean; - if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) goto clean; } break; @@ -434,23 +445,26 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, if (!cpp_demangle_push_str(ddata, " imaginary", 10)) goto clean; if (type_str != NULL) { - if (!vector_str_push(&subst_v, " imaginary", 10)) + if (!vector_str_push(&subst_v, " imaginary", + 10)) goto clean; - if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) goto clean; } break; case TYPE_EXT: - if (e_idx > v->ext_name.size - 1) + if (v->ext_name.size == 0 || + e_idx > v->ext_name.size - 1) goto clean; - if ((e_len = strlen(v->ext_name.container[e_idx])) == 0) + if ((e_len = strlen(v->ext_name.container[e_idx])) == + 0) goto clean; - if ((buf = malloc(sizeof(char) * (e_len + 1))) == NULL) + if ((buf = malloc(e_len + 2)) == NULL) goto clean; - - memcpy(buf, " ", 1); - memcpy(buf + 1, v->ext_name.container[e_idx], e_len); + snprintf(buf, e_len + 2, " %s", + v->ext_name.container[e_idx]); if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) { free(buf); @@ -463,7 +477,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, free(buf); goto clean; } - if (!cpp_demangle_push_subst_v(ddata, &subst_v)) { + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) { free(buf); goto clean; } @@ -478,7 +493,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, if (type_str != NULL) { if (!vector_str_push(&subst_v, " restrict", 9)) goto clean; - if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) goto clean; } break; @@ -489,7 +505,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, if (type_str != NULL) { if (!vector_str_push(&subst_v, " volatile", 9)) goto clean; - if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) goto clean; } break; @@ -500,11 +517,42 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, if (type_str != NULL) { if (!vector_str_push(&subst_v, " const", 6)) goto clean; - if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) goto clean; } break; + case TYPE_VEC: + if (v->ext_name.size == 0 || + e_idx > v->ext_name.size - 1) + goto clean; + if ((e_len = strlen(v->ext_name.container[e_idx])) == + 0) + goto clean; + if ((buf = malloc(e_len + 12)) == NULL) + goto clean; + snprintf(buf, e_len + 12, " __vector(%s)", + v->ext_name.container[e_idx]); + if (!cpp_demangle_push_str(ddata, buf, e_len + 11)) { + free(buf); + goto clean; + } + if (type_str != NULL) { + if (!vector_str_push(&subst_v, buf, + e_len + 11)) { + free(buf); + goto clean; + } + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) { + free(buf); + goto clean; + } + } + free(buf); + ++e_idx; + break; }; --idx; } @@ -655,10 +703,14 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata) switch (*ddata->cur) { case 'b': + if (*(ddata->cur + 2) != 'E') + return (0); switch (*(++ddata->cur)) { case '0': + ddata->cur += 2; return (cpp_demangle_push_str(ddata, "false", 5)); case '1': + ddata->cur += 2; return (cpp_demangle_push_str(ddata, "true", 4)); default: return (0); @@ -707,7 +759,8 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata) ++ddata->cur; } ++ddata->cur; - return (cpp_demangle_push_str(ddata, num, ddata->cur - num)); + return (cpp_demangle_push_str(ddata, num, + ddata->cur - num - 1)); default: return (0); @@ -998,6 +1051,38 @@ cpp_demangle_read_expression(struct cpp_demangle_data *ddata) return (0); } +static int +cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str) +{ + struct vector_str *output; + size_t i, p_idx, idx, exp_len; + char *exp; + + output = ddata->push_head > 0 ? &ddata->output_tmp : + &ddata->output; + + p_idx = output->size; + + if (!cpp_demangle_read_expression(ddata)) + return (0); + + if ((exp = vector_str_substr(output, p_idx, output->size - 1, + &exp_len)) == NULL) + return (0); + + idx = output->size; + for (i = p_idx; i < idx; ++i) { + if (!vector_str_pop(output)) { + free(exp); + return (0); + } + } + + *str = exp; + + return (1); +} + static int cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata, const char *name, size_t len) @@ -1127,12 +1212,65 @@ cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c, static int cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) { + char *name, *type, *num_str; + long offset; + int rtn; if (ddata == NULL || *ddata->cur == '\0') return (0); /* special name */ switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { + case SIMPLE_HASH('G', 'A'): + if (!cpp_demangle_push_str(ddata, "hidden alias for ", 17)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + return (cpp_demangle_read_encoding(ddata)); + + case SIMPLE_HASH('G', 'R'): + if (!cpp_demangle_push_str(ddata, "reference temporary #", 21)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + if (!cpp_demangle_read_name_flat(ddata, &name)) + return (0); + rtn = 0; + if (!cpp_demangle_read_number_as_string(ddata, &num_str)) + goto clean1; + if (!cpp_demangle_push_str(ddata, num_str, strlen(num_str))) + goto clean2; + if (!cpp_demangle_push_str(ddata, " for ", 5)) + goto clean2; + if (!cpp_demangle_push_str(ddata, name, strlen(name))) + goto clean2; + rtn = 1; + clean2: + free(num_str); + clean1: + free(name); + return (rtn); + + case SIMPLE_HASH('G', 'T'): + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + switch (*ddata->cur) { + case 'n': + if (!cpp_demangle_push_str(ddata, + "non-transaction clone for ", 26)) + return (0); + case 't': + default: + if (!cpp_demangle_push_str(ddata, + "transaction clone for ", 22)) + return (0); + } + ++ddata->cur; + return (cpp_demangle_read_encoding(ddata)); + case SIMPLE_HASH('G', 'V'): /* sentry object for 1 time init */ if (!cpp_demangle_push_str(ddata, "guard variable for ", 20)) @@ -1154,14 +1292,49 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) return (0); return (cpp_demangle_read_encoding(ddata)); + case SIMPLE_HASH('T', 'C'): + /* construction vtable */ + if (!cpp_demangle_push_str(ddata, "construction vtable for ", + 24)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + if (!cpp_demangle_read_type_flat(ddata, &type)) + return (0); + rtn = 0; + if (!cpp_demangle_read_number(ddata, &offset)) + goto clean3; + if (*ddata->cur++ != '_') + goto clean3; + if (!cpp_demangle_read_type(ddata, 0)) + goto clean3; + if (!cpp_demangle_push_str(ddata, "-in-", 4)) + goto clean3; + if (!cpp_demangle_push_str(ddata, type, strlen(type))) + goto clean3; + rtn = 1; + clean3: + free(type); + return (rtn); + case SIMPLE_HASH('T', 'D'): /* typeinfo common proxy */ break; + case SIMPLE_HASH('T', 'F'): + /* typeinfo fn */ + if (!cpp_demangle_push_str(ddata, "typeinfo fn for ", 16)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + return (cpp_demangle_read_type(ddata, 0)); + case SIMPLE_HASH('T', 'h'): /* virtual function non-virtual override thunk */ - if (cpp_demangle_push_str(ddata, - "virtual function non-virtual override ", 38) == 0) + if (!cpp_demangle_push_str(ddata, + "virtual function non-virtual override ", 38)) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1170,24 +1343,51 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) return (0); return (cpp_demangle_read_encoding(ddata)); - case SIMPLE_HASH('T', 'I'): - /* typeinfo structure */ - /* FALLTHROUGH */ - case SIMPLE_HASH('T', 'S'): - /* RTTI name (NTBS) */ - if (!cpp_demangle_push_str(ddata, "typeinfo for ", 14)) + case SIMPLE_HASH('T', 'H'): + /* TLS init function */ + if (!cpp_demangle_push_str(ddata, "TLS init function for ", + 22)) return (0); ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 1)); + break; + + case SIMPLE_HASH('T', 'I'): + /* typeinfo structure */ + if (!cpp_demangle_push_str(ddata, "typeinfo for ", 13)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + return (cpp_demangle_read_type(ddata, 0)); + + case SIMPLE_HASH('T', 'J'): + /* java class */ + if (!cpp_demangle_push_str(ddata, "java Class for ", 15)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + return (cpp_demangle_read_type(ddata, 0)); + + case SIMPLE_HASH('T', 'S'): + /* RTTI name (NTBS) */ + if (!cpp_demangle_push_str(ddata, "typeinfo name for ", 18)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + return (cpp_demangle_read_type(ddata, 0)); case SIMPLE_HASH('T', 'T'): /* VTT table */ if (!cpp_demangle_push_str(ddata, "VTT for ", 8)) return (0); ddata->cur += 2; - return (cpp_demangle_read_type(ddata, 1)); + if (*ddata->cur == '\0') + return (0); + return (cpp_demangle_read_type(ddata, 0)); case SIMPLE_HASH('T', 'v'): /* virtual function virtual override thunk */ @@ -1208,7 +1408,17 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 1)); + return (cpp_demangle_read_type(ddata, 0)); + + case SIMPLE_HASH('T', 'W'): + /* TLS wrapper function */ + if (!cpp_demangle_push_str(ddata, "TLS wrapper function for ", + 25)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + break; }; return (cpp_demangle_read_name(ddata)); @@ -1270,8 +1480,7 @@ cpp_demangle_read_name(struct cpp_demangle_data *ddata) if (ddata == NULL || *ddata->cur == '\0') return (0); - output = cpp_demangle_gnu3_push_head > 0 ? - &ddata->output_tmp : &ddata->output; + output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; subst_str = NULL; @@ -1326,6 +1535,38 @@ clean: return (rtn); } +static int +cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str) +{ + struct vector_str *output; + size_t i, p_idx, idx, name_len; + char *name; + + output = ddata->push_head > 0 ? &ddata->output_tmp : + &ddata->output; + + p_idx = output->size; + + if (!cpp_demangle_read_name(ddata)) + return (0); + + if ((name = vector_str_substr(output, p_idx, output->size - 1, + &name_len)) == NULL) + return (0); + + idx = output->size; + for (i = p_idx; i < idx; ++i) { + if (!vector_str_pop(output)) { + free(name); + return (0); + } + } + + *str = name; + + return (1); +} + static int cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata) { @@ -1355,8 +1596,7 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata) ++ddata->cur; } - output = cpp_demangle_gnu3_push_head > 0 ? - &ddata->output_tmp : &ddata->output; + output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; if (!vector_str_init(&v)) return (0); @@ -1452,6 +1692,24 @@ cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn) return (1); } +static int +cpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str) +{ + long n; + + if (!cpp_demangle_read_number(ddata, &n)) { + *str = NULL; + return (0); + } + + if (asprintf(str, "%ld", n) < 0) { + *str = NULL; + return (0); + } + + return (1); +} + static int cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata) { @@ -1581,9 +1839,18 @@ static int cpp_demangle_read_sname(struct cpp_demangle_data *ddata) { long len; + int err; if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 || - len <= 0 || cpp_demangle_push_str(ddata, ddata->cur, len) == 0) + len <= 0) + return (0); + + if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0)) + err = cpp_demangle_push_str(ddata, "(anonymous namespace)", 21); + else + err = cpp_demangle_push_str(ddata, ddata->cur, len); + + if (err == 0) return (0); assert(ddata->output.size > 0); @@ -1732,8 +1999,7 @@ cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata) ddata->cur += 2; - output = cpp_demangle_gnu3_push_head > 0 ? - &ddata->output_tmp : &ddata->output; + output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; p_idx = output->size; if (!cpp_demangle_read_uqname(ddata)) @@ -1783,8 +2049,7 @@ cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata, if (ddata == NULL || str == NULL || len == 0) return (0); - output = cpp_demangle_gnu3_push_head > 0 ? &ddata->output_tmp : - &ddata->output; + output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; p_idx = output->size; substr = NULL; @@ -1852,8 +2117,7 @@ cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata) return (0); limit = 0; - v = cpp_demangle_gnu3_push_head > 0 ? - &ddata->output_tmp : &ddata->output; + v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; for (;;) { idx = v->size; if (!cpp_demangle_read_tmpl_arg(ddata)) @@ -1936,14 +2200,14 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit) size_t p_idx, type_str_len; int extern_c, is_builtin; long len; - char *type_str; + char *type_str, *exp_str, *num_str; if (ddata == NULL) return (0); output = &ddata->output; if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) { - cpp_demangle_gnu3_push_head++; + ddata->push_head++; output = &ddata->output_tmp; } else if (delimit == 1) { if (ddata->paren == false) { @@ -1978,7 +2242,7 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit) extern_c = 0; is_builtin = 1; p_idx = output->size; - type_str = NULL; + type_str = exp_str = num_str = NULL; again: /* builtin type */ switch (*ddata->cur) { @@ -2024,6 +2288,82 @@ again: ++ddata->cur; goto rtn; + case 'D': + ++ddata->cur; + switch (*ddata->cur) { + case 'd': + /* IEEE 754r decimal floating point (64 bits) */ + if (!cpp_demangle_push_str(ddata, "decimal64", 9)) + goto clean; + ++ddata->cur; + break; + case 'e': + /* IEEE 754r decimal floating point (128 bits) */ + if (!cpp_demangle_push_str(ddata, "decimal128", 10)) + goto clean; + ++ddata->cur; + break; + case 'f': + /* IEEE 754r decimal floating point (32 bits) */ + if (!cpp_demangle_push_str(ddata, "decimal32", 9)) + goto clean; + ++ddata->cur; + break; + case 'h': + /* IEEE 754r half-precision floating point (16 bits) */ + if (!cpp_demangle_push_str(ddata, "half", 4)) + goto clean; + ++ddata->cur; + break; + case 'i': + /* char32_t */ + if (!cpp_demangle_push_str(ddata, "char32_t", 8)) + goto clean; + ++ddata->cur; + break; + case 'n': + /* std::nullptr_t (i.e., decltype(nullptr)) */ + if (!cpp_demangle_push_str(ddata, "decltype(nullptr)", + 17)) + goto clean; + ++ddata->cur; + break; + case 's': + /* char16_t */ + if (!cpp_demangle_push_str(ddata, "char16_t", 8)) + goto clean; + ++ddata->cur; + break; + case 'v': + /* gcc vector_size extension. */ + ++ddata->cur; + if (*ddata->cur == '_') { + ++ddata->cur; + if (!cpp_demangle_read_expression_flat(ddata, + &exp_str)) + goto clean; + if (!vector_str_push(&v.ext_name, exp_str, + strlen(exp_str))) + goto clean; + } else { + if (!cpp_demangle_read_number_as_string(ddata, + &num_str)) + goto clean; + if (!vector_str_push(&v.ext_name, num_str, + strlen(num_str))) + goto clean; + } + if (*ddata->cur != '_') + goto clean; + ++ddata->cur; + if (!vector_type_qualifier_push(&v, TYPE_VEC)) + goto clean; + goto again; + default: + goto clean; + } + goto rtn; + case 'e': /* long double */ if (!cpp_demangle_push_str(ddata, "long double", 11)) @@ -2118,7 +2458,7 @@ again: case 'o': /* unsigned __int128 */ - if (!cpp_demangle_push_str(ddata, "unsigned _;int128", 17)) + if (!cpp_demangle_push_str(ddata, "unsigned __int128", 17)) goto clean; ++ddata->cur; goto rtn; @@ -2189,6 +2529,8 @@ again: if (!vector_str_push(&v.ext_name, ddata->cur, len)) return (0); ddata->cur += len; + if (!vector_type_qualifier_push(&v, TYPE_EXT)) + goto clean; goto again; case 'v': @@ -2253,14 +2595,16 @@ rtn: goto clean; free(type_str); + free(exp_str); + free(num_str); vector_type_qualifier_dest(&v); - if (cpp_demangle_gnu3_push_head > 0) { + if (ddata->push_head > 0) { if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata) == 0) return (0); - if (--cpp_demangle_gnu3_push_head > 0) + if (--ddata->push_head > 0) return (1); if (!vector_str_push(&ddata->output_tmp, " ", 1)) @@ -2284,11 +2628,45 @@ rtn: return (1); clean: free(type_str); + free(exp_str); + free(num_str); vector_type_qualifier_dest(&v); return (0); } +static int +cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str) +{ + struct vector_str *output; + size_t i, p_idx, idx, type_len; + char *type; + + output = ddata->push_head > 0 ? &ddata->output_tmp : + &ddata->output; + + p_idx = output->size; + + if (!cpp_demangle_read_type(ddata, 0)) + return (0); + + if ((type = vector_str_substr(output, p_idx, output->size - 1, + &type_len)) == NULL) + return (0); + + idx = output->size; + for (i = p_idx; i < idx; ++i) { + if (!vector_str_pop(output)) { + free(type); + return (0); + } + } + + *str = type; + + return (1); +} + /* * read unqualified-name, unqualified name are operator-name, ctor-dtor-name, * source-name diff --git a/contrib/elftoolchain/libelftc/os.Linux.mk b/contrib/elftoolchain/libelftc/os.Linux.mk index 9730bf6a2788..d99117d491f5 100644 --- a/contrib/elftoolchain/libelftc/os.Linux.mk +++ b/contrib/elftoolchain/libelftc/os.Linux.mk @@ -1,3 +1,3 @@ -# $Id: os.Linux.mk 994 2010-06-13 10:39:19Z jkoshy $ +# $Id: os.Linux.mk 3210 2015-05-17 13:40:49Z kaiwang27 $ -CFLAGS+= -Wall +CFLAGS+= -Wall -D_GNU_SOURCE diff --git a/contrib/elftoolchain/readelf/readelf.1 b/contrib/elftoolchain/readelf/readelf.1 index a71e85f24c8f..701d50089515 100644 --- a/contrib/elftoolchain/readelf/readelf.1 +++ b/contrib/elftoolchain/readelf/readelf.1 @@ -22,7 +22,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Id: readelf.1 3195 2015-05-12 17:22:19Z emaste $ +.\" $Id: readelf.1 3219 2015-05-24 23:42:34Z kaiwang27 $ .\" .Dd September 13, 2012 .Os @@ -90,7 +90,7 @@ sections in the ELF object. .It Fl e | Fl -headers Print all program, file and section headers in the ELF object. .It Fl g | Fl -section-groups -This option is recognized, but is ignored. +Print the contents of the section groups in the ELF object. .It Fl h | Fl -file-header Print the file header of the ELF object. .It Fl l | Fl -program-headers diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index 29bc38955040..b1b81a34d4f7 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2014 Kai Wang + * Copyright (c) 2009-2015 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,7 +46,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: readelf.c 3189 2015-04-20 17:02:01Z emaste $"); +ELFTC_VCSID("$Id: readelf.c 3223 2015-05-25 20:37:57Z emaste $"); /* * readelf(1) options. @@ -302,6 +302,7 @@ static void dump_gnu_hash(struct readelf *re, struct section *s); static void dump_hash(struct readelf *re); static void dump_phdr(struct readelf *re); static void dump_ppc_attributes(uint8_t *p, uint8_t *pe); +static void dump_section_groups(struct readelf *re); static void dump_symtab(struct readelf *re, int i); static void dump_symtabs(struct readelf *re); static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p); @@ -445,6 +446,7 @@ elf_machine(unsigned int mach) case EM_SPARC: return "Sun SPARC"; case EM_386: return "Intel i386"; case EM_68K: return "Motorola 68000"; + case EM_IAMCU: return "Intel MCU"; case EM_88K: return "Motorola 88000"; case EM_860: return "Intel i860"; case EM_MIPS: return "MIPS R3000 Big-Endian only"; @@ -1050,6 +1052,7 @@ r_type(unsigned int mach, unsigned int type) switch(mach) { case EM_NONE: return ""; case EM_386: + case EM_IAMCU: switch(type) { case 0: return "R_386_NONE"; case 1: return "R_386_32"; @@ -2381,6 +2384,7 @@ dwarf_reg(unsigned int mach, unsigned int reg) switch (mach) { case EM_386: + case EM_IAMCU: switch (reg) { case 0: return "eax"; case 1: return "ecx"; @@ -4047,6 +4051,61 @@ dump_liblist(struct readelf *re) #undef Elf_Lib +static void +dump_section_groups(struct readelf *re) +{ + struct section *s; + const char *symname; + Elf_Data *d; + uint32_t *w; + int i, j, elferr; + size_t n; + + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type != SHT_GROUP) + continue; + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(elferr)); + continue; + } + if (d->d_size <= 0) + continue; + + w = d->d_buf; + + /* We only support COMDAT section. */ +#ifndef GRP_COMDAT +#define GRP_COMDAT 0x1 +#endif + if ((*w++ & GRP_COMDAT) == 0) + return; + + if (s->entsize == 0) + s->entsize = 4; + + symname = get_symbol_name(re, s->link, s->info); + n = s->sz / s->entsize; + if (n-- < 1) + return; + + printf("\nCOMDAT group section [%5d] `%s' [%s] contains %ju" + " sections:\n", i, s->name, symname, (uintmax_t)n); + printf(" %-10.10s %s\n", "[Index]", "Name"); + for (j = 0; (size_t) j < n; j++, w++) { + if (*w >= re->shnum) { + warnx("invalid section index: %u", *w); + continue; + } + printf(" [%5u] %s\n", *w, re->sl[*w].name); + } + } +} + static uint8_t * dump_unknown_tag(uint64_t tag, uint8_t *p) { @@ -6838,6 +6897,8 @@ dump_elf(struct readelf *re) dump_phdr(re); if (re->options & RE_SS) dump_shdr(re); + if (re->options & RE_G) + dump_section_groups(re); if (re->options & RE_D) dump_dynamic(re); if (re->options & RE_R) @@ -7311,7 +7372,7 @@ Usage: %s [options] file...\n\ -c | --archive-index Print the archive symbol table for archives.\n\ -d | --dynamic Print the contents of SHT_DYNAMIC sections.\n\ -e | --headers Print all headers in the object.\n\ - -g | --section-groups (accepted, but ignored)\n\ + -g | --section-groups Print the contents of the section groups.\n\ -h | --file-header Print the file header for the object.\n\ -l | --program-headers Print the PHDR table for the object.\n\ -n | --notes Print the contents of SHT_NOTE sections.\n\ @@ -7365,8 +7426,8 @@ main(int argc, char **argv) re->options |= RE_AA; break; case 'a': - re->options |= RE_AA | RE_D | RE_H | RE_II | RE_L | - RE_R | RE_SS | RE_S | RE_VV; + re->options |= RE_AA | RE_D | RE_G | RE_H | RE_II | + RE_L | RE_R | RE_SS | RE_S | RE_VV; break; case 'c': re->options |= RE_C; diff --git a/lib/libelftc/elftc_version.c b/lib/libelftc/elftc_version.c index fb0a731c3492..e8a11d4b8f0c 100644 --- a/lib/libelftc/elftc_version.c +++ b/lib/libelftc/elftc_version.c @@ -6,5 +6,5 @@ const char * elftc_version(void) { - return "elftoolchain r3197M"; + return "elftoolchain r3223M"; } From 3a86cbbbcb71403f65fb9388c1f66ffc71776c5b Mon Sep 17 00:00:00 2001 From: gjb Date: Wed, 27 May 2015 17:33:30 +0000 Subject: [PATCH 12/65] Invert the build date and svn revision to match the namimg convention that has been in use for a while. MFC after: 3 days Sponsored by: The FreeBSD Foundation --- release/Makefile.mirrors | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/Makefile.mirrors b/release/Makefile.mirrors index a050444a393b..ed10c5553bbd 100644 --- a/release/Makefile.mirrors +++ b/release/Makefile.mirrors @@ -49,7 +49,7 @@ BUILDDATE!= cd ${.CURDIR} && date -j -f '%s' $$(stat -f "%c" ${.OBJDIR}/dist/ba BUILDDATE!= date +%Y%m%d . endif . endif -_SNAP_SUFFIX:= -r${SVNREVISION}-${BUILDDATE} +_SNAP_SUFFIX:= ${BUILDDATE}-r${SVNREVISION} .else # release SNAPSHOT= From 64ae6e65431b67c2ce47c09531b5b470848c2432 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 27 May 2015 17:51:06 +0000 Subject: [PATCH 13/65] Add to the SYNOPSIS of the kinfo_get*() functions since these functions all return types that are defined in that header. MFC after: 1 week --- lib/libutil/kinfo_getallproc.3 | 3 ++- lib/libutil/kinfo_getfile.3 | 3 ++- lib/libutil/kinfo_getproc.3 | 3 ++- lib/libutil/kinfo_getvmmap.3 | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/libutil/kinfo_getallproc.3 b/lib/libutil/kinfo_getallproc.3 index 56d4ad613bb9..7005d4f2931a 100644 --- a/lib/libutil/kinfo_getallproc.3 +++ b/lib/libutil/kinfo_getallproc.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 9, 2009 +.Dd May 27, 2015 .Dt KINFO_GETALLPROC 3 .Os .Sh NAME @@ -35,6 +35,7 @@ .Lb libutil .Sh SYNOPSIS .In sys/types.h +.In sys/user.h .In libutil.h .Ft struct kinfo_proc * .Fn kinfo_getallproc "int *cntp" diff --git a/lib/libutil/kinfo_getfile.3 b/lib/libutil/kinfo_getfile.3 index 1e0bab70150b..2a35687bf25d 100644 --- a/lib/libutil/kinfo_getfile.3 +++ b/lib/libutil/kinfo_getfile.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 6, 2008 +.Dd May 27, 2015 .Dt KINFO_GETFILE 3 .Os .Sh NAME @@ -35,6 +35,7 @@ .Lb libutil .Sh SYNOPSIS .In sys/types.h +.In sys/user.h .In libutil.h .Ft struct kinfo_file * .Fn kinfo_getfile "pid_t pid" "int *cntp" diff --git a/lib/libutil/kinfo_getproc.3 b/lib/libutil/kinfo_getproc.3 index 804cb6c19b77..f5ccbc5011ab 100644 --- a/lib/libutil/kinfo_getproc.3 +++ b/lib/libutil/kinfo_getproc.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 1, 2013 +.Dd May 27, 2015 .Dt KINFO_GETPROC 3 .Os .Sh NAME @@ -35,6 +35,7 @@ .Lb libutil .Sh SYNOPSIS .In sys/types.h +.In sys/user.h .In libutil.h .Ft struct kinfo_proc * .Fn kinfo_getproc "pid_t pid" diff --git a/lib/libutil/kinfo_getvmmap.3 b/lib/libutil/kinfo_getvmmap.3 index 165de6084147..c6a13700a71d 100644 --- a/lib/libutil/kinfo_getvmmap.3 +++ b/lib/libutil/kinfo_getvmmap.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 6, 2008 +.Dd May 27, 2015 .Dt KINFO_GETVMMAP 3 .Os .Sh NAME @@ -35,6 +35,7 @@ .Lb libutil .Sh SYNOPSIS .In sys/types.h +.In sys/user.h .In libutil.h .Ft struct kinfo_vmentry * .Fn kinfo_getvmmap "pid_t pid" "int *cntp" From b365af7766cc44bd4b33dbec9b7eb20311f21f36 Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 27 May 2015 18:07:32 +0000 Subject: [PATCH 14/65] Bump __FreeBSD_version for the r283602, which changed dounmount() to require referenced struct mount *. Sponsored by: The FreeBSD Foundation --- sys/sys/param.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/sys/param.h b/sys/sys/param.h index 960d1ca34c7e..9bd1dd7d53f5 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 1100074 /* Master, propagated to newvers */ +#define __FreeBSD_version 1100075 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, From 4a4be98eae460918227f3cff47cf8c574ea39ea3 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 27 May 2015 18:11:05 +0000 Subject: [PATCH 15/65] Export a list of VM objects in the system via a sysctl. The list can be examined via 'vmstat -o'. It can be used to determine which files are using physical pages of memory and how much each is using. Differential Revision: https://reviews.freebsd.org/D2277 Reviewed by: alc, kib MFC after: 2 weeks Sponsored by: Norse Corp, Inc. (forward porting to HEAD/10) --- lib/libutil/Makefile | 6 +- lib/libutil/kinfo_getvmobject.3 | 74 +++++++++++++++++ lib/libutil/kinfo_getvmobject.c | 94 ++++++++++++++++++++++ lib/libutil/libutil.h | 2 + sys/sys/user.h | 21 +++++ sys/vm/vm_object.c | 137 ++++++++++++++++++++++++++++++++ usr.bin/vmstat/vmstat.8 | 5 +- usr.bin/vmstat/vmstat.c | 135 ++++++++++++++++++++++++++++++- 8 files changed, 469 insertions(+), 5 deletions(-) create mode 100644 lib/libutil/kinfo_getvmobject.3 create mode 100644 lib/libutil/kinfo_getvmobject.c diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index 7e5f1a34895b..2f68628279b3 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -10,7 +10,8 @@ SHLIB_MAJOR= 9 SRCS= _secure_path.c auth.c expand_number.c flopen.c fparseln.c gr_util.c \ hexdump.c humanize_number.c kinfo_getfile.c kinfo_getfile.c \ - kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c kld.c \ + kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c \ + kinfo_getvmobject.c kld.c \ login_auth.c login_cap.c \ login_class.c login_crypt.c login_ok.c login_times.c login_tty.c \ pidfile.c property.c pty.c pw_util.c quotafile.c realhostname.c \ @@ -27,7 +28,8 @@ CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../libc/gen/ MAN+= expand_number.3 flopen.3 fparseln.3 hexdump.3 \ humanize_number.3 kinfo_getallproc.3 kinfo_getfile.3 \ - kinfo_getproc.3 kinfo_getvmmap.3 kld.3 login_auth.3 login_cap.3 \ + kinfo_getproc.3 kinfo_getvmmap.3 kinfo_getvmobject.3 kld.3 \ + login_auth.3 login_cap.3 \ login_class.3 login_ok.3 login_times.3 login_tty.3 pidfile.3 \ property.3 pty.3 quotafile.3 realhostname.3 realhostname_sa.3 \ _secure_path.3 trimdomain.3 uucplock.3 pw_util.3 diff --git a/lib/libutil/kinfo_getvmobject.3 b/lib/libutil/kinfo_getvmobject.3 new file mode 100644 index 000000000000..dc0edd2bfecf --- /dev/null +++ b/lib/libutil/kinfo_getvmobject.3 @@ -0,0 +1,74 @@ +.\" +.\" Copyright (c) 2015 John Baldwin +.\" 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$ +.\" +.Dd May 27, 2015 +.Dt KINFO_GETVMOBJECT 3 +.Os +.Sh NAME +.Nm kinfo_getvmobject +.Nd function for getting system-wide memory information +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/types.h +.In sys/user.h +.In libutil.h +.Ft struct kinfo_vmobject * +.Fn kinfo_getvmobject "int *cntp" +.Sh DESCRIPTION +This function is used to obtain information about the objects using memory +in the system. +.Pp +The +.Ar cntp +argument allows the caller to know how many records are returned. +.Pp +This function is a wrapper around the +.Dq vm.objects +.Xr sysctl 3 +MIB. +While the kernel returns a packed structure, this function expands the +data into a fixed record format. +.Sh RETURN VALUES +On success the +.Fn kinfo_getvmobject +function returns a pointer to an array of +.Vt struct kinfo_vmobject +structures as defined by +.In sys/user.h . +The array is allocated by an internal call to +.Xr malloc 3 +and must be freed by the caller with a call to +.Xr free 3 . +On failure the +.Fn kinfo_getvmobject +function returns +.Dv NULL . +.Sh SEE ALSO +.Xr free 3 , +.Xr kinfo_getvmmap 3 , +.Xr malloc 3 diff --git a/lib/libutil/kinfo_getvmobject.c b/lib/libutil/kinfo_getvmobject.c new file mode 100644 index 000000000000..7e031dadccb0 --- /dev/null +++ b/lib/libutil/kinfo_getvmobject.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013 Hudson River Trading LLC + * Written by: John H. Baldwin + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include "libutil.h" + +struct kinfo_vmobject * +kinfo_getvmobject(int *cntp) +{ + char *buf, *bp, *ep; + struct kinfo_vmobject *kvo, *list, *kp; + size_t len; + int cnt, i; + + buf = NULL; + for (i = 0; i < 3; i++) { + if (sysctlbyname("vm.objects", NULL, &len, NULL, 0) < 0) + return (NULL); + buf = reallocf(buf, len); + if (buf == NULL) + return (NULL); + if (sysctlbyname("vm.objects", buf, &len, NULL, 0) == 0) + goto unpack; + if (errno != ENOMEM) { + free(buf); + return (NULL); + } + } + free(buf); + return (NULL); + +unpack: + /* Count items */ + cnt = 0; + bp = buf; + ep = buf + len; + while (bp < ep) { + kvo = (struct kinfo_vmobject *)(uintptr_t)bp; + bp += kvo->kvo_structsize; + cnt++; + } + + list = calloc(cnt, sizeof(*list)); + if (list == NULL) { + free(buf); + return (NULL); + } + + /* Unpack */ + bp = buf; + kp = list; + while (bp < ep) { + kvo = (struct kinfo_vmobject *)(uintptr_t)bp; + memcpy(kp, kvo, kvo->kvo_structsize); + bp += kvo->kvo_structsize; + kp->kvo_structsize = sizeof(*kp); + kp++; + } + free(buf); + *cntp = cnt; + return (list); +} diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h index b8b9836b0fdf..b20ffa291a90 100644 --- a/lib/libutil/libutil.h +++ b/lib/libutil/libutil.h @@ -102,6 +102,8 @@ struct kinfo_file * kinfo_getfile(pid_t _pid, int *_cntp); struct kinfo_vmentry * kinfo_getvmmap(pid_t _pid, int *_cntp); +struct kinfo_vmobject * + kinfo_getvmobject(int *_cntp); struct kinfo_proc * kinfo_getallproc(int *_cntp); struct kinfo_proc * diff --git a/sys/sys/user.h b/sys/sys/user.h index c3b3bc59b414..e831a37ce541 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -485,6 +485,27 @@ struct kinfo_vmentry { char kve_path[PATH_MAX]; /* Path to VM obj, if any. */ }; +/* + * The "vm.objects" sysctl provides a list of all VM objects in the system + * via an array of these entries. + */ +struct kinfo_vmobject { + int kvo_structsize; /* Variable size of record. */ + int kvo_type; /* Object type: KVME_TYPE_*. */ + uint64_t kvo_size; /* Object size in pages. */ + uint64_t kvo_vn_fileid; /* inode number if vnode. */ + uint32_t kvo_vn_fsid; /* dev_t of vnode location. */ + int kvo_ref_count; /* Reference count. */ + int kvo_shadow_count; /* Shadow count. */ + int kvo_memattr; /* Memory attribute. */ + uint64_t kvo_resident; /* Number of resident pages. */ + uint64_t kvo_active; /* Number of active pages. */ + uint64_t kvo_inactive; /* Number of inactive pages. */ + uint64_t _kvo_qspare[8]; + uint32_t _kvo_ispare[8]; + char kvo_path[PATH_MAX]; /* Pathname, if any. */ +}; + /* * The KERN_PROC_KSTACK sysctl allows a process to dump the kernel stacks of * another process as a series of entries. Each stack is represented by a diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 78cea70a9f07..30623b2e50cf 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -2286,6 +2287,142 @@ next_page: } } +static int +sysctl_vm_object_list(SYSCTL_HANDLER_ARGS) +{ + struct kinfo_vmobject kvo; + char *fullpath, *freepath; + struct vnode *vp; + struct vattr va; + vm_object_t obj; + vm_page_t m; + int count, error; + + if (req->oldptr == NULL) { + /* + * If an old buffer has not been provided, generate an + * estimate of the space needed for a subsequent call. + */ + mtx_lock(&vm_object_list_mtx); + count = 0; + TAILQ_FOREACH(obj, &vm_object_list, object_list) { + if (obj->type == OBJT_DEAD) + continue; + count++; + } + mtx_unlock(&vm_object_list_mtx); + return (SYSCTL_OUT(req, NULL, sizeof(struct kinfo_vmobject) * + count * 11 / 10)); + } + + error = 0; + + /* + * VM objects are type stable and are never removed from the + * list once added. This allows us to safely read obj->object_list + * after reacquiring the VM object lock. + */ + mtx_lock(&vm_object_list_mtx); + TAILQ_FOREACH(obj, &vm_object_list, object_list) { + if (obj->type == OBJT_DEAD) + continue; + VM_OBJECT_RLOCK(obj); + if (obj->type == OBJT_DEAD) { + VM_OBJECT_RUNLOCK(obj); + continue; + } + mtx_unlock(&vm_object_list_mtx); + kvo.kvo_size = ptoa(obj->size); + kvo.kvo_resident = obj->resident_page_count; + kvo.kvo_ref_count = obj->ref_count; + kvo.kvo_shadow_count = obj->shadow_count; + kvo.kvo_memattr = obj->memattr; + kvo.kvo_active = 0; + kvo.kvo_inactive = 0; + TAILQ_FOREACH(m, &obj->memq, listq) { + /* + * A page may belong to the object but be + * dequeued and set to PQ_NONE while the + * object lock is not held. This makes the + * reads of m->queue below racy, and we do not + * count pages set to PQ_NONE. However, this + * sysctl is only meant to give an + * approximation of the system anyway. + */ + if (m->queue == PQ_ACTIVE) + kvo.kvo_active++; + else if (m->queue == PQ_INACTIVE) + kvo.kvo_inactive++; + } + + kvo.kvo_vn_fileid = 0; + kvo.kvo_vn_fsid = 0; + freepath = NULL; + fullpath = ""; + vp = NULL; + switch (obj->type) { + case OBJT_DEFAULT: + kvo.kvo_type = KVME_TYPE_DEFAULT; + break; + case OBJT_VNODE: + kvo.kvo_type = KVME_TYPE_VNODE; + vp = obj->handle; + vref(vp); + break; + case OBJT_SWAP: + kvo.kvo_type = KVME_TYPE_SWAP; + break; + case OBJT_DEVICE: + kvo.kvo_type = KVME_TYPE_DEVICE; + break; + case OBJT_PHYS: + kvo.kvo_type = KVME_TYPE_PHYS; + break; + case OBJT_DEAD: + kvo.kvo_type = KVME_TYPE_DEAD; + break; + case OBJT_SG: + kvo.kvo_type = KVME_TYPE_SG; + break; + case OBJT_MGTDEVICE: + kvo.kvo_type = KVME_TYPE_MGTDEVICE; + break; + default: + kvo.kvo_type = KVME_TYPE_UNKNOWN; + break; + } + VM_OBJECT_RUNLOCK(obj); + if (vp != NULL) { + vn_fullpath(curthread, vp, &fullpath, &freepath); + vn_lock(vp, LK_SHARED | LK_RETRY); + if (VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) { + kvo.kvo_vn_fileid = va.va_fileid; + kvo.kvo_vn_fsid = va.va_fsid; + } + vput(vp); + } + + strlcpy(kvo.kvo_path, fullpath, sizeof(kvo.kvo_path)); + if (freepath != NULL) + free(freepath, M_TEMP); + + /* Pack record size down */ + kvo.kvo_structsize = offsetof(struct kinfo_vmobject, kvo_path) + + strlen(kvo.kvo_path) + 1; + kvo.kvo_structsize = roundup(kvo.kvo_structsize, + sizeof(uint64_t)); + error = SYSCTL_OUT(req, &kvo, kvo.kvo_structsize); + mtx_lock(&vm_object_list_mtx); + if (error) + break; + } + mtx_unlock(&vm_object_list_mtx); + return (error); +} +SYSCTL_PROC(_vm, OID_AUTO, objects, CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_SKIP | + CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_object_list, "S,kinfo_vmobject", + "List of VM objects"); + #include "opt_ddb.h" #ifdef DDB #include diff --git a/usr.bin/vmstat/vmstat.8 b/usr.bin/vmstat/vmstat.8 index 4566ad2a421d..93e75b92470b 100644 --- a/usr.bin/vmstat/vmstat.8 +++ b/usr.bin/vmstat/vmstat.8 @@ -37,7 +37,7 @@ .Sh SYNOPSIS .Nm .\" .Op Fl fimst -.Op Fl afHhimPsz +.Op Fl afHhimoPsz .Op Fl M Ar core Op Fl N Ar system .Op Fl c Ar count .Op Fl n Ar devs @@ -119,6 +119,9 @@ Report on the usage of kernel dynamic memory allocated using by type. .It Fl n Change the maximum number of disks to display from the default of 2. +.It Fl o +Display a list of virtual memory objects in the system and the resident +memory used by each object. .It Fl P Report per-cpu system/user/idle cpu statistics. .It Fl p diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index 9049e442227f..e20268f27f83 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -143,12 +144,14 @@ static kvm_t *kd; #define TIMESTAT 0x10 #define VMSTAT 0x20 #define ZMEMSTAT 0x40 +#define OBJSTAT 0x80 static void cpustats(void); static void pcpustats(int, u_long, int); static void devstats(void); static void doforkst(void); static void dointr(unsigned int, int); +static void doobjstat(void); static void dosum(void); static void dovmstat(unsigned int, int); static void domemstat_malloc(void); @@ -181,7 +184,7 @@ main(int argc, char *argv[]) interval = reps = todo = 0; maxshowdevs = 2; hflag = isatty(1); - while ((c = getopt(argc, argv, "ac:fhHiM:mN:n:Pp:stw:z")) != -1) { + while ((c = getopt(argc, argv, "ac:fhHiM:mN:n:oPp:stw:z")) != -1) { switch (c) { case 'a': aflag++; @@ -220,6 +223,9 @@ main(int argc, char *argv[]) errx(1, "number of devices %d is < 0", maxshowdevs); break; + case 'o': + todo |= OBJSTAT; + break; case 'p': if (devstat_buildmatch(optarg, &matches, &num_matches) != 0) errx(1, "%s", devstat_errbuf); @@ -320,6 +326,8 @@ retry_nlist: domemstat_zone(); if (todo & SUMSTAT) dosum(); + if (todo & OBJSTAT) + doobjstat(); #ifdef notyet if (todo & TIMESTAT) dotimes(); @@ -1396,6 +1404,129 @@ domemstat_zone(void) printf("\n"); } +static void +display_object(struct kinfo_vmobject *kvo) +{ + const char *str; + + printf("%5jd ", (uintmax_t)kvo->kvo_resident); + printf("%5jd ", (uintmax_t)kvo->kvo_active); + printf("%5jd ", (uintmax_t)kvo->kvo_inactive); + printf("%3d ", kvo->kvo_ref_count); + printf("%3d ", kvo->kvo_shadow_count); + switch (kvo->kvo_memattr) { +#ifdef VM_MEMATTR_UNCACHEABLE + case VM_MEMATTR_UNCACHEABLE: + str = "UC"; + break; +#endif +#ifdef VM_MEMATTR_WRITE_COMBINING + case VM_MEMATTR_WRITE_COMBINING: + str = "WC"; + break; +#endif +#ifdef VM_MEMATTR_WRITE_THROUGH + case VM_MEMATTR_WRITE_THROUGH: + str = "WT"; + break; +#endif +#ifdef VM_MEMATTR_WRITE_PROTECTED + case VM_MEMATTR_WRITE_PROTECTED: + str = "WP"; + break; +#endif +#ifdef VM_MEMATTR_WRITE_BACK + case VM_MEMATTR_WRITE_BACK: + str = "WB"; + break; +#endif +#ifdef VM_MEMATTR_WEAK_UNCACHEABLE + case VM_MEMATTR_WEAK_UNCACHEABLE: + str = "UC-"; + break; +#endif +#ifdef VM_MEMATTR_WB_WA: + case VM_MEMATTR_WB_WA: + str = "WB"; + break; +#endif +#ifdef VM_MEMATTR_NOCACHE + case VM_MEMATTR_NOCACHE: + str = "NC"; + break; +#endif +#ifdef VM_MEMATTR_DEVICE + case VM_MEMATTR_DEVICE: + str = "DEV"; + break; +#endif +#ifdef VM_MEMATTR_CACHEABLE + case VM_MEMATTR_CACHEABLE: + str = "C"; + break; +#endif +#ifdef VM_MEMATTR_PREFETCHABLE + case VM_MEMATTR_PREFETCHABLE: + str = "PRE"; + break; +#endif + default: + str = "??"; + break; + } + printf("%-3s ", str); + switch (kvo->kvo_type) { + case KVME_TYPE_NONE: + str = "--"; + break; + case KVME_TYPE_DEFAULT: + str = "df"; + break; + case KVME_TYPE_VNODE: + str = "vn"; + break; + case KVME_TYPE_SWAP: + str = "sw"; + break; + case KVME_TYPE_DEVICE: + str = "dv"; + break; + case KVME_TYPE_PHYS: + str = "ph"; + break; + case KVME_TYPE_DEAD: + str = "dd"; + break; + case KVME_TYPE_SG: + str = "sg"; + break; + case KVME_TYPE_UNKNOWN: + default: + str = "??"; + break; + } + printf("%-2s ", str); + printf("%-s\n", kvo->kvo_path); +} + +static void +doobjstat(void) +{ + struct kinfo_vmobject *kvo; + int cnt, i; + + kvo = kinfo_getvmobject(&cnt); + if (kvo == NULL) { + warn("Failed to fetch VM object list"); + return; + } + printf("%5s %5s %5s %3s %3s %3s %2s %s\n", "RES", "ACT", "INACT", + "REF", "SHD", "CM", "TP", "PATH"); + for (i = 0; i < cnt; i++) + display_object(&kvo[i]); + free(kvo); +} + /* * kread reads something from the kernel, given its nlist index. */ @@ -1448,7 +1579,7 @@ static void usage(void) { (void)fprintf(stderr, "%s%s", - "usage: vmstat [-afHhimPsz] [-M core [-N system]] [-c count] [-n devs]\n", + "usage: vmstat [-afHhimoPsz] [-M core [-N system]] [-c count] [-n devs]\n", " [-p type,if,pass] [-w wait] [disks] [wait [count]]\n"); exit(1); } From ae73c05fd5fad2bd38891efa999a28dde53e79c6 Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 27 May 2015 19:28:14 +0000 Subject: [PATCH 16/65] Add missed {}. Noted by: Morten Rodal MFC after: 2 weeks --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index c44516f175fd..1193e47a0108 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -2314,9 +2314,10 @@ bail: * Since we couldn't setup the sa framework, try to force * unmount this file system. */ - if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) + if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) { vfs_ref(zfsvfs->z_vfs); (void) dounmount(zfsvfs->z_vfs, MS_FORCE, curthread); + } } return (err); } From 6a0a0389e13c1c72418854571b13c01d1cec705a Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 27 May 2015 19:49:33 +0000 Subject: [PATCH 17/65] Trim spurious colon. --- usr.bin/vmstat/vmstat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index e20268f27f83..0a3054ac50e9 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -1445,7 +1445,7 @@ display_object(struct kinfo_vmobject *kvo) str = "UC-"; break; #endif -#ifdef VM_MEMATTR_WB_WA: +#ifdef VM_MEMATTR_WB_WA case VM_MEMATTR_WB_WA: str = "WB"; break; From 026eafa5d44296b11a5ef777eaec8ec340c56d88 Mon Sep 17 00:00:00 2001 From: slm Date: Wed, 27 May 2015 20:37:34 +0000 Subject: [PATCH 18/65] This setting of stop_at_shutdown should have been removed with r279253 Approved by: ken MFC after: 1 week --- sys/dev/mpr/mpi/mpi2.h | 8 +- sys/dev/mpr/mpi/mpi2_cnfg.h | 8 +- sys/dev/mpr/mpi/mpi2_hbd.h | 8 +- sys/dev/mpr/mpi/mpi2_history.txt | 8 +- sys/dev/mpr/mpi/mpi2_init.h | 8 +- sys/dev/mpr/mpi/mpi2_ioc.h | 8 +- sys/dev/mpr/mpi/mpi2_ra.h | 8 +- sys/dev/mpr/mpi/mpi2_raid.h | 8 +- sys/dev/mpr/mpi/mpi2_sas.h | 8 +- sys/dev/mpr/mpi/mpi2_targ.h | 8 +- sys/dev/mpr/mpi/mpi2_tool.h | 8 +- sys/dev/mpr/mpi/mpi2_type.h | 8 +- sys/dev/mpr/mpr.c | 90 +++--- sys/dev/mpr/mpr_config.c | 5 +- sys/dev/mpr/mpr_ioctl.h | 7 +- sys/dev/mpr/mpr_mapping.c | 72 +++-- sys/dev/mpr/mpr_mapping.h | 10 +- sys/dev/mpr/mpr_pci.c | 14 +- sys/dev/mpr/mpr_sas.c | 476 +++++++++++++++++-------------- sys/dev/mpr/mpr_sas.h | 31 +- sys/dev/mpr/mpr_sas_lsi.c | 360 ++++++++++++++++------- sys/dev/mpr/mpr_user.c | 41 ++- sys/dev/mpr/mprvar.h | 38 ++- 23 files changed, 767 insertions(+), 473 deletions(-) diff --git a/sys/dev/mpr/mpi/mpi2.h b/sys/dev/mpr/mpi/mpi2.h index 10f17aba067e..42fdec20c503 100644 --- a/sys/dev/mpr/mpi/mpi2.h +++ b/sys/dev/mpr/mpi/mpi2.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2.h diff --git a/sys/dev/mpr/mpi/mpi2_cnfg.h b/sys/dev/mpr/mpi/mpi2_cnfg.h index d82750f80913..3b0eb637a9e2 100644 --- a/sys/dev/mpr/mpi/mpi2_cnfg.h +++ b/sys/dev/mpr/mpi/mpi2_cnfg.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_cnfg.h diff --git a/sys/dev/mpr/mpi/mpi2_hbd.h b/sys/dev/mpr/mpi/mpi2_hbd.h index d0cc09f905a0..520407b39948 100644 --- a/sys/dev/mpr/mpi/mpi2_hbd.h +++ b/sys/dev/mpr/mpi/mpi2_hbd.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2009-2011 LSI Corporation. + * Copyright (c) 2009-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_hbd.h diff --git a/sys/dev/mpr/mpi/mpi2_history.txt b/sys/dev/mpr/mpi/mpi2_history.txt index 296b75b87859..9fca7966f65a 100644 --- a/sys/dev/mpr/mpi/mpi2_history.txt +++ b/sys/dev/mpr/mpi/mpi2_history.txt @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,7 +27,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -35,7 +36,8 @@ Fusion-MPT MPI 2.0 / 2.5 Header File Change History ============================== - Copyright (c) 2000-2013 LSI Corporation. + Copyright (c) 2000-2015 LSI Corporation. + Copyright (c) 2013-2015 Avago Technologies --------------------------------------- Header Set Release Version: 02.00.33 diff --git a/sys/dev/mpr/mpi/mpi2_init.h b/sys/dev/mpr/mpi/mpi2_init.h index 62b0cfed120a..5f475c0e26ba 100644 --- a/sys/dev/mpr/mpi/mpi2_init.h +++ b/sys/dev/mpr/mpi/mpi2_init.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_init.h diff --git a/sys/dev/mpr/mpi/mpi2_ioc.h b/sys/dev/mpr/mpi/mpi2_ioc.h index 38a46f5280bc..54f39a5adc71 100644 --- a/sys/dev/mpr/mpi/mpi2_ioc.h +++ b/sys/dev/mpr/mpi/mpi2_ioc.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_ioc.h diff --git a/sys/dev/mpr/mpi/mpi2_ra.h b/sys/dev/mpr/mpi/mpi2_ra.h index 76db06b71b98..02304aaa002e 100644 --- a/sys/dev/mpr/mpi/mpi2_ra.h +++ b/sys/dev/mpr/mpi/mpi2_ra.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2009 LSI Corporation. + * Copyright (c) 2012-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_ra.h diff --git a/sys/dev/mpr/mpi/mpi2_raid.h b/sys/dev/mpr/mpi/mpi2_raid.h index c6bb59864a3c..52ebf07ee096 100644 --- a/sys/dev/mpr/mpi/mpi2_raid.h +++ b/sys/dev/mpr/mpi/mpi2_raid.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_raid.h diff --git a/sys/dev/mpr/mpi/mpi2_sas.h b/sys/dev/mpr/mpi/mpi2_sas.h index 2a107f1e1617..7cae2c3d4adf 100644 --- a/sys/dev/mpr/mpi/mpi2_sas.h +++ b/sys/dev/mpr/mpi/mpi2_sas.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_sas.h diff --git a/sys/dev/mpr/mpi/mpi2_targ.h b/sys/dev/mpr/mpi/mpi2_targ.h index 506e64f6370c..85b5ac562610 100644 --- a/sys/dev/mpr/mpi/mpi2_targ.h +++ b/sys/dev/mpr/mpi/mpi2_targ.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_targ.h diff --git a/sys/dev/mpr/mpi/mpi2_tool.h b/sys/dev/mpr/mpi/mpi2_tool.h index 94542cc7959b..59917c0077f5 100644 --- a/sys/dev/mpr/mpi/mpi2_tool.h +++ b/sys/dev/mpr/mpi/mpi2_tool.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_tool.h diff --git a/sys/dev/mpr/mpi/mpi2_type.h b/sys/dev/mpr/mpi/mpi2_type.h index da3aefb968f4..b063683263d0 100644 --- a/sys/dev/mpr/mpi/mpi2_type.h +++ b/sys/dev/mpr/mpi/mpi2_type.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2007 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_type.h diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index d3fb9a0682b8..07e73c54e8be 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2012-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,12 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #include @@ -72,7 +75,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include static int mpr_diag_reset(struct mpr_softc *sc, int sleep_flag); static int mpr_init_queues(struct mpr_softc *sc); @@ -352,11 +354,9 @@ mpr_transition_operational(struct mpr_softc *sc) static int mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) { - int error, i; + int error; Mpi2IOCFactsReply_t saved_facts; uint8_t saved_mode, reallocating; - struct mprsas_lun *lun, *lun_tmp; - struct mprsas_target *targ; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); @@ -513,27 +513,7 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) */ if (reallocating) { mpr_iocfacts_free(sc); - - /* - * The number of targets is based on IOC Facts, so free all of - * the allocated LUNs for each target and then the target buffer - * itself. - */ - for (i=0; i< saved_facts.MaxTargets; i++) { - targ = &sc->sassc->targets[i]; - SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, - lun_tmp) { - free(lun, M_MPR); - } - } - free(sc->sassc->targets, M_MPR); - - sc->sassc->targets = malloc(sizeof(struct mprsas_target) * - sc->facts->MaxTargets, M_MPR, M_WAITOK|M_ZERO); - if (!sc->sassc->targets) { - panic("%s failed to alloc targets with error %d\n", - __func__, ENOMEM); - } + mprsas_realloc_targets(sc, saved_facts.MaxTargets); } /* @@ -775,7 +755,7 @@ mpr_reinit(struct mpr_softc *sc) /* the end of discovery will release the simq, so we're done. */ mpr_dprint(sc, MPR_INFO, "%s finished sc %p post %u free %u\n", __func__, sc, sc->replypostindex, sc->replyfreeindex); - mprsas_release_simq_reinit(sassc); + mprsas_release_simq_reinit(sassc); return 0; } @@ -816,7 +796,8 @@ mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag) * 0.5 milisecond */ if (mtx_owned(&sc->mpr_mtx) && sleep_flag == CAN_SLEEP) - msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", hz/1000); + msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", + hz/1000); else if (sleep_flag == CAN_SLEEP) pause("mprdba", hz/1000); else @@ -982,7 +963,7 @@ mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm) reply_descriptor rd; MPR_FUNCTRACE(sc); - mpr_dprint(sc, MPR_TRACE, "%s SMID %u cm %p ccb %p\n", __func__, + mpr_dprint(sc, MPR_TRACE, "SMID %u cm %p ccb %p\n", cm->cm_desc.Default.SMID, cm, cm->cm_ccb); if (sc->mpr_flags & MPR_FLAGS_ATTACH_DONE && !(sc->mpr_flags & @@ -1372,6 +1353,8 @@ mpr_get_tunables(struct mpr_softc *sc) sc->disable_msix = 0; sc->disable_msi = 0; sc->max_chains = MPR_CHAIN_FRAMES; + sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD; + sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; /* * Grab the global variables. @@ -1380,6 +1363,8 @@ mpr_get_tunables(struct mpr_softc *sc) TUNABLE_INT_FETCH("hw.mpr.disable_msix", &sc->disable_msix); TUNABLE_INT_FETCH("hw.mpr.disable_msi", &sc->disable_msi); TUNABLE_INT_FETCH("hw.mpr.max_chains", &sc->max_chains); + TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu); + TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time); /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level", @@ -1402,6 +1387,14 @@ mpr_get_tunables(struct mpr_softc *sc) snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.exclude_ids", device_get_unit(sc->mpr_dev)); TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids)); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.enable_ssu", + device_get_unit(sc->mpr_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time", + device_get_unit(sc->mpr_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); } static void @@ -1474,11 +1467,20 @@ mpr_setup_sysctl(struct mpr_softc *sc) OID_AUTO, "max_chains", CTLFLAG_RD, &sc->max_chains, 0,"maximum chain frames that will be allocated"); + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "enable_ssu", CTLFLAG_RW, &sc->enable_ssu, 0, + "enable SSU to SATA SSD/HDD at shutdown"); + #if __FreeBSD_version >= 900030 SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "chain_alloc_fail", CTLFLAG_RD, &sc->chain_alloc_fail, "chain allocation failures"); #endif //FreeBSD_version >= 900030 + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "spinup_wait_time", CTLFLAG_RD, + &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for " + "spinup after SATA ID error"); } int @@ -2096,7 +2098,7 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle, (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) error = ENXIO; - if(reply) + if (reply) mpr_print_event(sc, reply); mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error); @@ -2163,8 +2165,8 @@ mpr_deregister_events(struct mpr_softc *sc, struct mpr_event_handle *handle) * Add a chain element as the next SGE for the specified command. * Reset cm_sge and cm_sgesize to indicate all the available space. Chains are * only required for IEEE commands. Therefore there is no code for commands - * that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands shouldn't - * be requesting chains). + * that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands + * shouldn't be requesting chains). */ static int mpr_add_chain(struct mpr_command *cm, int segsleft) @@ -2246,9 +2248,9 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) /* * Add one scatter-gather element to the scatter-gather list for a command. - * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the next - * SGE to fill in, respectively. In Gen3, the MPI SGL does not have a chain, - * so don't consider any chain additions. + * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the + * next SGE to fill in, respectively. In Gen3, the MPI SGL does not have a + * chain, so don't consider any chain additions. */ int mpr_push_sge(struct mpr_command *cm, MPI2_SGE_SIMPLE64 *sge, size_t len, @@ -2660,7 +2662,7 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) } } - if(error) { + if (error) { mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__); rc = mpr_reinit(sc); mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? @@ -2717,9 +2719,12 @@ mpr_read_config_page(struct mpr_softc *sc, struct mpr_config_params *params) cm->cm_data = params->buffer; cm->cm_length = params->length; - cm->cm_sge = &req->PageBufferSGE; - cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); - cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; + if (cm->cm_data != NULL) { + cm->cm_sge = &req->PageBufferSGE; + cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); + cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; + } else + cm->cm_sge = NULL; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_complete_data = params; @@ -2776,9 +2781,12 @@ mpr_config_complete(struct mpr_softc *sc, struct mpr_command *cm) goto done; } params->status = reply->IOCStatus; - if (params->hdr.Ext.ExtPageType != 0) { + if (params->hdr.Struct.PageType == MPI2_CONFIG_PAGETYPE_EXTENDED) { params->hdr.Ext.ExtPageType = reply->ExtPageType; params->hdr.Ext.ExtPageLength = reply->ExtPageLength; + params->hdr.Ext.PageType = reply->Header.PageType; + params->hdr.Ext.PageNumber = reply->Header.PageNumber; + params->hdr.Ext.PageVersion = reply->Header.PageVersion; } else { params->hdr.Struct.PageType = reply->Header.PageType; params->hdr.Struct.PageNumber = reply->Header.PageNumber; diff --git a/sys/dev/mpr/mpr_config.c b/sys/dev/mpr/mpr_config.c index 125451608dee..c0ea3d5ffb08 100644 --- a/sys/dev/mpr/mpr_config.c +++ b/sys/dev/mpr/mpr_config.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include diff --git a/sys/dev/mpr/mpr_ioctl.h b/sys/dev/mpr/mpr_ioctl.h index 5ec482f311b0..aa1a4cbf7697 100644 --- a/sys/dev/mpr/mpr_ioctl.h +++ b/sys/dev/mpr/mpr_ioctl.h @@ -27,12 +27,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD userland interface + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface * * $FreeBSD$ */ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,7 +57,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ diff --git a/sys/dev/mpr/mpr_mapping.c b/sys/dev/mpr/mpr_mapping.c index 7f0fc00a9c52..110e6a3b943f 100644 --- a/sys/dev/mpr/mpr_mapping.c +++ b/sys/dev/mpr/mpr_mapping.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include @@ -326,11 +327,13 @@ _mapping_get_high_missing_mt_idx(struct mpr_softc *sc) { u32 map_idx, high_idx = MPR_ENCTABLE_BAD_IDX; u8 high_missing_count = 0; - u32 start_idx, end_idx, start_idx_ir = 0, end_idx_ir; + u32 start_idx, end_idx, start_idx_ir, end_idx_ir; struct dev_mapping_table *mt_entry; u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); start_idx = 0; + start_idx_ir = 0; + end_idx_ir = 0; end_idx = sc->max_devices; if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) start_idx = 1; @@ -887,14 +890,14 @@ _mapping_get_dev_info(struct mpr_softc *sc, u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; - u8 entry, enc_idx, phy_idx; + u8 entry, enc_idx, phy_idx, sata_end_device; u32 map_idx, index, device_info; struct _map_phy_change *phy_change, *tmp_phy_change; uint64_t sas_address; struct enc_mapping_table *et_entry; struct dev_mapping_table *mt_entry; u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED; - int rc; + int rc = 1; for (entry = 0; entry < topo_change->num_entries; entry++) { phy_change = &topo_change->phy_details[entry]; @@ -908,41 +911,36 @@ _mapping_get_dev_info(struct mpr_softc *sc, continue; } + /* + * Always get SATA Identify information because this is used + * to determine if Start/Stop Unit should be sent to the drive + * when the system is shutdown. + */ device_info = le32toh(sas_device_pg0.DeviceInfo); - if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == - MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { - if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && - (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { - rc = mprsas_get_sas_address_for_sata_disk(sc, - &sas_address, phy_change->dev_handle, - device_info); - if (rc) { - printf("%s: failed to compute the " - "hashed SAS Address for SATA " - "device with handle 0x%04x\n", - __func__, phy_change->dev_handle); - sas_address = - sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; - } + sas_address = sas_device_pg0.SASAddress.High; + sas_address = (sas_address << 32) | + sas_device_pg0.SASAddress.Low; + sata_end_device = 0; + if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && + (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { + sata_end_device = 1; + rc = mprsas_get_sas_address_for_sata_disk(sc, + &sas_address, phy_change->dev_handle, device_info, + &phy_change->is_SATA_SSD); + if (rc) { + mpr_dprint(sc, MPR_ERROR, "%s: failed to get " + "disk type (SSD or HDD) and SAS Address " + "for SATA device with handle 0x%04x\n", + __func__, phy_change->dev_handle); + } else { mpr_dprint(sc, MPR_INFO, "SAS Address for SATA " "device = %jx\n", sas_address); - } else { - sas_address = - sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; } - } else { - sas_address = sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; } + phy_change->physical_id = sas_address; phy_change->slot = le16toh(sas_device_pg0.Slot); - phy_change->device_info = - le32toh(sas_device_pg0.DeviceInfo); + phy_change->device_info = le32toh(sas_device_pg0.DeviceInfo); if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { @@ -950,10 +948,10 @@ _mapping_get_dev_info(struct mpr_softc *sc, topo_change->enc_handle); if (enc_idx == MPR_ENCTABLE_BAD_IDX) { phy_change->is_processed = 1; - printf("%s: failed to add the device with " - "handle 0x%04x because the enclosure is " - "not in the mapping table\n", __func__, - phy_change->dev_handle); + mpr_dprint(sc, MPR_MAPPING, "%s: failed to add " + "the device with handle 0x%04x because the " + "enclosure is not in the mapping table\n", + __func__, phy_change->dev_handle); continue; } if (!((phy_change->device_info & diff --git a/sys/dev/mpr/mpr_mapping.h b/sys/dev/mpr/mpr_mapping.h index 3250c424e2a4..c00a3b795122 100644 --- a/sys/dev/mpr/mpr_mapping.h +++ b/sys/dev/mpr/mpr_mapping.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -38,6 +39,7 @@ * @dev_handle: device handle for the device pointed by this entry * @slot: slot ID * @is_processed: Flag to indicate whether this entry is processed or not + * @is_SATA_SSD: 1 if this is a SATA device AND an SSD, 0 otherwise */ struct _map_phy_change { uint64_t physical_id; @@ -46,6 +48,8 @@ struct _map_phy_change { uint16_t slot; uint8_t reason; uint8_t is_processed; + uint8_t is_SATA_SSD; + uint8_t reserved; }; /** @@ -66,6 +70,6 @@ struct _map_topology_change { extern int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *ioc, - u64 *sas_address, u16 handle, u32 device_info); + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); #endif diff --git a/sys/dev/mpr/mpr_pci.c b/sys/dev/mpr/mpr_pci.c index e19f33adceb4..7430eac03b3a 100644 --- a/sys/dev/mpr/mpr_pci.c +++ b/sys/dev/mpr/mpr_pci.c @@ -27,7 +27,7 @@ #include __FBSDID("$FreeBSD$"); -/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */ +/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT3 controllers */ /* TODO Move headers to mprvar */ #include @@ -99,17 +99,17 @@ struct mpr_ident { const char *desc; } mpr_identifiers[] = { { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, - 0xffff, 0xffff, 0, "LSI SAS3004" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3004" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008, - 0xffff, 0xffff, 0, "LSI SAS3008" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3008" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1, - 0xffff, 0xffff, 0, "LSI SAS3108_1" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_1" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2, - 0xffff, 0xffff, 0, "LSI SAS3108_2" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_2" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5, - 0xffff, 0xffff, 0, "LSI SAS3108_5" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, - 0xffff, 0xffff, 0, "LSI SAS3108_6" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" }, { 0, 0, 0, 0, 0, NULL } }; diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index 32c3a4633a1f..eac336068295 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,12 +24,15 @@ * 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. + * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #include @@ -122,14 +126,10 @@ static void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); static void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); static void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *); -static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, +static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, struct mpr_command *cm); -static int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, - uint8_t type); static void mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); -static void mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, - struct ccb_getdev *cgd); #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, @@ -142,13 +142,12 @@ static void mprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm); #if __FreeBSD_version >= 900026 -static void -mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); +static void mprsas_smpio_complete(struct mpr_softc *sc, + struct mpr_command *cm); static void mprsas_send_smpcmd(struct mprsas_softc *sassc, - union ccb *ccb, uint64_t sasaddr); -static void -mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); -#endif + union ccb *ccb, uint64_t sasaddr); +static void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); +#endif //FreeBSD_version >= 900026 struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, @@ -230,7 +229,7 @@ mprsas_startup_decrement(struct mprsas_softc *sassc) } } -/* LSI's firmware requires us to stop sending commands when we're doing task +/* The firmware requires us to stop sending commands when we're doing task * management, so refcount the TMs and keep the simq frozen when any are in * use. */ @@ -241,35 +240,31 @@ mprsas_alloc_tm(struct mpr_softc *sc) MPR_FUNCTRACE(sc); tm = mpr_alloc_high_priority_command(sc); - if (tm != NULL) { - if (sc->sassc->tm_count++ == 0) { - mpr_dprint(sc, MPR_RECOVERY, - "%s freezing simq\n", __func__); - xpt_freeze_simq(sc->sassc->sim, 1); - } - mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); - } return tm; } void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) { - mpr_dprint(sc, MPR_TRACE, "%s", __func__); + MPR_FUNCTRACE(sc); if (tm == NULL) return; - /* if there are no TMs in use, we can release the simq. We use our - * own refcount so that it's easier for a diag reset to cleanup and - * release the simq. + /* + * For TM's the devq is frozen for the device. Unfreeze it here and + * free the resources used for freezing the devq. Must clear the + * INRESET flag as well or scsi I/O will not work. */ - if (--sc->sassc->tm_count == 0) { - mpr_dprint(sc, MPR_RECOVERY, "%s releasing simq\n", __func__); - xpt_release_simq(sc->sassc->sim, 1); + if (tm->cm_targ != NULL) { + tm->cm_targ->flags &= ~MPRSAS_TARGET_INRESET; + } + if (tm->cm_ccb) { + mpr_dprint(sc, MPR_INFO, "Unfreezing devq for target ID %d\n", + tm->cm_targ->tid); + xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); + xpt_free_path(tm->cm_ccb->ccb_h.path); + xpt_free_ccb(tm->cm_ccb); } - mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); mpr_free_high_priority_command(sc, tm); } @@ -298,8 +293,8 @@ mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ) return; } - if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, - targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; @@ -473,11 +468,16 @@ mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_volume; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mpr_map_command(sc, cm); } /* - * The MPT2 firmware performs debounce on the link to avoid transient link + * The MPT3 firmware performs debounce on the link to avoid transient link * errors and false removals. When it does decide that link has been lost * and a device needs to go away, it expects that the host will perform a * target reset and then an op remove. The reset has the side-effect of @@ -532,6 +532,11 @@ mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_device; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mpr_map_command(sc, cm); } @@ -596,10 +601,10 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_map_command(sc, tm); - mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n", + mpr_dprint(sc, MPR_INFO, "clearing target %u handle 0x%04x\n", targ->tid, handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -608,7 +613,7 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_XINFO, "Completing missed command %p\n", tm); ccb = tm->cm_complete_data; - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); mprsas_scsiio_complete(sc, tm); } } @@ -726,7 +731,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * XXX MaxTargets could change during a reinit. since we don't + * XXX MaxTargets could change during a reinit. Since we don't * resize the targets[] array during such an event, cache the value * of MaxTargets here so that we don't get into trouble later. This * should move into the reinit logic. @@ -782,7 +787,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * Assume that discovery events will start right away. Freezing + * Assume that discovery events will start right away. * * Hold off boot until discovery is complete. */ @@ -790,9 +795,7 @@ mpr_attach_sas(struct mpr_softc *sc) sc->sassc->startup_refcount = 0; mprsas_startup_increment(sassc); - callout_init(&sassc->discovery_callout, 1 /*mprafe*/); - - sassc->tm_count = 0; + callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); /* * Register for async events so we can determine the EEDP @@ -962,7 +965,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) sassc = cam_sim_softc(sim); MPR_FUNCTRACE(sassc->sc); - mpr_dprint(sassc->sc, MPR_TRACE, "%s func 0x%x\n", __func__, + mpr_dprint(sassc->sc, MPR_TRACE, "ccb func_code 0x%x\n", ccb->ccb_h.func_code); mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); @@ -985,7 +988,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cpi->max_lun = 255; cpi->initiator_id = sassc->maxtargets - 1; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); + strncpy(cpi->hba_vid, "Avago Tech (LSI)", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = cam_sim_bus(sim); @@ -1005,7 +1008,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) */ cpi->maxio = 256 * 1024; #endif - cpi->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_GET_TRAN_SETTINGS: @@ -1024,7 +1027,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cts->ccb_h.target_id)); targ = &sassc->targets[cts->ccb_h.target_id]; if (targ->handle == 0x0) { - cts->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; } @@ -1054,12 +1057,12 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) scsi->valid = CTS_SCSI_VALID_TQ; scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; - cts->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_CALC_GEOMETRY: cam_calc_geometry(&ccb->ccg, /*extended*/1); - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_RESET_DEV: mpr_dprint(sassc->sc, MPR_XINFO, @@ -1071,7 +1074,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) case XPT_TERM_IO: mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success for abort or reset\n"); - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_SCSI_IO: mprsas_action_scsiio(sassc, ccb); @@ -1082,7 +1085,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) return; #endif default: - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + mprsas_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL); break; } xpt_done(ccb); @@ -1102,7 +1105,7 @@ mprsas_announce_reset(struct mpr_softc *sc, uint32_t ac_code, if (xpt_create_path(&path, NULL, path_id, target_id, lun_id) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for reset " - "notification\n"); + "notification\n"); return; } @@ -1131,8 +1134,8 @@ mprsas_complete_all_commands(struct mpr_softc *sc) if (cm->cm_complete != NULL) { mprsas_log_command(cm, MPR_RECOVERY, - "completing cm %p state %x ccb %p for diag reset\n", - cm, cm->cm_state, cm->cm_ccb); + "completing cm %p state %x ccb %p for diag " + "reset\n", cm, cm->cm_state, cm->cm_ccb); cm->cm_complete(sc, cm); completed = 1; } @@ -1145,6 +1148,14 @@ mprsas_complete_all_commands(struct mpr_softc *sc) completed = 1; } + if (cm->cm_sc->io_cmds_active != 0) { + cm->cm_sc->io_cmds_active--; + } else { + mpr_dprint(cm->cm_sc, MPR_INFO, "Warning: " + "io_cmds_active is out of sync - resynching to " + "0\n"); + } + if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) { /* this should never happen, but if it does, log */ mprsas_log_command(cm, MPR_RECOVERY, @@ -1180,9 +1191,8 @@ mprsas_handle_reinit(struct mpr_softc *sc) /* complete and cleanup after all outstanding commands */ mprsas_complete_all_commands(sc); - mpr_dprint(sc, MPR_INIT, "%s startup %u tm %u after command " - "completion\n", __func__, sc->sassc->startup_refcount, - sc->sassc->tm_count); + mpr_dprint(sc, MPR_INIT, "%s startup %u after command completion\n", + __func__, sc->sassc->startup_refcount); /* zero all the target handles, since they may change after the * reset, and we have to rediscover all the targets and use the new @@ -1244,7 +1254,6 @@ mprsas_logical_unit_reset_complete(struct mpr_softc *sc, "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1322,8 +1331,8 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) * task management commands don't have S/G lists. */ if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x for target reset! " - "This should not happen!\n", __func__, tm->cm_flags); + mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target " + "reset! This should not happen!\n", __func__, tm->cm_flags); mprsas_free_tm(sc, tm); return; } @@ -1333,7 +1342,6 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1349,8 +1357,6 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), le32toh(reply->TerminationCount)); - targ->flags &= ~MPRSAS_TARGET_INRESET; - if (targ->outstanding == 0) { /* we've finished recovery for this target and all * of its logical units. @@ -1378,7 +1384,7 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) #define MPR_RESET_TIMEOUT 30 -static int +int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) { MPI2_SCSI_TASK_MANAGE_REQUEST *req; @@ -1387,8 +1393,8 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) target = tm->cm_targ; if (target->handle == 0) { - mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n", - __func__, target->tid); + mpr_dprint(sc, MPR_ERROR, "%s null devhandle for target_id " + "%d\n", __func__, target->tid); return -1; } @@ -1404,6 +1410,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending logical unit reset\n"); tm->cm_complete = mprsas_logical_unit_reset_complete; + mprsas_prepare_for_tm(sc, tm, target, tm->cm_lun); } else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { /* @@ -1412,20 +1419,20 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) */ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; tm->cm_targ->target_resets++; - tm->cm_targ->flags |= MPRSAS_TARGET_INRESET; mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending target reset\n"); tm->cm_complete = mprsas_target_reset_complete; + mprsas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD); } else { mpr_dprint(sc, MPR_ERROR, "unexpected reset type 0x%x\n", type); return -1; } - mpr_dprint(sc, MPR_XINFO, "to target %u handle 0x%04x\n", target->tid, + mpr_dprint(sc, MPR_INFO, "to target %u handle 0x%04x\n", target->tid, target->handle); if (target->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", target->encl_level, target->encl_slot, target->connector_name); } @@ -1441,8 +1448,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, - "error %d sending reset type %u\n", - err, type); + "error %d sending reset type %u\n", err, type); return err; } @@ -1573,6 +1579,10 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, targ->aborts++; + mpr_dprint(sc, MPR_INFO, "Sending reset from %s for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, tm, targ, tm->cm_lun); + err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, @@ -1581,7 +1591,6 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, return err; } - static void mprsas_scsiio_timeout(void *data) { @@ -1617,11 +1626,11 @@ mprsas_scsiio_timeout(void *data) targ = cm->cm_targ; targ->timeouts++; - mprsas_log_command(cm, MPR_XINFO, "command timeout cm %p ccb %p " + mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p " "target %u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, targ->handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -1629,8 +1638,7 @@ mprsas_scsiio_timeout(void *data) /* XXX first, check the firmware state, to see if it's still * operational. if not, do a diag reset. */ - - cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT; + mprsas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT); cm->cm_state = MPR_CM_STATE_TIMEDOUT; TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); @@ -1681,19 +1689,22 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) mtx_assert(&sc->mpr_mtx, MA_OWNED); csio = &ccb->csio; + KASSERT(csio->ccb_h.target_id < sassc->maxtargets, + ("Target %d out of bounds in XPT_SCSI_IO\n", + csio->ccb_h.target_id)); targ = &sassc->targets[csio->ccb_h.target_id]; mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n", __func__, csio->ccb_h.target_id); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } if (targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT) { - mpr_dprint(sc, MPR_TRACE, "%s Raid component no SCSI IO " + mpr_dprint(sc, MPR_ERROR, "%s Raid component no SCSI IO " "supported %u\n", __func__, csio->ccb_h.target_id); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } @@ -1702,7 +1713,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) * Progress" and was actually aborted by the upper layer. Check for * this here and complete the command without error. */ - if (ccb->ccb_h.status != CAM_REQ_INPROG) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_INPROG) { mpr_dprint(sc, MPR_TRACE, "%s Command is not in progress for " "target %u\n", __func__, csio->ccb_h.target_id); xpt_done(ccb); @@ -1715,16 +1726,29 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) */ if (targ->flags & MPRSAS_TARGET_INREMOVAL) { if (targ->devinfo == 0) - csio->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - csio->ccb_h.status = CAM_SEL_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } if ((sc->mpr_flags & MPR_FLAGS_SHUTDOWN) != 0) { - mpr_dprint(sc, MPR_TRACE, "%s shutting down\n", __func__); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mpr_dprint(sc, MPR_INFO, "%s shutting down\n", __func__); + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + xpt_done(ccb); + return; + } + + /* + * If target has a reset in progress, freeze the devq and return. The + * devq will be released when the TM reset is finished. + */ + if (targ->flags & MPRSAS_TARGET_INRESET) { + ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; + mpr_dprint(sc, MPR_INFO, "%s: Freezing devq for target ID %d\n", + __func__, targ->tid); + xpt_freeze_devq(ccb->ccb_h.path, 1); xpt_done(ccb); return; } @@ -1807,7 +1831,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) if (MPR_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { mpr_free_command(sc, cm); - ccb->ccb_h.status = CAM_LUN_INVALID; + mprsas_set_ccbstatus(ccb, CAM_LUN_INVALID); xpt_done(ccb); return; } @@ -1904,7 +1928,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) } callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, - mprsas_scsiio_timeout, cm, 0); + mprsas_scsiio_timeout, cm, 0); targ->issued++; targ->outstanding++; @@ -2102,7 +2126,7 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio, desc_scsi_state, scsi_state); if (sc->mpr_debug & MPR_XINFO && - scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { + scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : Start :\n"); scsi_sense_print(csio); mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : End :\n"); @@ -2126,6 +2150,8 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) u8 *TLR_bits, TLR_on; int dir = 0, i; u16 alloc_len; + struct mprsas_target *target; + target_id_t target_id; MPR_FUNCTRACE(sc); mpr_dprint(sc, MPR_TRACE, @@ -2139,6 +2165,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) sassc = sc->sassc; ccb = cm->cm_complete_data; csio = &ccb->csio; + target_id = csio->ccb_h.target_id; rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; /* * XXX KDM if the chain allocation fails, does it matter if we do @@ -2197,7 +2224,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * because there can be no reply when we haven't actually * gone out to the hardware. */ - ccb->ccb_h.status = CAM_REQUEUE_REQ; + mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); /* * Currently the only error included in the mask is @@ -2214,7 +2241,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) xpt_freeze_simq(sassc->sim, 1); sassc->flags |= MPRSAS_QUEUE_FROZEN; mpr_dprint(sc, MPR_INFO, "Error sending command, " - "freezing SIM queue\n"); + "freezing SIM queue\n"); } } @@ -2224,7 +2251,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * commands that were sent. All SSU commands should be completed before * shutdown completes, meaning SSU_refcount will be 0 after SSU_started * is TRUE. - */ + */ if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) { mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n"); sc->SSU_refcount--; @@ -2232,12 +2259,12 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Take the fast path to completion */ if (cm->cm_reply == NULL) { - if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { + if (mprsas_get_ccbstatus(ccb) == CAM_REQ_INPROG) { if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; + mprsas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET); else { - ccb->ccb_h.status = CAM_REQ_CMP; - ccb->csio.scsi_status = SCSI_STATUS_OK; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + csio->scsi_status = SCSI_STATUS_OK; } if (sassc->flags & MPRSAS_QUEUE_FROZEN) { ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -2252,10 +2279,10 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * CAM_REQ_CMP. The first is if MPR_CM_FLAGS_ERROR_MASK is * set, the second is in the MPR_FLAGS_DIAGRESET above. */ - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { /* * Freeze the dev queue so that commands are - * executed in the correct order with after error + * executed in the correct order after error * recovery. */ ccb->ccb_h.status |= CAM_DEV_QFRZN; @@ -2285,7 +2312,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Completion failed at the transport level. */ if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | MPI2_SCSI_STATE_TERMINATED)) { - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } @@ -2294,7 +2321,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * recover the command. */ if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; + mprsas_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); break; } @@ -2306,7 +2333,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) == MPR_SCSI_RI_INVALID_FRAME)) { - sc->mapping_table[csio->ccb_h.target_id].TLR_bits = + sc->mapping_table[target_id].TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; } @@ -2318,16 +2345,16 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) */ if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { - ccb->ccb_h.status = CAM_REQ_ABORTED; + mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; } /* Handle normal status and sense */ csio->scsi_status = rep->SCSIStatus; if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; + mprsas_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { int sense_len, returned_sense_len; @@ -2362,12 +2389,11 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) (csio->data_ptr != NULL) && ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) && (sc->control_TLR) && - (sc->mapping_table[csio->ccb_h.target_id].device_info & + (sc->mapping_table[target_id].device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { vpd_list = (struct scsi_vpd_supported_page_list *) csio->data_ptr; - TLR_bits = &sc->mapping_table[csio->ccb_h.target_id]. - TLR_bits; + TLR_bits = &sc->mapping_table[target_id].TLR_bits; *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) + @@ -2380,6 +2406,24 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) } } } + + /* + * If this is a SATA direct-access end device, mark it so that + * a SCSI StartStopUnit command will be sent to it when the + * driver is being shutdown. + */ + if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) && + ((csio->data_ptr[0] & 0x1f) == T_DIRECT) && + (sc->mapping_table[target_id].device_info & + MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && + ((sc->mapping_table[target_id].device_info & + MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == + MPI2_SAS_DEVICE_INFO_END_DEVICE)) { + target = &sassc->targets[target_id]; + target->supports_SSU = TRUE; + mpr_dprint(sc, MPR_XINFO, "Target %d supports SSU\n", + target_id); + } break; case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: @@ -2390,13 +2434,13 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * failed. */ if (cm->cm_targ->devinfo == 0) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; case MPI2_IOCSTATUS_INVALID_SGL: mpr_print_scsiio_cmd(sc, cm); - ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; + mprsas_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); break; case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: /* @@ -2409,14 +2453,14 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * on the console. */ if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) - ccb->ccb_h.status = CAM_CMD_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT); else - ccb->ccb_h.status = CAM_REQ_ABORTED; + mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: /* resid is ignored for this condition */ csio->resid = 0; - ccb->ccb_h.status = CAM_DATA_RUN_ERR; + mprsas_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); break; case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: @@ -2425,7 +2469,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * transient transport-related) errors, retry these without * decrementing the retry count. */ - ccb->ccb_h.status = CAM_REQUEUE_REQ; + mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); mprsas_log_command(cm, MPR_INFO, "terminated ioc %x scsi %x state %x xfer %u\n", le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, @@ -2447,7 +2491,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, le32toh(rep->TransferCount)); csio->resid = cm->cm_length; - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } @@ -2460,7 +2504,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) "queue\n"); } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { ccb->ccb_h.status |= CAM_DEV_QFRZN; xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); } @@ -2487,16 +2531,16 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) * in the standard request size. */ if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x on SMP request!\n", - __func__, cm->cm_flags); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x on SMP " + "request!\n", __func__, cm->cm_flags); + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; if (rpl == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: NULL cm_reply!\n", __func__); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } @@ -2509,17 +2553,17 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } - mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address " - "%#jx completed successfully\n", __func__, (uintmax_t)sasaddr); + mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address %#jx " + "completed successfully\n", __func__, (uintmax_t)sasaddr); if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_SMP_STATUS_ERROR; + mprsas_set_ccbstatus(ccb, CAM_SMP_STATUS_ERROR); bailout: /* @@ -2558,7 +2602,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, */ mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " "supported\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; case CAM_DATA_SG: @@ -2571,7 +2615,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or response buffer segments " "not supported for SMP\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2605,7 +2649,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, response = ccb->smpio.smp_response; break; default: - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2614,9 +2658,9 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, * XXX We don't yet support physical addresses here. */ if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) { - mpr_printf(sc, "%s: physical addresses not supported\n", - __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " + "supported\n", __func__); + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2635,7 +2679,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " "response buffer segments not supported for SMP\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2673,7 +2717,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, if (cm == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n", __func__); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2760,7 +2804,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, bailout_error: mpr_free_command(sc, cm); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2783,7 +2827,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: target %d does not exist!\n", __func__, ccb->ccb_h.target_id); - ccb->ccb_h.status = CAM_SEL_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } @@ -2831,7 +2875,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->parent_handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent handle!\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } #ifdef OLD_MPR_PROBE @@ -2841,7 +2885,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (parent_target == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent target!\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2850,9 +2894,8 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, parent_target->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; - } sasaddr = parent_target->sasaddr; @@ -2862,7 +2905,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, targ->parent_handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2870,7 +2913,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent handle " "%d does not have a valid SAS address!\n", __func__, targ->handle, targ->parent_handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2882,7 +2925,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (sasaddr == 0) { mpr_dprint(sc, MPR_INFO, "%s: unable to find SAS address for " "handle %d\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } mprsas_send_smpcmd(sassc, ccb, sasaddr); @@ -2914,7 +2957,7 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) if (tm == NULL) { mpr_dprint(sc, MPR_ERROR, "command alloc failure in mprsas_action_resetdev\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2933,7 +2976,12 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; tm->cm_complete = mprsas_resetdev_complete; tm->cm_complete_data = ccb; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); tm->cm_targ = targ; + targ->flags |= MPRSAS_TARGET_INRESET; + mpr_map_command(sc, tm); } @@ -2962,7 +3010,7 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " "handle %#04x! This should not happen!\n", __func__, tm->cm_flags, req->DevHandle); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } @@ -2971,12 +3019,12 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, CAM_LUN_WILDCARD); } else - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); bailout: @@ -2995,7 +3043,8 @@ mprsas_poll(struct cam_sim *sim) /* frequent debug messages during a panic just slow * everything down too much. */ - mpr_printf(sassc->sc, "%s clearing MPR_TRACE\n", __func__); + mpr_dprint(sassc->sc, MPR_XINFO, "%s clearing MPR_TRACE\n", + __func__); sassc->sc->mpr_debug &= ~MPR_TRACE; } @@ -3094,7 +3143,7 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE); - if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) + if ((mprsas_get_ccbstatus((union ccb *)&cdai) == CAM_REQ_CMP) && (rcap_buf.prot & SRC16_PROT_EN)) { lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf.length); @@ -3121,8 +3170,6 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, #endif cgd = arg; - mprsas_prepare_ssu(sc, path, cgd); - #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) mprsas_check_eedp(sc, path, cgd); @@ -3134,64 +3181,6 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, } } -static void -mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, - struct ccb_getdev *cgd) -{ - struct mprsas_softc *sassc = sc->sassc; - path_id_t pathid; - target_id_t targetid; - lun_id_t lunid; - struct mprsas_target *target; - struct mprsas_lun *lun; - uint8_t found_lun; - - sassc = sc->sassc; - pathid = cam_sim_path(sassc->sim); - targetid = xpt_path_target_id(path); - lunid = xpt_path_lun_id(path); - - KASSERT(targetid < sassc->maxtargets, - ("Target %d out of bounds in mprsas_prepare_ssu\n", targetid)); - target = &sassc->targets[targetid]; - if (target->handle == 0x0) - return; - - /* - * If LUN is already in list, don't create a new one. - */ - found_lun = FALSE; - SLIST_FOREACH(lun, &target->luns, lun_link) { - if (lun->lun_id == lunid) { - found_lun = TRUE; - break; - } - } - if (!found_lun) { - lun = malloc(sizeof(struct mprsas_lun), M_MPR, - M_NOWAIT | M_ZERO); - if (lun == NULL) { - mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for " - "preparing SSU.\n"); - return; - } - lun->lun_id = lunid; - SLIST_INSERT_HEAD(&target->luns, lun, lun_link); - } - - /* - * If this is a SATA direct-access end device, mark it so that a SCSI - * StartStopUnit command will be sent to it when the driver is being - * shutdown. - */ - if (((cgd->inq_data.device & 0x1F) == T_DIRECT) && - (target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && - ((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == - MPI2_SAS_DEVICE_INFO_END_DEVICE)) { - lun->stop_at_shutdown = TRUE; - } -} - #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void @@ -3212,7 +3201,6 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, uint8_t found_lun; char path_str[64]; - sassc = sc->sassc; pathid = cam_sim_path(sassc->sim); targetid = xpt_path_target_id(path); lunid = xpt_path_lun_id(path); @@ -3288,7 +3276,7 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), M_MPR, M_NOWAIT | M_ZERO); if (rcap_buf == NULL) { - mpr_dprint(sc, MPR_FAULT, "Unable to alloc read capacity " + mpr_dprint(sc, MPR_ERROR, "Unable to alloc read capacity " "buffer for EEDP support.\n"); xpt_free_path(ccb->ccb_h.path); xpt_free_ccb(ccb); @@ -3341,7 +3329,7 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) xpt_release_devq(done_ccb->ccb_h.path, /*count*/ 1, /*run_queue*/TRUE); } - + rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; /* @@ -3359,21 +3347,21 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) /* * Got the LUN in the target's LUN list. Fill it in with EEDP - * info. If the READ CAP 16 command had some SCSI error (common + * info. If the READ CAP 16 command had some SCSI error (common * if command is not supported), mark the lun as not supporting * EEDP and set the block size to 0. */ - if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) - || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { + if ((mprsas_get_ccbstatus(done_ccb) != CAM_REQ_CMP) || + (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { lun->eedp_formatted = FALSE; lun->eedp_block_size = 0; break; } if (rcap_buf->protect & 0x01) { - mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for " - "target ID %d is formatted for EEDP " - "support.\n", done_ccb->ccb_h.target_lun, + mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for target ID " + "%d is formatted for EEDP support.\n", + done_ccb->ccb_h.target_lun, done_ccb->ccb_h.target_id); lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf->length); @@ -3389,6 +3377,34 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) #endif /* (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ +void +mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, + struct mprsas_target *target, lun_id_t lun_id) +{ + union ccb *ccb; + path_id_t path_id; + + /* + * Set the INRESET flag for this target so that no I/O will be sent to + * the target until the reset has completed. If an I/O request does + * happen, the devq will be frozen. The CCB holds the path which is + * used to release the devq. The devq is released and the CCB is freed + * when the TM completes. + */ + ccb = xpt_alloc_ccb_nowait(); + if (ccb) { + path_id = cam_sim_path(sc->sassc->sim); + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id, + target->tid, lun_id) != CAM_REQ_CMP) { + xpt_free_ccb(ccb); + } else { + tm->cm_ccb = ccb; + tm->cm_targ = target; + target->flags |= MPRSAS_TARGET_INRESET; + } + } +} + int mprsas_startup(struct mpr_softc *sc) { @@ -3489,3 +3505,33 @@ mprsas_check_id(struct mprsas_softc *sassc, int id) return (0); } + +void +mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) +{ + struct mprsas_softc *sassc; + struct mprsas_lun *lun, *lun_tmp; + struct mprsas_target *targ; + int i; + + sassc = sc->sassc; + /* + * The number of targets is based on IOC Facts, so free all of + * the allocated LUNs for each target and then the target buffer + * itself. + */ + for (i=0; i< maxtargets; i++) { + targ = &sassc->targets[i]; + SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { + free(lun, M_MPR); + } + } + free(sassc->targets, M_MPR); + + sassc->targets = malloc(sizeof(struct mprsas_target) * maxtargets, + M_MPR, M_WAITOK|M_ZERO); + if (!sassc->targets) { + panic("%s failed to alloc targets with error %d\n", + __func__, ENOMEM); + } +} diff --git a/sys/dev/mpr/mpr_sas.h b/sys/dev/mpr/mpr_sas.h index 9d3116af29d0..ebeed300c9fb 100644 --- a/sys/dev/mpr/mpr_sas.h +++ b/sys/dev/mpr/mpr_sas.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -35,7 +36,6 @@ struct mprsas_lun { lun_id_t lun_id; uint8_t eedp_formatted; uint32_t eedp_block_size; - uint8_t stop_at_shutdown; }; struct mprsas_target { @@ -55,11 +55,10 @@ struct mprsas_target { #define MPRSAS_TARGET_INREMOVAL (1 << 3) #define MPR_TARGET_FLAGS_RAID_COMPONENT (1 << 4) #define MPR_TARGET_FLAGS_VOLUME (1 << 5) +#define MPR_TARGET_IS_SATA_SSD (1 << 6) #define MPRSAS_TARGET_INRECOVERY (MPRSAS_TARGET_INABORT | \ MPRSAS_TARGET_INRESET | MPRSAS_TARGET_INCHIPRESET) -#define MPRSAS_TARGET_ADD (1 << 29) -#define MPRSAS_TARGET_REMOVE (1 << 30) uint16_t tid; SLIST_HEAD(, mprsas_lun) luns; TAILQ_HEAD(, mpr_command) commands; @@ -82,6 +81,8 @@ struct mprsas_target { unsigned int logical_unit_resets; unsigned int target_resets; uint8_t scsi_req_desc_type; + uint8_t stop_at_shutdown; + uint8_t supports_SSU; }; struct mprsas_softc { @@ -92,7 +93,6 @@ struct mprsas_softc { #define MPRSAS_DISCOVERY_TIMEOUT_PENDING (1 << 2) #define MPRSAS_QUEUE_FROZEN (1 << 3) #define MPRSAS_SHUTDOWN (1 << 4) -#define MPRSAS_SCANTHREAD (1 << 5) u_int maxtargets; struct mprsas_target *targets; struct cam_devq *devq; @@ -103,7 +103,6 @@ struct mprsas_softc { struct mpr_event_handle *mprsas_eh; u_int startup_refcount; - u_int tm_count; struct proc *sysctl_proc; struct taskqueue *ev_tq; @@ -150,6 +149,19 @@ mprsas_set_lun(uint8_t *lun, u_int ccblun) return (0); } +static __inline void +mprsas_set_ccbstatus(union ccb *ccb, int status) +{ + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= status; +} + +static __inline int +mprsas_get_ccbstatus(union ccb *ccb) +{ + return (ccb->ccb_h.status & CAM_STATUS_MASK); +} + #define MPR_SET_SINGLE_LUN(req, lun) \ do { \ bzero((req)->LUN, 8); \ @@ -158,11 +170,10 @@ do { \ void mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ); void mprsas_discovery_end(struct mprsas_softc *sassc); +void mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, + struct mprsas_target *target, lun_id_t lun_id); void mprsas_startup_increment(struct mprsas_softc *sassc); void mprsas_startup_decrement(struct mprsas_softc *sassc); -void mprsas_release_simq_reinit(struct mprsas_softc *sassc); -struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); -void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); void mprsas_firmware_event_work(void *arg, int pending); int mprsas_check_id(struct mprsas_softc *sassc, int id); diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 32e9b3a07804..7d6ef7070f7d 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for LSI MPT3 */ /* TODO Move headers to mprvar */ #include @@ -105,7 +106,9 @@ struct _ata_identify_device_data { u16 serial_number[10]; /* 10-19 */ u16 reserved2[7]; /* 20-26 */ u16 model_number[20]; /* 27-46*/ - u16 reserved3[209]; /* 47-255*/ + u16 reserved3[170]; /* 47-216 */ + u16 rotational_speed; /* 217 */ + u16 reserved4[38]; /* 218-255 */ }; static u32 event_count; static void mprsas_fw_work(struct mpr_softc *sc, @@ -116,8 +119,9 @@ static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate); static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo); +static void mprsas_ata_id_timeout(void *data); int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, - u64 *sas_address, u16 handle, u32 device_info); + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); static int mprsas_volume_add(struct mpr_softc *sc, u16 handle); static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc); @@ -325,7 +329,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) return; } - mpr_dprint(sc, MPR_INFO, "Sending FP action " + mpr_dprint(sc, MPR_EVENT, "Sending FP action " "from " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST " ":\n"); @@ -350,9 +354,9 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) if (reply && (le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { - mpr_dprint(sc, MPR_INFO, "%s: error " - "sending RaidActionPage; iocstatus " - "= 0x%x\n", __func__, + mpr_dprint(sc, MPR_ERROR, "%s: error " + "sending RaidActionPage; " + "iocstatus = 0x%x\n", __func__, le16toh(reply->IOCStatus)); } @@ -360,7 +364,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) mpr_free_command(sc, cm); } skip_fp_send: - mpr_dprint(sc, MPR_INFO, "Received " + mpr_dprint(sc, MPR_EVENT, "Received " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason " "code %x:\n", element->ReasonCode); switch (element->ReasonCode) { @@ -421,7 +425,6 @@ skip_fp_send: break; targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT; mprsas_rescan_target(sc, targ); - break; case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: /* @@ -678,14 +681,13 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ struct mprsas_target *targ; Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t config_page; - uint64_t sas_address, sata_sas_address; - uint64_t parent_sas_address = 0; - u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); + uint64_t sas_address, parent_sas_address = 0; u32 device_info, parent_devinfo = 0; unsigned int id; - int ret; - int error = 0; + int ret = 1, error = 0, i; struct mprsas_lun *lun; + u8 is_SATA_SSD = 0; + struct mpr_command *cm; sassc = sc->sassc; mprsas_startup_increment(sassc); @@ -717,26 +719,29 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ } /* TODO Check proper endianess */ sas_address = config_page.SASAddress.High; - sas_address = (sas_address << 32) | - config_page.SASAddress.Low; + sas_address = (sas_address << 32) | config_page.SASAddress.Low; + mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n", + sas_address); - if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) - == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { - if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { - ret = mprsas_get_sas_address_for_sata_disk(sc, - &sata_sas_address, handle, device_info); - if (!ret) - id = mpr_mapping_get_sas_id(sc, - sata_sas_address, handle); - else - id = mpr_mapping_get_sas_id(sc, - sas_address, handle); - } else - id = mpr_mapping_get_sas_id(sc, sas_address, - handle); - } else - id = mpr_mapping_get_sas_id(sc, sas_address, handle); + /* + * Always get SATA Identify information because this is used to + * determine if Start/Stop Unit should be sent to the drive when the + * system is shutdown. + */ + if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { + ret = mprsas_get_sas_address_for_sata_disk(sc, &sas_address, + handle, device_info, &is_SATA_SSD); + if (ret) { + mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type " + "(SSD or HDD) for SATA device with handle 0x%04x\n", + __func__, handle); + } else { + mpr_dprint(sc, MPR_INFO, "SAS Address from SATA " + "device = %jx\n", sas_address); + } + } + id = mpr_mapping_get_sas_id(sc, sas_address, handle); if (id == MPR_MAP_BAD_ID) { printf("failure at %s:%d/%s()! Could not get ID for device " "with handle 0x%04x\n", __FILE__, __LINE__, __func__, @@ -750,7 +755,7 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ error = ENXIO; goto out; } - + mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; @@ -773,6 +778,9 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ targ->tid = id; targ->linkrate = (linkrate>>4); targ->flags = 0; + if (is_SATA_SSD) { + targ->flags = MPR_TARGET_IS_SATA_SSD; + } if (le16toh(config_page.Flags) & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) { targ->scsi_req_desc_type = @@ -792,12 +800,12 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ SLIST_INIT(&targ->luns); mpr_describe_devinfo(targ->devinfo, devstring, 80); - mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "Found device <%s> <%s> " + mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> " "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring, mpr_describe_table(mpr_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); if (targ->encl_level_valid) { - mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "At enclosure level %d " + mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d " "and connector name (%4s)\n", targ->encl_level, targ->connector_name); } @@ -807,15 +815,57 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ #endif mprsas_rescan_target(sc, targ); mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid); + + /* + * Check all commands to see if the SATA_ID_TIMEOUT flag has been set. + * If so, send a Target Reset TM to the target that was just created. + * An Abort Task TM should be used instead of a Target Reset, but that + * would be much more difficult because targets have not been fully + * discovered yet, and LUN's haven't been setup. So, just reset the + * target instead of the LUN. + */ + for (i = 1; i < sc->num_reqs; i++) { + cm = &sc->commands[i]; + if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { + targ->timeouts++; + cm->cm_state = MPR_CM_STATE_TIMEDOUT; + + if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { + mpr_dprint(sc, MPR_INFO, "%s: sending Target " + "Reset for stuck SATA identify command " + "(cm = %p)\n", __func__, cm); + targ->tm->cm_targ = targ; + mprsas_send_reset(sc, targ->tm, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); + } else { + mpr_dprint(sc, MPR_ERROR, "Failed to allocate " + "tm for Target Reset after SATA ID " + "command timed out (cm %p)\n", cm); + } + /* + * No need to check for more since the target is + * already being reset. + */ + break; + } + } out: + /* + * Free the commands that may not have been freed from the SATA ID call + */ + for (i = 1; i < sc->num_reqs; i++) { + cm = &sc->commands[i]; + if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { + mpr_free_command(sc, cm); + } + } mprsas_startup_decrement(sassc); return (error); - } int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, - u64 *sas_address, u16 handle, u32 device_info) + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD) { Mpi2SataPassthroughReply_t mpi_reply; int i, rc, try_count; @@ -835,7 +885,16 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, ioc_status = le16toh(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; sas_status = mpi_reply.SASStatus; - } while ((rc == -EAGAIN || ioc_status || sas_status) && + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + if (sc->spinup_wait_time > 0) { + mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds " + "after SATA ID error to wait for spinup\n", + sc->spinup_wait_time); + msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, + "mprid", sc->spinup_wait_time * hz); + } + } + } while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) && (try_count < 5)); if (rc == 0 && !ioc_status && !sas_status) { @@ -884,6 +943,10 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 | (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 | (u64)hash_address.wwid[7]; + if (ata_identify.rotational_speed == 1) { + *is_SATA_SSD = 1; + } + return 0; } @@ -923,14 +986,29 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = buffer; cm->cm_length = htole32(sz); + + /* + * Start a timeout counter specifically for the SATA ID command. This + * is used to fix a problem where the FW does not send a reply sometimes + * when a bad disk is in the topology. So, this is used to timeout the + * command so that processing can continue normally. + */ + mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID " + "command\n", __func__); + callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz, + mprsas_ata_id_timeout, cm); error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); + mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID " + "command\n", __func__); + callout_stop(&cm->cm_callout); + reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* * If the request returns an error then we need to do a diag * reset - */ + */ printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; @@ -946,11 +1024,66 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, goto out; } out: - mpr_free_command(sc, cm); - free(buffer, M_MPR); + /* + * If the SATA_ID_TIMEOUT flag has been set for this command, don't free + * it. The command will be freed after sending a target reset TM. If + * the command did timeout, use EWOULDBLOCK. + */ + if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) + mpr_free_command(sc, cm); + else if (error == 0) + error = EWOULDBLOCK; + free(buffer, M_MPR); return (error); } +static void +mprsas_ata_id_timeout(void *data) +{ + struct mpr_softc *sc; + struct mpr_command *cm; + + cm = (struct mpr_command *)data; + sc = cm->cm_sc; + mtx_assert(&sc->mpr_mtx, MA_OWNED); + + mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n", + __func__, cm, sc); + if ((callout_pending(&cm->cm_callout)) || + (!callout_active(&cm->cm_callout))) { + mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " + "out\n", __func__); + return; + } + callout_deactivate(&cm->cm_callout); + + /* + * Run the interrupt handler to make sure it's not pending. This + * isn't perfect because the command could have already completed + * and been re-used, though this is unlikely. + */ + mpr_intr_locked(sc); + if (cm->cm_state == MPR_CM_STATE_FREE) { + mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " + "out\n", __func__); + return; + } + + mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm); + + /* + * Send wakeup() to the sleeping thread that issued this ATA ID + * command. wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), + * and this will keep reinit() from being called. This way, an Abort + * Task TM can be issued so that the timed out command can be cleared. + * The Abort Task cannot be sent from here because the driver has not + * completed setting up targets. Instead, the command is flagged so + * that special handling will be used to send the abort. + */ + cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT; + wakeup(cm); +} + static int mprsas_volume_add(struct mpr_softc *sc, u16 handle) { @@ -1024,15 +1157,13 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) path_id_t pathid = cam_sim_path(sassc->sim); target_id_t targetid; struct mprsas_target *target; - struct mprsas_lun *lun; char path_str[64]; struct timeval cur_time, start_time; mpr_lock(sc); /* - * For each LUN of each target, issue a StartStopUnit command to stop - * the device. + * For each target, issue a StartStopUnit command to stop the device. */ sc->SSU_started = TRUE; sc->SSU_refcount = 0; @@ -1042,59 +1173,52 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) continue; } - SLIST_FOREACH(lun, &target->luns, lun_link) { - ccb = xpt_alloc_ccb_nowait(); - if (ccb == NULL) { - mpr_unlock(sc); - mpr_dprint(sc, MPR_FAULT, "Unable to alloc " - "CCB to stop unit.\n"); + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB to stop " + "unit.\n"); + return; + } + + /* + * The stop_at_shutdown flag will be set if this device is + * a SATA direct-access end device. + */ + if (target->stop_at_shutdown) { + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, + pathid, targetid, CAM_LUN_WILDCARD) != + CAM_REQ_CMP) { + mpr_dprint(sc, MPR_ERROR, "Unable to create " + "path to stop unit.\n"); + xpt_free_ccb(ccb); return; } + xpt_path_string(ccb->ccb_h.path, path_str, + sizeof(path_str)); + + mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s " + "handle %d\n", path_str, target->handle); /* - * The stop_at_shutdown flag will be set if this LUN is - * a SATA direct-access end device. + * Issue a START STOP UNIT command for the target. + * Increment the SSU counter to be used to count the + * number of required replies. */ - if (lun->stop_at_shutdown) { - if (xpt_create_path(&ccb->ccb_h.path, - xpt_periph, pathid, targetid, - lun->lun_id) != CAM_REQ_CMP) { - mpr_dprint(sc, MPR_FAULT, "Unable to " - "create LUN path to stop unit.\n"); - xpt_free_ccb(ccb); - mpr_unlock(sc); - return; - } - xpt_path_string(ccb->ccb_h.path, path_str, - sizeof(path_str)); - - mpr_dprint(sc, MPR_INFO, "Sending StopUnit: " - "path %s handle %d\n", path_str, - target->handle); - - /* - * Issue a START STOP UNIT command for the LUN. - * Increment the SSU counter to be used to - * count the number of required replies. - */ - mpr_dprint(sc, MPR_INFO, "Incrementing SSU " - "count\n"); - sc->SSU_refcount++; - ccb->ccb_h.target_id = - xpt_path_target_id(ccb->ccb_h.path); - ccb->ccb_h.target_lun = lun->lun_id; - ccb->ccb_h.ppriv_ptr1 = sassc; - scsi_start_stop(&ccb->csio, - /*retries*/0, - mprsas_stop_unit_done, - MSG_SIMPLE_Q_TAG, - /*start*/FALSE, - /*load/eject*/0, - /*immediate*/FALSE, - MPR_SENSE_LEN, - /*timeout*/10000); - xpt_action(ccb); - } + mpr_dprint(sc, MPR_INFO, "Incrementing SSU count\n"); + sc->SSU_refcount++; + ccb->ccb_h.target_id = + xpt_path_target_id(ccb->ccb_h.path); + ccb->ccb_h.ppriv_ptr1 = sassc; + scsi_start_stop(&ccb->csio, + /*retries*/0, + mprsas_stop_unit_done, + MSG_SIMPLE_Q_TAG, + /*start*/FALSE, + /*load/eject*/0, + /*immediate*/FALSE, + MPR_SENSE_LEN, + /*timeout*/10000); + xpt_action(ccb); } } @@ -1102,7 +1226,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) /* * Wait until all of the SSU commands have completed or time has - * expired (60 seconds). pause for 100ms each time through. If any + * expired (60 seconds). Pause for 100ms each time through. If any * command times out, the target will be reset in the SCSI command * timeout routine. */ @@ -1112,7 +1236,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) getmicrotime(&cur_time); if ((cur_time.tv_sec - start_time.tv_sec) > 60) { - mpr_dprint(sc, MPR_FAULT, "Time has expired waiting " + mpr_dprint(sc, MPR_ERROR, "Time has expired waiting " "for SSU commands to complete.\n"); break; } @@ -1162,6 +1286,8 @@ mprsas_ir_shutdown(struct mpr_softc *sc) unsigned int id, found_volume = 0; struct mpr_command *cm; Mpi2RaidActionRequest_t *action; + target_id_t targetid; + struct mprsas_target *target; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); @@ -1214,5 +1340,47 @@ mprsas_ir_shutdown(struct mpr_softc *sc) mpr_free_command(sc, cm); out: + /* + * All of the targets must have the correct value set for + * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable. + * + * The possible values for the 'enable_ssu' variable are: + * 0: disable to SSD and HDD + * 1: disable only to HDD (default) + * 2: disable only to SSD + * 3: enable to SSD and HDD + * anything else will default to 1. + */ + for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { + target = &sc->sassc->targets[targetid]; + if (target->handle == 0x0) { + continue; + } + + if (target->supports_SSU) { + switch (sc->enable_ssu) { + case MPR_SSU_DISABLE_SSD_DISABLE_HDD: + target->stop_at_shutdown = FALSE; + break; + case MPR_SSU_DISABLE_SSD_ENABLE_HDD: + target->stop_at_shutdown = TRUE; + if (target->flags & MPR_TARGET_IS_SATA_SSD) { + target->stop_at_shutdown = FALSE; + } + break; + case MPR_SSU_ENABLE_SSD_ENABLE_HDD: + target->stop_at_shutdown = TRUE; + break; + case MPR_SSU_ENABLE_SSD_DISABLE_HDD: + default: + target->stop_at_shutdown = TRUE; + if ((target->flags & + MPR_TARGET_IS_SATA_SSD) == 0) { + target->stop_at_shutdown = FALSE; + } + break; + } + } + } mprsas_SSU_to_SATA_devices(sc); } diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 60680f5288a3..37d946718b23 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_user.c @@ -27,10 +27,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD userland interface + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface */ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +55,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -90,7 +91,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include @@ -284,8 +285,7 @@ mpr_user_read_cfg_header(struct mpr_softc *sc, static int mpr_user_read_cfg_page(struct mpr_softc *sc, - struct mpr_cfg_page_req *page_req, - void *buf) + struct mpr_cfg_page_req *page_req, void *buf) { MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; struct mpr_config_params params; @@ -328,6 +328,10 @@ mpr_user_read_extcfg_header(struct mpr_softc *sc, hdr->PageNumber = ext_page_req->header.PageNumber; hdr->ExtPageType = ext_page_req->header.ExtPageType; params.page_address = le32toh(ext_page_req->page_address); + params.buffer = NULL; + params.length = 0; + params.callback = NULL; + if ((error = mpr_read_config_page(sc, ¶ms)) != 0) { /* * Leave the request. Without resetting the chip, it's @@ -365,8 +369,8 @@ mpr_user_read_extcfg_page(struct mpr_softc *sc, params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; params.page_address = le32toh(ext_page_req->page_address); hdr->PageVersion = reqhdr->PageVersion; - hdr->PageNumber = reqhdr->PageNumber; hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + hdr->PageNumber = reqhdr->PageNumber; hdr->ExtPageType = reqhdr->ExtPageType; hdr->ExtPageLength = reqhdr->ExtPageLength; params.buffer = buf; @@ -541,6 +545,8 @@ mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd) req->ImageOffset = 0; req->ImageSize = cmd->len; + cm->cm_flags |= MPR_CM_FLAGS_DATAIN; + return (mpr_push_ieee_sge(cm, &req->SGL, 0)); } @@ -834,11 +840,22 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) task->TaskMID = cm->cm_desc.Default.SMID; cm->cm_data = NULL; - cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; + cm->cm_desc.HighPriority.RequestFlags = + MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = NULL; cm->cm_complete_data = NULL; - err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + targ = mprsas_find_target_by_handle(sc->sassc, 0, + task->DevHandle); + if (targ == NULL) { + mpr_dprint(sc, MPR_INFO, + "%s %d : invalid handle for requested TM 0x%x \n", + __func__, __LINE__, task->DevHandle); + err = 1; + } else { + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + } if (err != 0) { err = EIO; @@ -1029,7 +1046,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) dir = BUS_DMASYNC_POSTREAD; else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT) - dir = BUS_DMASYNC_POSTWRITE;; + dir = BUS_DMASYNC_POSTWRITE; bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); @@ -1351,8 +1368,8 @@ done: } static int -mpr_diag_register(struct mpr_softc *sc, - mpr_fw_diag_register_t *diag_register, uint32_t *return_code) +mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, + uint32_t *return_code) { mpr_fw_diagnostic_buffer_t *pBuffer; uint8_t extended_type, buffer_type, i; diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index 9752dcd35f6f..acac44c5baec 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,13 +25,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * * $FreeBSD$ */ #ifndef _MPRVAR_H #define _MPRVAR_H -#define MPR_DRIVER_VERSION "05.255.05.00-fbsd" +#define MPR_DRIVER_VERSION "09.255.01.00-fbsd" #define MPR_DB_MAX_WAIT 2500 @@ -47,16 +50,19 @@ #define MPR_FUNCTRACE(sc) \ mpr_dprint((sc), MPR_TRACE, "%s\n", __func__) -#define CAN_SLEEP 1 -#define NO_SLEEP 0 +#define CAN_SLEEP 1 +#define NO_SLEEP 0 #define MPR_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */ +#define MPR_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */ #define IFAULT_IOP_OVER_TEMP_THRESHOLD_EXCEEDED 0x2810 #define MPR_SCSI_RI_INVALID_FRAME (0x00000002) #define MPR_STRING_LENGTH 64 +#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */ + #include /* @@ -213,13 +219,14 @@ struct mpr_command { #define MPR_CM_FLAGS_CHAIN_FAILED (1 << 8) #define MPR_CM_FLAGS_ERROR_MASK MPR_CM_FLAGS_CHAIN_FAILED #define MPR_CM_FLAGS_USE_CCB (1 << 9) +#define MPR_CM_FLAGS_SATA_ID_TIMEOUT (1 << 10) u_int cm_state; #define MPR_CM_STATE_FREE 0 #define MPR_CM_STATE_BUSY 1 #define MPR_CM_STATE_TIMEDOUT 2 bus_dmamap_t cm_dmamap; struct scsi_sense_data *cm_sense; - TAILQ_HEAD(, mpr_chain) cm_chain_list; + TAILQ_HEAD(, mpr_chain) cm_chain_list; uint32_t cm_req_busaddr; uint32_t cm_sense_busaddr; struct callout cm_callout; @@ -256,6 +263,8 @@ struct mpr_softc { int chain_free; int max_chains; int chain_free_lowwater; + u_int enable_ssu; + int spinup_wait_time; #if __FreeBSD_version >= 900030 uint64_t chain_alloc_fail; #endif @@ -270,7 +279,7 @@ struct mpr_softc { char tmp_string[MPR_STRING_LENGTH]; TAILQ_HEAD(, mpr_command) req_list; TAILQ_HEAD(, mpr_command) high_priority_req_list; - TAILQ_HEAD(, mpr_chain) chain_list; + TAILQ_HEAD(, mpr_chain) chain_list; TAILQ_HEAD(, mpr_command) tm_list; int replypostindex; int replyfreeindex; @@ -291,7 +300,7 @@ struct mpr_softc { uint8_t event_mask[16]; TAILQ_HEAD(, mpr_event_handle) event_list; - struct mpr_event_handle *mpr_log_eh; + struct mpr_event_handle *mpr_log_eh; struct mtx mpr_mtx; struct intr_config_hook mpr_ich; @@ -565,6 +574,11 @@ mpr_unlock(struct mpr_softc *sc) #define MPR_MAPPING (1 << 9) /* Trace device mappings */ #define MPR_TRACE (1 << 10) /* Function-by-function trace */ +#define MPR_SSU_DISABLE_SSD_DISABLE_HDD 0 +#define MPR_SSU_ENABLE_SSD_DISABLE_HDD 1 +#define MPR_SSU_DISABLE_SSD_ENABLE_HDD 2 +#define MPR_SSU_ENABLE_SSD_ENABLE_HDD 3 + #define mpr_printf(sc, args...) \ device_printf((sc)->mpr_dev, ##args) @@ -600,9 +614,6 @@ do { \ #define MPR_EVENTFIELD(sc, facts, attr, fmt) \ mpr_dprint_field((sc), MPR_EVENT, #attr ": " #fmt "\n", (facts)->attr) -#define CAN_SLEEP 1 -#define NO_SLEEP 0 - static __inline void mpr_from_u64(uint64_t data, U64 *mpr) { @@ -613,7 +624,6 @@ mpr_from_u64(uint64_t data, U64 *mpr) static __inline uint64_t mpr_to_u64(U64 *data) { - return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low)); } @@ -727,6 +737,12 @@ void mprsas_prepare_volume_remove(struct mprsas_softc *sassc, int mprsas_startup(struct mpr_softc *sc); struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *, int, uint16_t); +void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets); +struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); +void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); +void mprsas_release_simq_reinit(struct mprsas_softc *sassc); +int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, + uint8_t type); SYSCTL_DECL(_hw_mpr); From 7c550ca17d1f1837103075166c4d229c0bca95da Mon Sep 17 00:00:00 2001 From: rmacklem Date: Wed, 27 May 2015 22:00:05 +0000 Subject: [PATCH 19/65] Make the size of the hash tables used by the NFSv4 server tunable. No appreciable change in performance was observed after increasing the sizes of these tables and then testing with a single client. However, there was an email that indicated high CPU overheads for a heavily loaded NFSv4 and it is hoped that increasing the sizes of the hash tables via these tunables might help. The tables remain the same size by default. Differential Revision: https://reviews.freebsd.org/D2596 MFC after: 2 weeks --- sys/fs/nfs/nfs.h | 4 +- sys/fs/nfs/nfsdport.h | 2 +- sys/fs/nfs/nfsrvstate.h | 12 ++--- sys/fs/nfsserver/nfs_nfsdport.c | 13 +++-- sys/fs/nfsserver/nfs_nfsdserv.c | 22 ++++++--- sys/fs/nfsserver/nfs_nfsdsocket.c | 5 +- sys/fs/nfsserver/nfs_nfsdstate.c | 80 ++++++++++++++++++++----------- sys/fs/nfsserver/nfs_nfsdsubs.c | 23 ++++++--- 8 files changed, 105 insertions(+), 56 deletions(-) diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h index 2ee91457b5a1..be60c1ca7753 100644 --- a/sys/fs/nfs/nfs.h +++ b/sys/fs/nfs/nfs.h @@ -138,11 +138,11 @@ /* * This macro defines the high water mark for issuing V4 delegations. - * (It is currently set at a conservative 20% of NFSRV_V4STATELIMIT. This + * (It is currently set at a conservative 20% of nfsrv_v4statelimit. This * may want to increase when clients can make more effective use of * delegations.) */ -#define NFSRV_V4DELEGLIMIT(c) (((c) * 5) > NFSRV_V4STATELIMIT) +#define NFSRV_V4DELEGLIMIT(c) (((c) * 5) > nfsrv_v4statelimit) #define NFS_READDIRBLKSIZ DIRBLKSIZ /* Minimal nm_readdirsize */ diff --git a/sys/fs/nfs/nfsdport.h b/sys/fs/nfs/nfsdport.h index efa4b12500ca..a20b55469a71 100644 --- a/sys/fs/nfs/nfsdport.h +++ b/sys/fs/nfs/nfsdport.h @@ -88,7 +88,7 @@ struct nfsexstuff { bcmp(&(f1)->fh_fid, &(f2)->fh_fid, sizeof(struct fid)) == 0) #define NFSLOCKHASH(f) \ - (&nfslockhash[nfsrv_hashfh(f) % NFSLOCKHASHSIZE]) + (&nfslockhash[nfsrv_hashfh(f) % nfsrv_lockhashsize]) #define NFSFPVNODE(f) ((struct vnode *)((f)->f_data)) #define NFSFPCRED(f) ((f)->f_cred) diff --git a/sys/fs/nfs/nfsrvstate.h b/sys/fs/nfs/nfsrvstate.h index 59a0542c1c9c..972fffe15eb9 100644 --- a/sys/fs/nfs/nfsrvstate.h +++ b/sys/fs/nfs/nfsrvstate.h @@ -52,9 +52,9 @@ LIST_HEAD(nfsuserhashhead, nfsusrgrp); TAILQ_HEAD(nfsuserlruhead, nfsusrgrp); #define NFSCLIENTHASH(id) \ - (&nfsclienthash[(id).lval[1] % NFSCLIENTHASHSIZE]) + (&nfsclienthash[(id).lval[1] % nfsrv_clienthashsize]) #define NFSSTATEHASH(clp, id) \ - (&((clp)->lc_stateid[(id).other[2] % NFSSTATEHASHSIZE])) + (&((clp)->lc_stateid[(id).other[2] % nfsrv_statehashsize])) #define NFSUSERHASH(id) \ (&nfsuserhash[(id) % NFSUSERHASHSIZE]) #define NFSUSERNAMEHASH(p, l) \ @@ -71,7 +71,7 @@ struct nfssessionhash { struct nfssessionhashhead list; }; #define NFSSESSIONHASH(f) \ - (&nfssessionhash[nfsrv_hashsessionid(f) % NFSSESSIONHASHSIZE]) + (&nfssessionhash[nfsrv_hashsessionid(f) % nfsrv_sessionhashsize]) /* * Client server structure for V4. It is doubly linked into two lists. @@ -81,7 +81,7 @@ struct nfssessionhash { */ struct nfsclient { LIST_ENTRY(nfsclient) lc_hash; /* Clientid hash list */ - struct nfsstatehead lc_stateid[NFSSTATEHASHSIZE]; /* stateid hash */ + struct nfsstatehead *lc_stateid; /* Stateid hash */ struct nfsstatehead lc_open; /* Open owner list */ struct nfsstatehead lc_deleg; /* Delegations */ struct nfsstatehead lc_olddeleg; /* and old delegations */ @@ -97,10 +97,10 @@ struct nfsclient { u_int32_t lc_cbref; /* Cnt of callbacks */ uid_t lc_uid; /* User credential */ gid_t lc_gid; - u_int16_t lc_namelen; + u_int16_t lc_idlen; /* Client ID and len */ + u_int16_t lc_namelen; /* plus GSS principal and len */ u_char *lc_name; struct nfssockreq lc_req; /* Callback info */ - u_short lc_idlen; /* Length of id string */ u_int32_t lc_flags; /* LCL_ flag bits */ u_char lc_verf[NFSX_VERF]; /* client verifier */ u_char lc_id[1]; /* Malloc'd correct size */ diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 94475d93c66a..85b4466575af 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -58,7 +58,10 @@ extern struct nfsrv_stablefirst nfsrv_stablefirst; extern void (*nfsd_call_servertimer)(void); extern SVCPOOL *nfsrvd_pool; extern struct nfsv4lock nfsd_suspend_lock; -extern struct nfssessionhash nfssessionhash[NFSSESSIONHASHSIZE]; +extern struct nfsclienthashhead *nfsclienthash; +extern struct nfslockhashhead *nfslockhash; +extern struct nfssessionhash *nfssessionhash; +extern int nfsrv_sessionhashsize; struct vfsoptlist nfsv4root_opt, nfsv4root_newopt; NFSDLOCKMUTEX; struct nfsrchash_bucket nfsrchash_table[NFSRVCACHE_HASHSIZE]; @@ -3330,9 +3333,6 @@ nfsd_modevent(module_t mod, int type, void *data) mtx_init(&nfsrc_udpmtx, "nfsuc", NULL, MTX_DEF); mtx_init(&nfs_v4root_mutex, "nfs4rt", NULL, MTX_DEF); mtx_init(&nfsv4root_mnt.mnt_mtx, "nfs4mnt", NULL, MTX_DEF); - for (i = 0; i < NFSSESSIONHASHSIZE; i++) - mtx_init(&nfssessionhash[i].mtx, "nfssm", - NULL, MTX_DEF); lockinit(&nfsv4root_mnt.mnt_explock, PVFS, "explock", 0, 0); nfsrvd_initcache(); nfsd_init(); @@ -3380,9 +3380,12 @@ nfsd_modevent(module_t mod, int type, void *data) mtx_destroy(&nfsrc_udpmtx); mtx_destroy(&nfs_v4root_mutex); mtx_destroy(&nfsv4root_mnt.mnt_mtx); - for (i = 0; i < NFSSESSIONHASHSIZE; i++) + for (i = 0; i < nfsrv_sessionhashsize; i++) mtx_destroy(&nfssessionhash[i].mtx); lockdestroy(&nfsv4root_mnt.mnt_explock); + free(nfsclienthash, M_NFSDCLIENT); + free(nfslockhash, M_NFSDLOCKFILE); + free(nfssessionhash, M_NFSDSESSION); loaded = 0; break; default: diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index bd0c2dad73ad..bd054c47718d 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -53,6 +53,7 @@ extern enum vtype nv34tov_type[8]; extern struct timeval nfsboottime; extern int nfs_rootfhset; extern int nfsrv_enable_crossmntpt; +extern int nfsrv_statehashsize; #endif /* !APPLEKEXT */ static int nfs_async = 0; @@ -3468,9 +3469,10 @@ nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram, idlen = i; if (nd->nd_flag & ND_GSS) i += nd->nd_princlen; - MALLOC(clp, struct nfsclient *, sizeof (struct nfsclient) + i, - M_NFSDCLIENT, M_WAITOK); - NFSBZERO((caddr_t)clp, sizeof (struct nfsclient) + i); + clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK | + M_ZERO); + clp->lc_stateid = malloc(sizeof(struct nfsstatehead) * + nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK); NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx); NFSSOCKADDRALLOC(clp->lc_req.nr_nam); NFSSOCKADDRSIZE(clp->lc_req.nr_nam, sizeof (struct sockaddr_in)); @@ -3530,7 +3532,8 @@ nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram, if (clp) { NFSSOCKADDRFREE(clp->lc_req.nr_nam); NFSFREEMUTEX(&clp->lc_req.nr_mtx); - free((caddr_t)clp, M_NFSDCLIENT); + free(clp->lc_stateid, M_NFSDCLIENT); + free(clp, M_NFSDCLIENT); } if (!nd->nd_repstat) { NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER); @@ -3547,7 +3550,8 @@ nfsmout: if (clp) { NFSSOCKADDRFREE(clp->lc_req.nr_nam); NFSFREEMUTEX(&clp->lc_req.nr_mtx); - free((caddr_t)clp, M_NFSDCLIENT); + free(clp->lc_stateid, M_NFSDCLIENT); + free(clp, M_NFSDCLIENT); } NFSEXITCODE2(error, nd); return (error); @@ -3738,8 +3742,10 @@ nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram, idlen = i; if (nd->nd_flag & ND_GSS) i += nd->nd_princlen; - clp = (struct nfsclient *)malloc(sizeof(struct nfsclient) + i, - M_NFSDCLIENT, M_WAITOK | M_ZERO); + clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK | + M_ZERO); + clp->lc_stateid = malloc(sizeof(struct nfsstatehead) * + nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK); NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx); NFSSOCKADDRALLOC(clp->lc_req.nr_nam); NFSSOCKADDRSIZE(clp->lc_req.nr_nam, sizeof (struct sockaddr_in)); @@ -3796,6 +3802,7 @@ nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram, if (clp != NULL) { NFSSOCKADDRFREE(clp->lc_req.nr_nam); NFSFREEMUTEX(&clp->lc_req.nr_mtx); + free(clp->lc_stateid, M_NFSDCLIENT); free(clp, M_NFSDCLIENT); } if (nd->nd_repstat == 0) { @@ -3828,6 +3835,7 @@ nfsmout: if (clp != NULL) { NFSSOCKADDRFREE(clp->lc_req.nr_nam); NFSFREEMUTEX(&clp->lc_req.nr_mtx); + free(clp->lc_stateid, M_NFSDCLIENT); free(clp, M_NFSDCLIENT); } NFSEXITCODE2(error, nd); diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c index b15dfec4b648..9c00a0c09b31 100644 --- a/sys/fs/nfsserver/nfs_nfsdsocket.c +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -46,7 +46,8 @@ extern struct nfsrvfh nfs_pubfh, nfs_rootfh; extern int nfs_pubfhset, nfs_rootfhset; extern struct nfsv4lock nfsv4rootfs_lock; extern struct nfsrv_stablefirst nfsrv_stablefirst; -extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; +extern struct nfsclienthashhead *nfsclienthash; +extern int nfsrv_clienthashsize; extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies; extern int nfsd_debuglevel; NFSV4ROOTLOCKMUTEX; @@ -610,7 +611,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, */ if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) { nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT; - for (i = 0; i < NFSCLIENTHASHSIZE; i++) { + for (i = 0; i < nfsrv_clienthashsize; i++) { LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { if (clp->lc_flags & LCL_EXPIREIT) { diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index 5e9beebf0875..15f5243717cf 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -44,14 +44,38 @@ extern u_int32_t newnfs_true, newnfs_false; NFSV4ROOTLOCKMUTEX; NFSSTATESPINLOCK; +SYSCTL_DECL(_vfs_nfsd); +int nfsrv_statehashsize = NFSSTATEHASHSIZE; +SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN, + &nfsrv_statehashsize, 0, + "Size of state hash table set via loader.conf"); + +int nfsrv_clienthashsize = NFSCLIENTHASHSIZE; +SYSCTL_INT(_vfs_nfsd, OID_AUTO, clienthashsize, CTLFLAG_RDTUN, + &nfsrv_clienthashsize, 0, + "Size of client hash table set via loader.conf"); + +int nfsrv_lockhashsize = NFSLOCKHASHSIZE; +SYSCTL_INT(_vfs_nfsd, OID_AUTO, fhhashsize, CTLFLAG_RDTUN, + &nfsrv_lockhashsize, 0, + "Size of file handle hash table set via loader.conf"); + +int nfsrv_sessionhashsize = NFSSESSIONHASHSIZE; +SYSCTL_INT(_vfs_nfsd, OID_AUTO, sessionhashsize, CTLFLAG_RDTUN, + &nfsrv_sessionhashsize, 0, + "Size of session hash table set via loader.conf"); + +static int nfsrv_v4statelimit = NFSRV_V4STATELIMIT; +SYSCTL_INT(_vfs_nfsd, OID_AUTO, v4statelimit, CTLFLAG_RWTUN, + &nfsrv_v4statelimit, 0, + "High water limit for NFSv4 opens+locks+delegations"); + /* * Hash lists for nfs V4. - * (Some would put them in the .h file, but I don't like declaring storage - * in a .h) */ -struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; -struct nfslockhashhead nfslockhash[NFSLOCKHASHSIZE]; -struct nfssessionhash nfssessionhash[NFSSESSIONHASHSIZE]; +struct nfsclienthashhead *nfsclienthash; +struct nfslockhashhead *nfslockhash; +struct nfssessionhash *nfssessionhash; #endif /* !APPLEKEXT */ static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 0; @@ -153,7 +177,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, /* * Check for state resource limit exceeded. */ - if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) { + if (nfsrv_openpluslock > nfsrv_v4statelimit) { error = NFSERR_RESOURCE; goto out; } @@ -188,7 +212,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, * Search for a match in the client list. */ gotit = i = 0; - while (i < NFSCLIENTHASHSIZE && !gotit) { + while (i < nfsrv_clienthashsize && !gotit) { LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { if (new_clp->lc_idlen == clp->lc_idlen && !NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) { @@ -215,7 +239,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, /* * Get rid of the old one. */ - if (i != NFSCLIENTHASHSIZE) { + if (i != nfsrv_clienthashsize) { LIST_REMOVE(clp, lc_hash); nfsrv_cleanclient(clp, p); nfsrv_freedeleglist(&clp->lc_deleg); @@ -244,7 +268,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, LIST_INIT(&new_clp->lc_deleg); LIST_INIT(&new_clp->lc_olddeleg); LIST_INIT(&new_clp->lc_session); - for (i = 0; i < NFSSTATEHASHSIZE; i++) + for (i = 0; i < nfsrv_statehashsize; i++) LIST_INIT(&new_clp->lc_stateid[i]); LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, lc_hash); @@ -344,7 +368,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, ls_list); LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list) tstp->ls_clp = new_clp; - for (i = 0; i < NFSSTATEHASHSIZE; i++) { + for (i = 0; i < nfsrv_statehashsize; i++) { LIST_NEWHEAD(&new_clp->lc_stateid[i], &clp->lc_stateid[i], ls_hash); LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) @@ -405,7 +429,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, ls_list); LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list) tstp->ls_clp = new_clp; - for (i = 0; i < NFSSTATEHASHSIZE; i++) { + for (i = 0; i < nfsrv_statehashsize; i++) { LIST_NEWHEAD(&new_clp->lc_stateid[i], &clp->lc_stateid[i], ls_hash); LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) @@ -615,7 +639,7 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, if (!error && (opflags & CLOPS_RENEWOP)) { if (nfsrv_notsamecredname(nd, clp)) { doneok = 0; - for (i = 0; i < NFSSTATEHASHSIZE && doneok == 0; i++) { + for (i = 0; i < nfsrv_statehashsize && doneok == 0; i++) { LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { if ((stp->ls_flags & NFSLCK_OPEN) && stp->ls_uid == nd->nd_cred->cr_uid) { @@ -687,7 +711,7 @@ nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p) } /* Scan for state on the clientid. */ - for (i = 0; i < NFSSTATEHASHSIZE; i++) + for (i = 0; i < nfsrv_statehashsize; i++) if (!LIST_EMPTY(&clp->lc_stateid[i])) { NFSLOCKV4ROOTMUTEX(); nfsv4_unlock(&nfsv4rootfs_lock, 1); @@ -744,7 +768,7 @@ nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p) * Search for a match in the client list. */ gotit = i = 0; - while (i < NFSCLIENTHASHSIZE && !gotit) { + while (i < nfsrv_clienthashsize && !gotit) { LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { if (revokep->nclid_idlen == clp->lc_idlen && !NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) { @@ -806,7 +830,7 @@ nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt) /* * Rattle through the client lists until done. */ - while (i < NFSCLIENTHASHSIZE && cnt < maxcnt) { + while (i < nfsrv_clienthashsize && cnt < maxcnt) { clp = LIST_FIRST(&nfsclienthash[i]); while (clp != LIST_END(&nfsclienthash[i]) && cnt < maxcnt) { nfsrv_dumpaclient(clp, &dumpp[cnt]); @@ -1074,7 +1098,7 @@ nfsrv_servertimer(void) /* * For each client... */ - for (i = 0; i < NFSCLIENTHASHSIZE; i++) { + for (i = 0; i < nfsrv_clienthashsize; i++) { clp = LIST_FIRST(&nfsclienthash[i]); while (clp != LIST_END(&nfsclienthash[i])) { nclp = LIST_NEXT(clp, lc_hash); @@ -1085,7 +1109,7 @@ nfsrv_servertimer(void) nfsrv_clients > nfsrv_clienthighwater)) || (clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC || (clp->lc_expiry < NFSD_MONOSEC && - (nfsrv_openpluslock * 10 / 9) > NFSRV_V4STATELIMIT)) { + (nfsrv_openpluslock * 10 / 9) > nfsrv_v4statelimit)) { /* * Lease has expired several nfsrv_lease times ago: * PLUS @@ -1124,7 +1148,7 @@ nfsrv_servertimer(void) stp->ls_noopens++; if (stp->ls_noopens > NFSNOOPEN || (nfsrv_openpluslock * 2) > - NFSRV_V4STATELIMIT) + nfsrv_v4statelimit) nfsrv_stablefirst.nsf_flags |= NFSNSF_NOOPENS; } else { @@ -1188,7 +1212,8 @@ nfsrv_zapclient(struct nfsclient *clp, NFSPROC_T *p) newnfs_disconnect(&clp->lc_req); NFSSOCKADDRFREE(clp->lc_req.nr_nam); NFSFREEMUTEX(&clp->lc_req.nr_mtx); - free((caddr_t)clp, M_NFSDCLIENT); + free(clp->lc_stateid, M_NFSDCLIENT); + free(clp, M_NFSDCLIENT); NFSLOCKSTATE(); newnfsstats.srvclients--; nfsrv_openpluslock--; @@ -1534,7 +1559,7 @@ nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp, * Check for state resource limit exceeded. */ if ((new_stp->ls_flags & NFSLCK_LOCK) && - nfsrv_openpluslock > NFSRV_V4STATELIMIT) { + nfsrv_openpluslock > nfsrv_v4statelimit) { error = NFSERR_RESOURCE; goto out; } @@ -2232,7 +2257,7 @@ nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp, * returns NFSERR_RESOURCE and the limit is just a rather * arbitrary high water mark, so no harm is done. */ - if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) { + if (nfsrv_openpluslock > nfsrv_v4statelimit) { error = NFSERR_RESOURCE; goto out; } @@ -4298,7 +4323,7 @@ nfsrv_nextstateindex(struct nfsclient *clp) */ min_index = 0; max_index = 0xffffffff; - for (i = 0; i < NFSSTATEHASHSIZE; i++) { + for (i = 0; i < nfsrv_statehashsize; i++) { LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { if (stp->ls_stateid.other[2] > 0x80000000) { if (stp->ls_stateid.other[2] < max_index) @@ -4322,7 +4347,7 @@ nfsrv_nextstateindex(struct nfsclient *clp) * cleanest way to code the loop.) */ tryagain: - for (i = 0; i < NFSSTATEHASHSIZE; i++) { + for (i = 0; i < nfsrv_statehashsize; i++) { LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { if (stp->ls_stateid.other[2] == canuse) { canuse++; @@ -5319,13 +5344,13 @@ nfsrv_throwawayopens(NFSPROC_T *p) /* * For each client... */ - for (i = 0; i < NFSCLIENTHASHSIZE; i++) { + for (i = 0; i < nfsrv_clienthashsize; i++) { LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { if (LIST_EMPTY(&stp->ls_open) && (stp->ls_noopens > NFSNOOPEN || (nfsrv_openpluslock * 2) > - NFSRV_V4STATELIMIT)) + nfsrv_v4statelimit)) nfsrv_freeopenowner(stp, 0, p); } } @@ -5696,11 +5721,12 @@ nfsrv_throwawayallstate(NFSPROC_T *p) /* * For each client, clean out the state and then free the structure. */ - for (i = 0; i < NFSCLIENTHASHSIZE; i++) { + for (i = 0; i < nfsrv_clienthashsize; i++) { LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { nfsrv_cleanclient(clp, p); nfsrv_freedeleglist(&clp->lc_deleg); nfsrv_freedeleglist(&clp->lc_olddeleg); + free(clp->lc_stateid, M_NFSDCLIENT); free(clp, M_NFSDCLIENT); } } @@ -5708,7 +5734,7 @@ nfsrv_throwawayallstate(NFSPROC_T *p) /* * Also, free up any remaining lock file structures. */ - for (i = 0; i < NFSLOCKHASHSIZE; i++) { + for (i = 0; i < nfsrv_lockhashsize; i++) { LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) { printf("nfsd unload: fnd a lock file struct\n"); nfsrv_freenfslockfile(lfp); diff --git a/sys/fs/nfsserver/nfs_nfsdsubs.c b/sys/fs/nfsserver/nfs_nfsdsubs.c index 6bd141250784..c0421e34ce1f 100644 --- a/sys/fs/nfsserver/nfs_nfsdsubs.c +++ b/sys/fs/nfsserver/nfs_nfsdsubs.c @@ -44,9 +44,12 @@ __FBSDID("$FreeBSD$"); extern u_int32_t newnfs_true, newnfs_false; extern int nfs_pubfhset; -extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; -extern struct nfslockhashhead nfslockhash[NFSLOCKHASHSIZE]; -extern struct nfssessionhash nfssessionhash[NFSSESSIONHASHSIZE]; +extern struct nfsclienthashhead *nfsclienthash; +extern int nfsrv_clienthashsize; +extern struct nfslockhashhead *nfslockhash; +extern int nfsrv_lockhashsize; +extern struct nfssessionhash *nfssessionhash; +extern int nfsrv_sessionhashsize; extern int nfsrv_useacl; extern uid_t nfsrv_defaultuid; extern gid_t nfsrv_defaultgid; @@ -2036,12 +2039,20 @@ nfsd_init(void) * Initialize client queues. Don't free/reinitialize * them when nfsds are restarted. */ - for (i = 0; i < NFSCLIENTHASHSIZE; i++) + nfsclienthash = malloc(sizeof(struct nfsclienthashhead) * + nfsrv_clienthashsize, M_NFSDCLIENT, M_WAITOK | M_ZERO); + for (i = 0; i < nfsrv_clienthashsize; i++) LIST_INIT(&nfsclienthash[i]); - for (i = 0; i < NFSLOCKHASHSIZE; i++) + nfslockhash = malloc(sizeof(struct nfslockhashhead) * + nfsrv_lockhashsize, M_NFSDLOCKFILE, M_WAITOK | M_ZERO); + for (i = 0; i < nfsrv_lockhashsize; i++) LIST_INIT(&nfslockhash[i]); - for (i = 0; i < NFSSESSIONHASHSIZE; i++) + nfssessionhash = malloc(sizeof(struct nfssessionhash) * + nfsrv_sessionhashsize, M_NFSDSESSION, M_WAITOK | M_ZERO); + for (i = 0; i < nfsrv_sessionhashsize; i++) { + mtx_init(&nfssessionhash[i].mtx, "nfssm", NULL, MTX_DEF); LIST_INIT(&nfssessionhash[i].list); + } /* and the v2 pubfh should be all zeros */ NFSBZERO(nfs_v2pubfh, NFSX_V2FH); From 58e7a208774538c5e33d960683525cc7902ac213 Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 27 May 2015 22:25:49 +0000 Subject: [PATCH 20/65] - Don't request BUS_DMA_ALLOCNOW for dma tags, that requires enormous amount of memory. - Don't request segsize of BUS_SPACE_MAXSIZE_32BIT, when maxsize is MCLBYTES. With this change bwi_attach() can succeed on i386. Submitted by: scottl --- sys/dev/bwi/if_bwi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index 97b7021cd3a1..9f66ff45da7f 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -1921,7 +1921,7 @@ bwi_dma_alloc(struct bwi_softc *sc) BUS_SPACE_MAXSIZE, /* maxsize */ BUS_SPACE_UNRESTRICTED, /* nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ + 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->sc_parent_dtag); if (error) { @@ -1942,7 +1942,7 @@ bwi_dma_alloc(struct bwi_softc *sc) tx_ring_sz, 1, BUS_SPACE_MAXSIZE_32BIT, - BUS_DMA_ALLOCNOW, + 0, NULL, NULL, &sc->sc_txring_dtag); if (error) { @@ -1972,7 +1972,7 @@ bwi_dma_alloc(struct bwi_softc *sc) rx_ring_sz, 1, BUS_SPACE_MAXSIZE_32BIT, - BUS_DMA_ALLOCNOW, + 0, NULL, NULL, &sc->sc_rxring_dtag); if (error) { @@ -2097,7 +2097,7 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base, dma_size, 1, BUS_SPACE_MAXSIZE_32BIT, - BUS_DMA_ALLOCNOW, + 0, NULL, NULL, &st->stats_ring_dtag); if (error) { @@ -2145,7 +2145,7 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base, dma_size, 1, BUS_SPACE_MAXSIZE_32BIT, - BUS_DMA_ALLOCNOW, + 0, NULL, NULL, &st->stats_dtag); if (error) { @@ -2227,7 +2227,7 @@ bwi_dma_mbuf_create(struct bwi_softc *sc) NULL, NULL, MCLBYTES, 1, - BUS_SPACE_MAXSIZE_32BIT, + MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_buf_dtag); From 7e97abb36e04d57d97e41441929e8947fd325b37 Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 27 May 2015 22:27:15 +0000 Subject: [PATCH 21/65] Setup the interrupt handler after bwi_attach(). If IRQ is shared, interrupt may come during bwi_attach(). --- sys/dev/bwi/if_bwi_pci.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sys/dev/bwi/if_bwi_pci.c b/sys/dev/bwi/if_bwi_pci.c index 1977b93a4acc..c2badc504a9b 100644 --- a/sys/dev/bwi/if_bwi_pci.c +++ b/sys/dev/bwi/if_bwi_pci.c @@ -161,12 +161,6 @@ bwi_pci_attach(device_t dev) device_printf(dev, "could not map interrupt\n"); goto bad1; } - if (bus_setup_intr(dev, sc->sc_irq_res, - INTR_TYPE_NET | INTR_MPSAFE, - NULL, bwi_intr, sc, &sc->sc_irq_handle)) { - device_printf(dev, "could not establish interrupt\n"); - goto bad2; - } /* Get more PCI information */ sc->sc_pci_did = pci_get_device(dev); @@ -174,11 +168,17 @@ bwi_pci_attach(device_t dev) sc->sc_pci_subvid = pci_get_subvendor(dev); sc->sc_pci_subdid = pci_get_subdevice(dev); - error = bwi_attach(sc); - if (error == 0) /* success */ - return 0; + if ((error = bwi_attach(sc)) != 0) + goto bad2; + + if (bus_setup_intr(dev, sc->sc_irq_res, + INTR_TYPE_NET | INTR_MPSAFE, + NULL, bwi_intr, sc, &sc->sc_irq_handle)) { + device_printf(dev, "could not establish interrupt\n"); + goto bad2; + } + return (0); - bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); bad2: bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); bad1: From 8f088f6f343e72d7c938ca58dcf7e84c8a087e13 Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 27 May 2015 22:29:19 +0000 Subject: [PATCH 22/65] In bwi_mac_fw_alloc(): - Use device_printf() instead of if_printf(). - Reduce cut and paste. --- sys/dev/bwi/bwimac.c | 50 ++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/sys/dev/bwi/bwimac.c b/sys/dev/bwi/bwimac.c index 849bf022f1d4..21f4333bbfb0 100644 --- a/sys/dev/bwi/bwimac.c +++ b/sys/dev/bwi/bwimac.c @@ -883,7 +883,6 @@ static int bwi_mac_fw_alloc(struct bwi_mac *mac) { struct bwi_softc *sc = mac->mac_sc; - struct ifnet *ifp = sc->sc_ifp; char fwname[64]; int idx; @@ -895,10 +894,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) snprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH, sc->sc_fw_version); mac->mac_stub = firmware_get(fwname); - if (mac->mac_stub == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } + if (mac->mac_stub == NULL) + goto no_firmware; } if (mac->mac_ucode == NULL) { @@ -907,11 +904,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) mac->mac_rev >= 5 ? 5 : mac->mac_rev); mac->mac_ucode = firmware_get(fwname); - if (mac->mac_ucode == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } - + if (mac->mac_ucode == NULL) + goto no_firmware; if (!bwi_fwimage_is_valid(sc, mac->mac_ucode, BWI_FW_T_UCODE)) return EINVAL; } @@ -922,11 +916,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) mac->mac_rev < 5 ? 4 : 5); mac->mac_pcm = firmware_get(fwname); - if (mac->mac_pcm == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } - + if (mac->mac_pcm == NULL) + goto no_firmware; if (!bwi_fwimage_is_valid(sc, mac->mac_pcm, BWI_FW_T_PCM)) return EINVAL; } @@ -938,8 +929,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) { idx = 5; } else { - if_printf(ifp, "no suitible IV for MAC rev %d\n", - mac->mac_rev); + device_printf(sc->sc_dev, + "no suitible IV for MAC rev %d\n", mac->mac_rev); return ENODEV; } @@ -947,10 +938,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) sc->sc_fw_version, idx); mac->mac_iv = firmware_get(fwname); - if (mac->mac_iv == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } + if (mac->mac_iv == NULL) + goto no_firmware; if (!bwi_fwimage_is_valid(sc, mac->mac_iv, BWI_FW_T_IV)) return EINVAL; } @@ -960,12 +949,12 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) if (mac->mac_rev == 2 || mac->mac_rev == 4 || mac->mac_rev >= 11) { /* No extended IV */ - goto back; + return (0); } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) { idx = 5; } else { - if_printf(ifp, "no suitible ExtIV for MAC rev %d\n", - mac->mac_rev); + device_printf(sc->sc_dev, + "no suitible ExtIV for MAC rev %d\n", mac->mac_rev); return ENODEV; } @@ -973,15 +962,16 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) sc->sc_fw_version, idx); mac->mac_iv_ext = firmware_get(fwname); - if (mac->mac_iv_ext == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } + if (mac->mac_iv_ext == NULL) + goto no_firmware; if (!bwi_fwimage_is_valid(sc, mac->mac_iv_ext, BWI_FW_T_IV)) return EINVAL; } -back: - return 0; + return (0); + +no_firmware: + device_printf(sc->sc_dev, "request firmware %s failed\n", fwname); + return (ENOENT); } static void From e347653ba08b12386f2285d9827172ad6eaeefea Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 27 May 2015 22:30:21 +0000 Subject: [PATCH 23/65] To avoid sleeping in firmware_get() with bwi mutex held, call bwi_mac_fw_alloc() at the device attach, not in the interface init. --- sys/dev/bwi/bwimac.c | 7 +------ sys/dev/bwi/bwimac.h | 1 + sys/dev/bwi/if_bwi.c | 4 ++++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/dev/bwi/bwimac.c b/sys/dev/bwi/bwimac.c index 21f4333bbfb0..f39ef44d4174 100644 --- a/sys/dev/bwi/bwimac.c +++ b/sys/dev/bwi/bwimac.c @@ -101,7 +101,6 @@ static void bwi_mac_opmode_init(struct bwi_mac *); static void bwi_mac_hostflags_init(struct bwi_mac *); static void bwi_mac_bss_param_init(struct bwi_mac *); -static int bwi_mac_fw_alloc(struct bwi_mac *); static void bwi_mac_fw_free(struct bwi_mac *); static int bwi_mac_fw_load(struct bwi_mac *); static int bwi_mac_fw_init(struct bwi_mac *); @@ -325,10 +324,6 @@ bwi_mac_init(struct bwi_mac *mac) /* * Load and initialize firmwares */ - error = bwi_mac_fw_alloc(mac); - if (error) - return error; - error = bwi_mac_fw_load(mac); if (error) return error; @@ -879,7 +874,7 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw, /* * XXX Error cleanup */ -static int +int bwi_mac_fw_alloc(struct bwi_mac *mac) { struct bwi_softc *sc = mac->mac_sc; diff --git a/sys/dev/bwi/bwimac.h b/sys/dev/bwi/bwimac.h index 2c5275edfab7..a6d90083c60b 100644 --- a/sys/dev/bwi/bwimac.h +++ b/sys/dev/bwi/bwimac.h @@ -57,6 +57,7 @@ void bwi_mac_init_tpctl_11bg(struct bwi_mac *); void bwi_mac_dummy_xmit(struct bwi_mac *); void bwi_mac_reset_hwkeys(struct bwi_mac *); int bwi_mac_config_ps(struct bwi_mac *); +int bwi_mac_fw_alloc(struct bwi_mac *); uint16_t bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t); uint32_t bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t); diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index 9f66ff45da7f..53fb58faf783 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -446,6 +446,10 @@ bwi_attach(struct bwi_softc *sc) if (error) goto fail; + error = bwi_mac_fw_alloc(mac); + if (error) + goto fail; + ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); if (ifp == NULL) { device_printf(dev, "can not if_alloc()\n"); From e78dd9d8ebd584a44a515ae0711bca71f63243a6 Mon Sep 17 00:00:00 2001 From: pkelsey Date: Thu, 28 May 2015 05:38:07 +0000 Subject: [PATCH 24/65] Add CAP_FCNTL to the lease file capsicum rights, and limit to CAP_FCNTL_GETFL. Without CAP_FCNTL_GETFL, the lease file truncation in rewrite_client_leases() will fail to trim old data when rewriting the file with a lesser amount of data. Reviewed by: pjd, rwatson Approved by: jmallett (mentor) MFC after: 1 week --- sbin/dhclient/dhclient.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 22b21f1da68c..79058133f7b2 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1845,12 +1845,16 @@ rewrite_client_leases(void) leaseFile = fopen(path_dhclient_db, "w"); if (!leaseFile) error("can't create %s: %m", path_dhclient_db); - cap_rights_init(&rights, CAP_FSTAT, CAP_FSYNC, CAP_FTRUNCATE, - CAP_SEEK, CAP_WRITE); + cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC, + CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE); if (cap_rights_limit(fileno(leaseFile), &rights) < 0 && errno != ENOSYS) { error("can't limit lease descriptor: %m"); } + if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 && + errno != ENOSYS) { + error("can't limit lease descriptor fcntls: %m"); + } } else { fflush(leaseFile); rewind(leaseFile); From 3ec4a0eee648e9bc2714ce93a0aba56c963fd79b Mon Sep 17 00:00:00 2001 From: scottl Date: Thu, 28 May 2015 08:00:11 +0000 Subject: [PATCH 25/65] Follow-up r283636 with a fix to the other abuses of BUS_SPACE_MAXSIZE_32BIT. It makes no sense to specify a segment size that's larger than the total amount that you want to allocate. --- sys/dev/bwi/if_bwi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index 53fb58faf783..ad41bc675447 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -1945,7 +1945,7 @@ bwi_dma_alloc(struct bwi_softc *sc) NULL, NULL, tx_ring_sz, 1, - BUS_SPACE_MAXSIZE_32BIT, + tx_ring_sz, 0, NULL, NULL, &sc->sc_txring_dtag); @@ -1975,7 +1975,7 @@ bwi_dma_alloc(struct bwi_softc *sc) NULL, NULL, rx_ring_sz, 1, - BUS_SPACE_MAXSIZE_32BIT, + rx_ring_sz, 0, NULL, NULL, &sc->sc_rxring_dtag); @@ -2100,7 +2100,7 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base, NULL, NULL, dma_size, 1, - BUS_SPACE_MAXSIZE_32BIT, + dma_size, 0, NULL, NULL, &st->stats_ring_dtag); @@ -2148,7 +2148,7 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base, NULL, NULL, dma_size, 1, - BUS_SPACE_MAXSIZE_32BIT, + dma_size, 0, NULL, NULL, &st->stats_dtag); From e79c62ff68fc74d88cb6f479859f6fae9baa5101 Mon Sep 17 00:00:00 2001 From: bz Date: Thu, 28 May 2015 12:33:21 +0000 Subject: [PATCH 26/65] Similarly to other architecture, add the include for cpufunc.h which is needed for pte.h by vmstat to resolve MIPS_CCA_UNCACHED. --- sys/mips/include/pcpu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/mips/include/pcpu.h b/sys/mips/include/pcpu.h index 89b65257cefd..f4be33dd8aa9 100644 --- a/sys/mips/include/pcpu.h +++ b/sys/mips/include/pcpu.h @@ -31,6 +31,7 @@ #ifndef _MACHINE_PCPU_H_ #define _MACHINE_PCPU_H_ +#include #include #define PCPU_MD_COMMON_FIELDS \ From 7fad77ce36457a913d6a03f57f062eb3b1f052b8 Mon Sep 17 00:00:00 2001 From: jhb Date: Thu, 28 May 2015 13:56:19 +0000 Subject: [PATCH 27/65] Tweak the description of when waitpid() doesn't return any status for a non-blocking wait to avoid the word "empty". Requested by: ngie --- tests/sys/kern/ptrace_test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/sys/kern/ptrace_test.c b/tests/sys/kern/ptrace_test.c index 6bd5eebfec38..321dc828545d 100644 --- a/tests/sys/kern/ptrace_test.c +++ b/tests/sys/kern/ptrace_test.c @@ -224,9 +224,9 @@ ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc) } /* - * This wait should return an empty pid. The parent should - * see the child as non-exited until the debugger sees the - * exit. + * This wait should return a pid of 0 to indicate no status to + * report. The parent should see the child as non-exited + * until the debugger sees the exit. */ wpid = waitpid(child, &status, WNOHANG); ATF_REQUIRE(wpid == 0); @@ -357,9 +357,9 @@ ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc) } /* - * This wait should return an empty pid. The parent should - * see the child as non-exited until the debugger sees the - * exit. + * This wait should return a pid of 0 to indicate no status to + * report. The parent should see the child as non-exited + * until the debugger sees the exit. */ wpid = waitpid(child, &status, WNOHANG); ATF_REQUIRE(wpid == 0); From d4fad6a818ac56e5f5bf1e0ef95a8ad458608d74 Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 May 2015 14:24:21 +0000 Subject: [PATCH 28/65] Address some compiler warnings. No functional change. MFC after: 3 days --- sys/netinet/sctp_indata.c | 12 +++++++++--- sys/netinet/sctp_output.c | 3 --- sys/netinet/sctputil.c | 5 ++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index d3b485560305..f477e0cc909b 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -3462,12 +3462,18 @@ sctp_fs_audit(struct sctp_association *asoc) { struct sctp_tmit_chunk *chk; int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0; - int entry_flight, entry_cnt, ret; + int ret; +#ifndef INVARIANTS + int entry_flight, entry_cnt; + +#endif + + ret = 0; +#ifndef INVARIANTS entry_flight = asoc->total_flight; entry_cnt = asoc->total_flight_count; - ret = 0; - +#endif if (asoc->pr_sctp_cnt >= asoc->sent_queue_cnt) return (0); diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index ed3b9ec6818d..524882b2744c 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -11996,9 +11996,6 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, struct uio *uio, int resv_upfront) { - int left; - - left = sp->length; sp->data = m_uiotombuf(uio, M_WAITOK, sp->length, resv_upfront, 0); if (sp->data == NULL) { diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index a30a9425a6a4..f73e14db44b5 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1449,7 +1449,7 @@ sctp_timeout_handler(void *t) struct socket *so; #endif - int did_output, type; + int did_output; tmr = (struct sctp_timer *)t; inp = (struct sctp_inpcb *)tmr->ep; @@ -1488,7 +1488,6 @@ sctp_timeout_handler(void *t) } /* if this is an iterator timeout, get the struct and clear inp */ tmr->stopped_from = 0xa003; - type = tmr->type; if (inp) { SCTP_INP_INCR_REF(inp); if ((inp->sctp_socket == NULL) && @@ -1873,7 +1872,7 @@ out_decr: } out_no_decr: SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n", - type); + tmr->type); CURVNET_RESTORE(); } From a82f33e60c7dfa71ecd32bfbaf1a5f930fcecb96 Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 May 2015 16:00:23 +0000 Subject: [PATCH 29/65] Fix and cleanup the debug information. This has no user-visible changes. Thanks to Irene Ruengeler for proving a patch. MFC after: 3 days --- sys/netinet/sctp_asconf.c | 10 ++-- sys/netinet/sctp_cc_functions.c | 9 ++-- sys/netinet/sctp_constants.h | 27 ++++++----- sys/netinet/sctp_indata.c | 62 +++++++++++++----------- sys/netinet/sctp_input.c | 86 +++++++++++++++++++++------------ sys/netinet/sctp_output.c | 14 ++++-- sys/netinet/sctp_pcb.c | 3 +- sys/netinet/sctp_timer.c | 8 +-- sys/netinet/sctp_usrreq.c | 45 +++++++++++------ sys/netinet/sctputil.c | 8 +-- sys/netinet6/sctp6_usrreq.c | 6 ++- 11 files changed, 171 insertions(+), 107 deletions(-) diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index 456990019c2f..10bb0a26f471 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -555,7 +555,9 @@ sctp_process_asconf_set_primary(struct sockaddr *src, (stcb->asoc.primary_destination->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) { - sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7); + sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1); if (sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_FASTHANDOFF)) { sctp_assoc_immediate_retrans(stcb, @@ -991,7 +993,7 @@ sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet) SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa); sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary, - SCTP_FROM_SCTP_TIMER + SCTP_LOC_8); + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3); stcb->asoc.num_send_timers_up--; if (stcb->asoc.num_send_timers_up < 0) { stcb->asoc.num_send_timers_up = 0; @@ -1030,7 +1032,7 @@ sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net) SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO); sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_TIMER + SCTP_LOC_5); + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_4); stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); net->error_count = 0; TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { @@ -1684,7 +1686,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset, if (serial_num == asoc->asconf_seq_out - 1) { /* stop our timer */ sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3); + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_5); } /* process the ASCONF-ACK contents */ ack_length = ntohs(cp->ch.chunk_length) - diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c index 17a897b93d45..d616d1949496 100644 --- a/sys/netinet/sctp_cc_functions.c +++ b/sys/netinet/sctp_cc_functions.c @@ -226,7 +226,8 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, - stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32); + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_1); sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); } @@ -1732,7 +1733,8 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb, } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, - stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32); + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_2); sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); } @@ -2264,7 +2266,8 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb, } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, - stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32); + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_3); sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); } diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index de451651a6a6..d90bd2502ad4 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -765,18 +765,19 @@ __FBSDID("$FreeBSD$"); */ /* File defines */ -#define SCTP_FROM_SCTP_INPUT 0x10000000 -#define SCTP_FROM_SCTP_PCB 0x20000000 -#define SCTP_FROM_SCTP_INDATA 0x30000000 -#define SCTP_FROM_SCTP_TIMER 0x40000000 -#define SCTP_FROM_SCTP_USRREQ 0x50000000 -#define SCTP_FROM_SCTPUTIL 0x60000000 -#define SCTP_FROM_SCTP6_USRREQ 0x70000000 -#define SCTP_FROM_SCTP_ASCONF 0x80000000 -#define SCTP_FROM_SCTP_OUTPUT 0x90000000 -#define SCTP_FROM_SCTP_PEELOFF 0xa0000000 -#define SCTP_FROM_SCTP_PANDA 0xb0000000 -#define SCTP_FROM_SCTP_SYSCTL 0xc0000000 +#define SCTP_FROM_SCTP_INPUT 0x10000000 +#define SCTP_FROM_SCTP_PCB 0x20000000 +#define SCTP_FROM_SCTP_INDATA 0x30000000 +#define SCTP_FROM_SCTP_TIMER 0x40000000 +#define SCTP_FROM_SCTP_USRREQ 0x50000000 +#define SCTP_FROM_SCTPUTIL 0x60000000 +#define SCTP_FROM_SCTP6_USRREQ 0x70000000 +#define SCTP_FROM_SCTP_ASCONF 0x80000000 +#define SCTP_FROM_SCTP_OUTPUT 0x90000000 +#define SCTP_FROM_SCTP_PEELOFF 0xa0000000 +#define SCTP_FROM_SCTP_PANDA 0xb0000000 +#define SCTP_FROM_SCTP_SYSCTL 0xc0000000 +#define SCTP_FROM_SCTP_CC_FUNCTIONS 0xd0000000 /* Location ID's */ #define SCTP_LOC_1 0x00000001 @@ -812,6 +813,8 @@ __FBSDID("$FreeBSD$"); #define SCTP_LOC_31 0x0000001f #define SCTP_LOC_32 0x00000020 #define SCTP_LOC_33 0x00000021 +#define SCTP_LOC_34 0x00000022 +#define SCTP_LOC_35 0x00000023 /* Free assoc codes */ diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index f477e0cc909b..50a662864a02 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -1034,7 +1034,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.TSN_seq, (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_7; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_8; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1056,7 +1056,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_8; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_9; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1073,7 +1073,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_9; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_10; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1100,7 +1100,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_10; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_11; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1123,7 +1123,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_11; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_12; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1144,7 +1144,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_12; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_13; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1162,7 +1162,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.TSN_seq, (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_12; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_14; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1184,7 +1184,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_13; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1476,7 +1476,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, asoc->strmin[strmno].last_sequence_delivered, tsn, strmno, strmseq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_14; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return (0); @@ -1713,7 +1713,7 @@ failed_pdapi_express_del: snprintf(msg, sizeof(msg), "Reas. queue emtpy, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", tsn, strmno, strmseq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_17; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; if (last_chunk) { @@ -1732,7 +1732,7 @@ failed_pdapi_express_del: snprintf(msg, sizeof(msg), "PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", tsn, strmno, strmseq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_18; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; if (last_chunk) { @@ -1761,7 +1761,7 @@ failed_pdapi_express_del: snprintf(msg, sizeof(msg), "No PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", tsn, strmno, strmseq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_17; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_19; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; if (last_chunk) { @@ -2159,7 +2159,8 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap) */ if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18); + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_20); } sctp_send_shutdown(stcb, ((stcb->asoc.alternate) ? stcb->asoc.alternate : stcb->asoc.primary_destination)); @@ -2382,7 +2383,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, snprintf(msg, sizeof(msg), "DATA chunk of length %d", chk_length); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_19; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_21; sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, mflowtype, mflowid, @@ -2397,7 +2398,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, struct mbuf *op_err; op_err = sctp_generate_no_user_data_cause(ch->dp.tsn); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_19; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_22; sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, mflowtype, mflowid, @@ -3628,7 +3629,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal than TSN %8.8x", cumack, send_s); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_23; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } @@ -3824,7 +3825,9 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, } if (net->dest_state & SCTP_ADDR_PF) { net->dest_state &= ~SCTP_ADDR_PF; - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_24); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net); /* Done with this net */ @@ -3910,7 +3913,7 @@ again: } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); + SCTP_FROM_SCTP_INDATA + SCTP_LOC_25); } } } @@ -3984,7 +3987,7 @@ again: *abort_now = 1; /* XXX */ op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_26; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); } else { struct sctp_nets *netp; @@ -4197,7 +4200,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal than TSN %8.8x", cum_ack, send_s); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_27; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } @@ -4229,7 +4232,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, /* stop any timers */ TAILQ_FOREACH(net, &asoc->nets, sctp_next) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, - stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26); + stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_28); net->partial_bytes_acked = 0; net->flight_size = 0; } @@ -4434,14 +4437,14 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, if (net->new_pseudo_cumack) sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_INDATA + SCTP_LOC_27); + SCTP_FROM_SCTP_INDATA + SCTP_LOC_29); } } else { if (accum_moved) { TAILQ_FOREACH(net, &asoc->nets, sctp_next) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, - stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_28); + stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30); } } } @@ -4614,7 +4617,9 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, } if (net->dest_state & SCTP_ADDR_PF) { net->dest_state &= ~SCTP_ADDR_PF; - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_31); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net); /* Done with this net */ @@ -4637,7 +4642,8 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, TAILQ_FOREACH(net, &asoc->nets, sctp_next) { /* stop all timers */ sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, - stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30); + stcb, net, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_32); net->flight_size = 0; net->partial_bytes_acked = 0; } @@ -4693,7 +4699,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, *abort_now = 1; /* XXX */ op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_33; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } else { @@ -4845,7 +4851,7 @@ again: } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); + SCTP_FROM_SCTP_INDATA + SCTP_LOC_34); } } } @@ -5135,7 +5141,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, "New cum ack %8.8x too high, highest TSN %8.8x", new_cum_tsn, asoc->highest_tsn_inside_map); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_33; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_35; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 048dfd3d094c..89047cbd60c1 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -513,7 +513,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, * primary. */ sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, - asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4); + asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); /* calculate the RTO */ net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, @@ -633,7 +633,8 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, } sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, + r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); } old_error_counter = r_net->error_count; @@ -654,7 +655,8 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net); } if (old_error_counter > 0) { - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, + stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_5); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); } if (r_net == stcb->asoc.primary_destination) { @@ -673,7 +675,9 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_PRIM_DELETED)) { - sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7); + sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); if (sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_FASTHANDOFF)) { sctp_assoc_immediate_retrans(stcb, @@ -795,7 +799,8 @@ sctp_handle_abort(struct sctp_abort_chunk *abort, error = 0; } /* stop any receive timers */ - sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); + sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_7); /* notify user of the abort and clean up... */ sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED); /* free the tcb */ @@ -817,7 +822,7 @@ sctp_handle_abort(struct sctp_abort_chunk *abort, #endif stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, - SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); + SCTP_FROM_SCTP_INPUT + SCTP_LOC_8); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -932,7 +937,8 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, * stop the shutdown timer, since we WILL move to * SHUTDOWN-ACK-SENT. */ - sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_8); + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, + net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9); } /* Now is there unsent data on a stream somewhere? */ some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED); @@ -1025,7 +1031,8 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, } #endif /* stop the timer */ - sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9); + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_10); /* send SHUTDOWN-COMPLETE */ sctp_send_shutdown_complete(stcb, net, 0); /* notify upper layer protocol */ @@ -1046,7 +1053,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, - SCTP_FROM_SCTP_INPUT + SCTP_LOC_10); + SCTP_FROM_SCTP_INPUT + SCTP_LOC_11); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -1206,7 +1213,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch, atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, - SCTP_FROM_SCTP_INPUT + SCTP_LOC_11); + SCTP_FROM_SCTP_INPUT + SCTP_LOC_12); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -1558,9 +1565,12 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, return (NULL); } /* we have already processed the INIT so no problem */ - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, - net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_12); - sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_13); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, + stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_13); + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, + stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); /* update current state */ if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) SCTP_STAT_INCR_COUNTER32(sctps_activeestab); @@ -1720,7 +1730,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, } if (how_indx < sizeof(asoc->cookie_how)) asoc->cookie_how[how_indx] = 8; - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); sctp_stop_all_cookie_timers(stcb); /* * since we did not send a HB make sure we don't double @@ -1865,8 +1876,10 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, /* temp code */ if (how_indx < sizeof(asoc->cookie_how)) asoc->cookie_how[how_indx] = 12; - sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_17); /* notify upper layer */ *notification = SCTP_NOTIFY_ASSOC_RESTART; @@ -2134,7 +2147,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_TCB_LOCK(stcb); #endif (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, - SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); + SCTP_FROM_SCTP_INPUT + SCTP_LOC_18); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2165,7 +2178,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_19); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2182,7 +2196,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_20); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2211,7 +2226,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_21); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2271,7 +2287,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_22); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2741,7 +2758,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, SCTP_TCB_LOCK((*stcb)); atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20); + (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_23); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(pcb_so, 1); #endif @@ -3173,7 +3191,8 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE } #endif /* stop the timer */ - sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22); + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_24); SCTP_STAT_INCR_COUNTER32(sctps_shutdown); /* free the TCB */ SCTPDBG(SCTP_DEBUG_INPUT2, @@ -3186,7 +3205,8 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23); + (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_25); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -3294,7 +3314,8 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, /* restart the timer */ sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, - stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_24); + stcb, tp1->whoTo, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_26); sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, tp1->whoTo); @@ -3362,7 +3383,8 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, * this, otherwise we let the timer fire. */ sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, - stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_25); + stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); } break; @@ -3539,7 +3561,8 @@ sctp_clean_up_stream_reset(struct sctp_tcb *stcb) } asoc = &stcb->asoc; - sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_26); + sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, + chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_28); TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next); @@ -4783,7 +4806,8 @@ process_control_chunks: SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_29); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -5203,7 +5227,8 @@ process_control_chunks: SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_30); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -5381,7 +5406,8 @@ process_control_chunks: SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_31); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 524882b2744c..ef263a8c583c 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -8327,7 +8327,8 @@ again_one_more_time: /* 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); + inp, stcb, net, + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_1); } } ctl_cnt++; @@ -9780,7 +9781,7 @@ one_chunk_around: * t3-expiring. */ sctp_timer_stop(SCTP_TIMER_TYPE_SEND, inp, stcb, net, - SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_4); + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_2); sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); } } @@ -10387,7 +10388,8 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked /* No memory so we drop the idea, and set a timer */ if (stcb->asoc.delayed_ack) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_5); + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_3); sctp_timer_start(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL); } else { @@ -10455,7 +10457,8 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked /* sa_ignore NO_NULL_CHK */ if (stcb->asoc.delayed_ack) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_6); + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_4); sctp_timer_start(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL); } else { @@ -12424,7 +12427,8 @@ sctp_lower_sosend(struct socket *so, if (control) { if (sctp_process_cmsgs_for_init(stcb, control, &error)) { - sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_7); + sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_5); hold_tcblock = 0; stcb = NULL; goto out_unlocked; diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 6edf33afc986..f6e9e326f8d3 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -3544,7 +3544,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } - if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_8) == 0) { + if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE, + SCTP_FROM_SCTP_PCB + SCTP_LOC_8) == 0) { cnt++; } } diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index d8422b901747..257d18845b23 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -110,7 +110,9 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, net->dest_state |= SCTP_ADDR_PF; net->last_active = sctp_get_tick_count(); sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_TIMER + SCTP_LOC_1); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -153,7 +155,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, "Association error counter exceeded"); - inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1; + inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_2; sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (1); } @@ -1046,7 +1048,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp, op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, "Cookie timer expired, but no cookie"); - inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_4; + inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_3; sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); } else { #ifdef INVARIANTS diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index d2529695ea33..50059101712d 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -288,7 +288,8 @@ sctp_notify(struct sctp_inpcb *inp, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */ @@ -777,7 +778,8 @@ sctp_disconnect(struct socket *so) (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3); /* No unlock tcb assoc is gone */ return (0); } @@ -862,7 +864,8 @@ sctp_disconnect(struct socket *so) SCTP_STAT_DECR_GAUGE32(sctps_currestab); } SCTP_INP_RUNLOCK(inp); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5); return (0); } else { sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); @@ -1562,7 +1565,8 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error); /* Fill in the return id */ if (error) { - (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6); + (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7); goto out_now; } a_id = (sctp_assoc_t *) optval; @@ -4785,7 +4789,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination, - SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8); sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED); } else { /* @@ -5203,7 +5207,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) && !(net->dest_state & SCTP_ADDR_NOHB)) { sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9); } net->dest_state |= SCTP_ADDR_NOHB; } @@ -5227,7 +5231,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) { if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11); } net->dest_state |= SCTP_ADDR_NO_PMTUD; net->mtu = paddrp->spp_pathmtu + ovh; @@ -5251,7 +5255,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (net->error_count > net->pf_threshold)) { net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -5294,7 +5300,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (net->error_count > net->pf_threshold)) { net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_13); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -5329,7 +5337,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, net->dest_state &= ~SCTP_ADDR_NOHB; } sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_14); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); } sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT); @@ -5339,7 +5347,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, if (!(net->dest_state & SCTP_ADDR_NOHB)) { net->dest_state |= SCTP_ADDR_NOHB; if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + inp, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_15); } } } @@ -5349,7 +5359,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16); } net->dest_state |= SCTP_ADDR_NO_PMTUD; net->mtu = paddrp->spp_pathmtu + ovh; @@ -6199,7 +6209,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (net->error_count <= net->failure_threshold)) { net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_17); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -6228,7 +6240,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (net->error_count <= net->failure_threshold)) { net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_18); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -7127,7 +7141,8 @@ sctp_accept(struct socket *so, struct sockaddr **addr) } if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { SCTP_TCB_LOCK(stcb); - sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7); + sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19); } return (0); } diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index f73e14db44b5..a78bcf690ffe 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -6322,14 +6322,14 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, (sin->sin_addr.s_addr == INADDR_BROADCAST) || IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_7); *error = EINVAL; goto out_now; } if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { /* assoc gone no un-lock */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_8); *error = ENOBUFS; goto out_now; } @@ -6343,14 +6343,14 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_9); *error = EINVAL; goto out_now; } if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { /* assoc gone no un-lock */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_10); *error = ENOBUFS; goto out_now; } diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index f2b2322ee4bc..54c65b61b9e6 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -211,7 +211,8 @@ sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6, */ nxtsz = ntohl(icmp6->icmp6_mtu); /* Stop any PMTU timer */ - sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL, SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_1); + sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL, + SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_1); /* Adjust destination size limit */ if (net->mtu > nxtsz) { @@ -333,7 +334,8 @@ sctp6_notify(struct sctp_inpcb *inp, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_2); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */ From 8a477638bd5fc6f57f630e19dd2a8f1458f45526 Mon Sep 17 00:00:00 2001 From: pkelsey Date: Thu, 28 May 2015 16:18:41 +0000 Subject: [PATCH 30/65] Provide an unambiguous description of the potential hazard in calling pthread_setspecific(3) from a key destructor. Reviewed by: jhb Approved by: jmallett (mentor) MFC after: 3 days --- share/man/man3/pthread_setspecific.3 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/share/man/man3/pthread_setspecific.3 b/share/man/man3/pthread_setspecific.3 index 1ea3002d43a0..3153c991f90b 100644 --- a/share/man/man3/pthread_setspecific.3 +++ b/share/man/man3/pthread_setspecific.3 @@ -67,7 +67,10 @@ is undefined. The .Fn pthread_setspecific function may be called from a thread-specific data destructor function, -however this may result in lost storage or infinite loops. +however this may result in lost storage or infinite loops if doing so +causes non-NULL key values to remain after +.Bq PTHREAD_DESTRUCTOR_ITERATIONS +iterations of destructor calls have been made. .Sh RETURN VALUES If successful, the .Fn pthread_setspecific From 67b3bbe09c36f09dda55d0e010c9d1bf12cc6073 Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 May 2015 16:39:22 +0000 Subject: [PATCH 31/65] Some more debug info cleanup. MFC after: 3 days --- sys/netinet/sctputil.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index a78bcf690ffe..24110dd1ce89 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1808,7 +1808,8 @@ sctp_timeout_handler(void *t) SCTP_STAT_INCR(sctps_timoassockill); /* Can we free it yet? */ SCTP_INP_DECR_REF(inp); - sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_1); + sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, + SCTP_FROM_SCTPUTIL + SCTP_LOC_1); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) so = SCTP_INP_SO(inp); atomic_add_int(&stcb->asoc.refcnt, 1); @@ -1817,7 +1818,8 @@ sctp_timeout_handler(void *t) SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_2); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_2); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -1837,7 +1839,8 @@ sctp_timeout_handler(void *t) * killer */ SCTP_INP_DECR_REF(inp); - sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, + SCTP_FROM_SCTPUTIL + SCTP_LOC_3); sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, SCTP_CALLED_FROM_INPKILL_TIMER); inp = NULL; @@ -3909,7 +3912,8 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_4); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_4); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -4033,7 +4037,8 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, atomic_subtract_int(&stcb->asoc.refcnt, 1); } #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_5); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_5); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) if (!so_locked) { SCTP_SOCKET_UNLOCK(so, 1); @@ -5164,7 +5169,8 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t * freed_so_far, int hold_rlock, sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED); /* make sure no timer is running */ - sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_6); + sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTPUTIL + SCTP_LOC_6); SCTP_TCB_UNLOCK(stcb); } else { /* Update how much we have pending */ @@ -6322,14 +6328,16 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, (sin->sin_addr.s_addr == INADDR_BROADCAST) || IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_7); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_7); *error = EINVAL; goto out_now; } if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { /* assoc gone no un-lock */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_8); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_8); *error = ENOBUFS; goto out_now; } @@ -6343,14 +6351,16 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_9); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_9); *error = EINVAL; goto out_now; } if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { /* assoc gone no un-lock */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_10); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_10); *error = ENOBUFS; goto out_now; } From 3f2b4fc770fb5b735b286cf251b967cfa4afdf12 Mon Sep 17 00:00:00 2001 From: neel Date: Thu, 28 May 2015 17:37:01 +0000 Subject: [PATCH 32/65] Fix non-deterministic delays when accessing a vcpu that was in "running" or "sleeping" state. This is done by forcing the vcpu to transition to "idle" by returning to userspace with an exit code of VM_EXITCODE_REQIDLE. MFC after: 2 weeks --- sys/amd64/include/vmm.h | 26 +++++++-- sys/amd64/vmm/amd/svm.c | 12 +++- sys/amd64/vmm/intel/vmx.c | 12 +++- sys/amd64/vmm/vmm.c | 114 ++++++++++++++++++++++++++++++-------- sys/amd64/vmm/vmm_stat.c | 1 + sys/amd64/vmm/vmm_stat.h | 1 + usr.sbin/bhyve/bhyverun.c | 14 ++++- 7 files changed, 145 insertions(+), 35 deletions(-) diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index d3798bcab2e3..1a4e5ab485c8 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -120,13 +120,18 @@ struct vm_object; struct vm_guest_paging; struct pmap; +struct vm_eventinfo { + void *rptr; /* rendezvous cookie */ + int *sptr; /* suspend cookie */ + int *iptr; /* reqidle cookie */ +}; + typedef int (*vmm_init_func_t)(int ipinum); typedef int (*vmm_cleanup_func_t)(void); typedef void (*vmm_resume_func_t)(void); typedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap); typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip, - struct pmap *pmap, void *rendezvous_cookie, - void *suspend_cookie); + struct pmap *pmap, struct vm_eventinfo *info); typedef void (*vmi_cleanup_func_t)(void *vmi); typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num, uint64_t *retval); @@ -208,6 +213,7 @@ struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid); void vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip); void vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip); void vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip); +void vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip); #ifdef _SYS__CPUSET_H_ /* @@ -232,17 +238,24 @@ cpuset_t vm_suspended_cpus(struct vm *vm); #endif /* _SYS__CPUSET_H_ */ static __inline int -vcpu_rendezvous_pending(void *rendezvous_cookie) +vcpu_rendezvous_pending(struct vm_eventinfo *info) { - return (*(uintptr_t *)rendezvous_cookie != 0); + return (*((uintptr_t *)(info->rptr)) != 0); } static __inline int -vcpu_suspended(void *suspend_cookie) +vcpu_suspended(struct vm_eventinfo *info) { - return (*(int *)suspend_cookie); + return (*info->sptr); +} + +static __inline int +vcpu_reqidle(struct vm_eventinfo *info) +{ + + return (*info->iptr); } /* @@ -506,6 +519,7 @@ enum vm_exitcode { VM_EXITCODE_MONITOR, VM_EXITCODE_MWAIT, VM_EXITCODE_SVM, + VM_EXITCODE_REQIDLE, VM_EXITCODE_MAX }; diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c index 20e8f765cb9a..53b12b72c93d 100644 --- a/sys/amd64/vmm/amd/svm.c +++ b/sys/amd64/vmm/amd/svm.c @@ -1900,7 +1900,7 @@ enable_gintr(void) */ static int svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap, - void *rend_cookie, void *suspended_cookie) + struct vm_eventinfo *evinfo) { struct svm_regctx *gctx; struct svm_softc *svm_sc; @@ -1975,18 +1975,24 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap, */ disable_gintr(); - if (vcpu_suspended(suspended_cookie)) { + if (vcpu_suspended(evinfo)) { enable_gintr(); vm_exit_suspended(vm, vcpu, state->rip); break; } - if (vcpu_rendezvous_pending(rend_cookie)) { + if (vcpu_rendezvous_pending(evinfo)) { enable_gintr(); vm_exit_rendezvous(vm, vcpu, state->rip); break; } + if (vcpu_reqidle(evinfo)) { + enable_gintr(); + vm_exit_reqidle(vm, vcpu, state->rip); + break; + } + /* We are asked to give the cpu by scheduler. */ if (vcpu_should_yield(vm, vcpu)) { enable_gintr(); diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index 4c3f20d6df17..7ee50d4fb30e 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -2554,7 +2554,7 @@ vmx_exit_handle_nmi(struct vmx *vmx, int vcpuid, struct vm_exit *vmexit) static int vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap, - void *rendezvous_cookie, void *suspend_cookie) + struct vm_eventinfo *evinfo) { int rc, handled, launched; struct vmx *vmx; @@ -2623,18 +2623,24 @@ vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap, * vmx_inject_interrupts() can suspend the vcpu due to a * triple fault. */ - if (vcpu_suspended(suspend_cookie)) { + if (vcpu_suspended(evinfo)) { enable_intr(); vm_exit_suspended(vmx->vm, vcpu, rip); break; } - if (vcpu_rendezvous_pending(rendezvous_cookie)) { + if (vcpu_rendezvous_pending(evinfo)) { enable_intr(); vm_exit_rendezvous(vmx->vm, vcpu, rip); break; } + if (vcpu_reqidle(evinfo)) { + enable_intr(); + vm_exit_reqidle(vmx->vm, vcpu, rip); + break; + } + if (vcpu_should_yield(vm, vcpu)) { enable_intr(); vm_exit_astpending(vmx->vm, vcpu, rip); diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 26712955e41e..2c37a1ac2c69 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -95,6 +95,7 @@ struct vcpu { struct mtx mtx; /* (o) protects 'state' and 'hostcpu' */ enum vcpu_state state; /* (o) vcpu state */ int hostcpu; /* (o) vcpu's host cpu */ + int reqidle; /* (i) request vcpu to idle */ struct vlapic *vlapic; /* (i) APIC device model */ enum x2apic_state x2apic_state; /* (i) APIC mode */ uint64_t exitintinfo; /* (i) events pending at VM exit */ @@ -164,8 +165,8 @@ static struct vmm_ops *ops; #define VMM_RESUME() (ops != NULL ? (*ops->resume)() : 0) #define VMINIT(vm, pmap) (ops != NULL ? (*ops->vminit)(vm, pmap): NULL) -#define VMRUN(vmi, vcpu, rip, pmap, rptr, sptr) \ - (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, pmap, rptr, sptr) : ENXIO) +#define VMRUN(vmi, vcpu, rip, pmap, evinfo) \ + (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, pmap, evinfo) : ENXIO) #define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL) #define VMSPACE_ALLOC(min, max) \ (ops != NULL ? (*ops->vmspace_alloc)(min, max) : NULL) @@ -221,6 +222,28 @@ TUNABLE_INT("hw.vmm.force_iommu", &vmm_force_iommu); SYSCTL_INT(_hw_vmm, OID_AUTO, force_iommu, CTLFLAG_RDTUN, &vmm_force_iommu, 0, "Force use of I/O MMU even if no passthrough devices were found."); +static void vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr); + +#ifdef KTR +static const char * +vcpu_state2str(enum vcpu_state state) +{ + + switch (state) { + case VCPU_IDLE: + return ("idle"); + case VCPU_FROZEN: + return ("frozen"); + case VCPU_RUNNING: + return ("running"); + case VCPU_SLEEPING: + return ("sleeping"); + default: + return ("unknown"); + } +} +#endif + static void vcpu_cleanup(struct vm *vm, int i, bool destroy) { @@ -255,6 +278,7 @@ vcpu_init(struct vm *vm, int vcpu_id, bool create) vcpu->vlapic = VLAPIC_INIT(vm->cookie, vcpu_id); vm_set_x2apic_state(vm, vcpu_id, X2APIC_DISABLED); + vcpu->reqidle = 0; vcpu->exitintinfo = 0; vcpu->nmi_pending = 0; vcpu->extint_pending = 0; @@ -980,11 +1004,13 @@ save_guest_fpustate(struct vcpu *vcpu) static VMM_STAT(VCPU_IDLE_TICKS, "number of ticks vcpu was idle"); static int -vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate, +vcpu_set_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate, bool from_idle) { + struct vcpu *vcpu; int error; + vcpu = &vm->vcpu[vcpuid]; vcpu_assert_locked(vcpu); /* @@ -993,8 +1019,13 @@ vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate, * ioctl() operating on a vcpu at any point. */ if (from_idle) { - while (vcpu->state != VCPU_IDLE) + while (vcpu->state != VCPU_IDLE) { + vcpu->reqidle = 1; + vcpu_notify_event_locked(vcpu, false); + VCPU_CTR1(vm, vcpuid, "vcpu state change from %s to " + "idle requested", vcpu_state2str(vcpu->state)); msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz); + } } else { KASSERT(vcpu->state != VCPU_IDLE, ("invalid transition from " "vcpu idle state")); @@ -1031,6 +1062,9 @@ vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate, if (error) return (EBUSY); + VCPU_CTR2(vm, vcpuid, "vcpu state changed from %s to %s", + vcpu_state2str(vcpu->state), vcpu_state2str(newstate)); + vcpu->state = newstate; if (newstate == VCPU_RUNNING) vcpu->hostcpu = curcpu; @@ -1053,11 +1087,11 @@ vcpu_require_state(struct vm *vm, int vcpuid, enum vcpu_state newstate) } static void -vcpu_require_state_locked(struct vcpu *vcpu, enum vcpu_state newstate) +vcpu_require_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate) { int error; - if ((error = vcpu_set_state_locked(vcpu, newstate, false)) != 0) + if ((error = vcpu_set_state_locked(vm, vcpuid, newstate, false)) != 0) panic("Error %d setting state to %d", error, newstate); } @@ -1145,7 +1179,7 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu) * vcpu returned from VMRUN() and before it acquired the * vcpu lock above. */ - if (vm->rendezvous_func != NULL || vm->suspend) + if (vm->rendezvous_func != NULL || vm->suspend || vcpu->reqidle) break; if (vm_nmi_pending(vm, vcpuid)) break; @@ -1182,13 +1216,13 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu) } t = ticks; - vcpu_require_state_locked(vcpu, VCPU_SLEEPING); + vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING); /* * XXX msleep_spin() cannot be interrupted by signals so * wake up periodically to check pending signals. */ msleep_spin(vcpu, &vcpu->mtx, wmesg, hz); - vcpu_require_state_locked(vcpu, VCPU_FROZEN); + vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN); vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t); } @@ -1350,9 +1384,9 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu) if (vm->rendezvous_func == NULL) { VCPU_CTR0(vm, vcpuid, "Sleeping during suspend"); - vcpu_require_state_locked(vcpu, VCPU_SLEEPING); + vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING); msleep_spin(vcpu, &vcpu->mtx, "vmsusp", hz); - vcpu_require_state_locked(vcpu, VCPU_FROZEN); + vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN); } else { VCPU_CTR0(vm, vcpuid, "Rendezvous during suspend"); vcpu_unlock(vcpu); @@ -1375,6 +1409,19 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu) return (0); } +static int +vm_handle_reqidle(struct vm *vm, int vcpuid, bool *retu) +{ + struct vcpu *vcpu = &vm->vcpu[vcpuid]; + + vcpu_lock(vcpu); + KASSERT(vcpu->reqidle, ("invalid vcpu reqidle %d", vcpu->reqidle)); + vcpu->reqidle = 0; + vcpu_unlock(vcpu); + *retu = true; + return (0); +} + int vm_suspend(struct vm *vm, enum vm_suspend_how how) { @@ -1431,6 +1478,18 @@ vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip) vmm_stat_incr(vm, vcpuid, VMEXIT_RENDEZVOUS, 1); } +void +vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip) +{ + struct vm_exit *vmexit; + + vmexit = vm_exitinfo(vm, vcpuid); + vmexit->rip = rip; + vmexit->inst_length = 0; + vmexit->exitcode = VM_EXITCODE_REQIDLE; + vmm_stat_incr(vm, vcpuid, VMEXIT_REQIDLE, 1); +} + void vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip) { @@ -1446,6 +1505,7 @@ vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip) int vm_run(struct vm *vm, struct vm_run *vmrun) { + struct vm_eventinfo evinfo; int error, vcpuid; struct vcpu *vcpu; struct pcb *pcb; @@ -1453,7 +1513,6 @@ vm_run(struct vm *vm, struct vm_run *vmrun) struct vm_exit *vme; bool retu, intr_disabled; pmap_t pmap; - void *rptr, *sptr; vcpuid = vmrun->cpuid; @@ -1466,11 +1525,12 @@ vm_run(struct vm *vm, struct vm_run *vmrun) if (CPU_ISSET(vcpuid, &vm->suspended_cpus)) return (EINVAL); - rptr = &vm->rendezvous_func; - sptr = &vm->suspend; pmap = vmspace_pmap(vm->vmspace); vcpu = &vm->vcpu[vcpuid]; vme = &vcpu->exitinfo; + evinfo.rptr = &vm->rendezvous_func; + evinfo.sptr = &vm->suspend; + evinfo.iptr = &vcpu->reqidle; restart: critical_enter(); @@ -1485,7 +1545,7 @@ restart: restore_guest_fpustate(vcpu); vcpu_require_state(vm, vcpuid, VCPU_RUNNING); - error = VMRUN(vm->cookie, vcpuid, vcpu->nextrip, pmap, rptr, sptr); + error = VMRUN(vm->cookie, vcpuid, vcpu->nextrip, pmap, &evinfo); vcpu_require_state(vm, vcpuid, VCPU_FROZEN); save_guest_fpustate(vcpu); @@ -1498,6 +1558,9 @@ restart: retu = false; vcpu->nextrip = vme->rip + vme->inst_length; switch (vme->exitcode) { + case VM_EXITCODE_REQIDLE: + error = vm_handle_reqidle(vm, vcpuid, &retu); + break; case VM_EXITCODE_SUSPENDED: error = vm_handle_suspend(vm, vcpuid, &retu); break; @@ -1536,6 +1599,8 @@ restart: if (error == 0 && retu == false) goto restart; + VCPU_CTR2(vm, vcpuid, "retu %d/%d", error, vme->exitcode); + /* copy the exit information */ bcopy(vme, &vmrun->vm_exit, sizeof(struct vm_exit)); return (error); @@ -2072,7 +2137,7 @@ vcpu_set_state(struct vm *vm, int vcpuid, enum vcpu_state newstate, vcpu = &vm->vcpu[vcpuid]; vcpu_lock(vcpu); - error = vcpu_set_state_locked(vcpu, newstate, from_idle); + error = vcpu_set_state_locked(vm, vcpuid, newstate, from_idle); vcpu_unlock(vcpu); return (error); @@ -2168,15 +2233,11 @@ vm_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state) * - If the vcpu is running on a different host_cpu then an IPI will be directed * to the host_cpu to cause the vcpu to trap into the hypervisor. */ -void -vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr) +static void +vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr) { int hostcpu; - struct vcpu *vcpu; - vcpu = &vm->vcpu[vcpuid]; - - vcpu_lock(vcpu); hostcpu = vcpu->hostcpu; if (vcpu->state == VCPU_RUNNING) { KASSERT(hostcpu != NOCPU, ("vcpu running on invalid hostcpu")); @@ -2201,6 +2262,15 @@ vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr) if (vcpu->state == VCPU_SLEEPING) wakeup_one(vcpu); } +} + +void +vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr) +{ + struct vcpu *vcpu = &vm->vcpu[vcpuid]; + + vcpu_lock(vcpu); + vcpu_notify_event_locked(vcpu, lapic_intr); vcpu_unlock(vcpu); } diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c index 4ae5fb9132cc..7e2f64d1fe1f 100644 --- a/sys/amd64/vmm/vmm_stat.c +++ b/sys/amd64/vmm/vmm_stat.c @@ -164,6 +164,7 @@ VMM_STAT(VMEXIT_NESTED_FAULT, "vm exits due to nested page fault"); VMM_STAT(VMEXIT_INST_EMUL, "vm exits for instruction emulation"); VMM_STAT(VMEXIT_UNKNOWN, "number of vm exits for unknown reason"); VMM_STAT(VMEXIT_ASTPENDING, "number of times astpending at exit"); +VMM_STAT(VMEXIT_REQIDLE, "number of times idle requested at exit"); VMM_STAT(VMEXIT_USERSPACE, "number of vm exits handled in userspace"); VMM_STAT(VMEXIT_RENDEZVOUS, "number of times rendezvous pending at exit"); VMM_STAT(VMEXIT_EXCEPTION, "number of vm exits due to exceptions"); diff --git a/sys/amd64/vmm/vmm_stat.h b/sys/amd64/vmm/vmm_stat.h index 1640ba37e025..c69584090264 100644 --- a/sys/amd64/vmm/vmm_stat.h +++ b/sys/amd64/vmm/vmm_stat.h @@ -157,4 +157,5 @@ VMM_STAT_DECLARE(VMEXIT_ASTPENDING); VMM_STAT_DECLARE(VMEXIT_USERSPACE); VMM_STAT_DECLARE(VMEXIT_RENDEZVOUS); VMM_STAT_DECLARE(VMEXIT_EXCEPTION); +VMM_STAT_DECLARE(VMEXIT_REQIDLE); #endif diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 47a769908cf3..ee0f1060a92c 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -100,7 +100,7 @@ static struct vm_exit vmexit[VM_MAXCPU]; struct bhyvestats { uint64_t vmexit_bogus; - uint64_t vmexit_bogus_switch; + uint64_t vmexit_reqidle; uint64_t vmexit_hlt; uint64_t vmexit_pause; uint64_t vmexit_mtrap; @@ -460,6 +460,17 @@ vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) return (VMEXIT_CONTINUE); } +static int +vmexit_reqidle(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) +{ + + assert(vmexit->inst_length == 0); + + stats.vmexit_reqidle++; + + return (VMEXIT_CONTINUE); +} + static int vmexit_hlt(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) { @@ -571,6 +582,7 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = { [VM_EXITCODE_VMX] = vmexit_vmx, [VM_EXITCODE_SVM] = vmexit_svm, [VM_EXITCODE_BOGUS] = vmexit_bogus, + [VM_EXITCODE_REQIDLE] = vmexit_reqidle, [VM_EXITCODE_RDMSR] = vmexit_rdmsr, [VM_EXITCODE_WRMSR] = vmexit_wrmsr, [VM_EXITCODE_MTRAP] = vmexit_mtrap, From ec768a1460601dc29457cd73121acbb33b43840b Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 May 2015 17:57:56 +0000 Subject: [PATCH 33/65] Use macros for overhead in a consistent way. No functional change. Thanks to Irene Ruengeler for suggesting the change. MFC after: 3 days --- sys/netinet/sctp_output.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index ef263a8c583c..ebc66923b9d7 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -4063,7 +4063,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_route_t iproute; int len; - len = sizeof(struct ip) + sizeof(struct sctphdr); + len = SCTP_MIN_V4_OVERHEAD; if (port) { len += sizeof(struct udphdr); } @@ -4345,7 +4345,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, flowlabel = ntohl(((struct in6pcb *)inp)->in6p_flowinfo); } flowlabel &= 0x000fffff; - len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr); + len = SCTP_MIN_OVERHEAD; if (port) { len += sizeof(struct udphdr); } @@ -5107,10 +5107,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, if (op_err == NULL) { /* Ok need to try to get a mbuf */ #ifdef INET6 - l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_OVERHEAD; #else - l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_V4_OVERHEAD; #endif + l_len += sizeof(struct sctp_chunkhdr); l_len += plen; l_len += sizeof(struct sctp_paramhdr); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA); @@ -5176,10 +5177,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, /* Ok need to try to get an mbuf */ #ifdef INET6 - l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_OVERHEAD; #else - l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_V4_OVERHEAD; #endif + l_len += sizeof(struct sctp_chunkhdr); l_len += plen; l_len += sizeof(struct sctp_paramhdr); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA); @@ -5251,10 +5253,11 @@ invalid_size: int l_len; #ifdef INET6 - l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_OVERHEAD; #else - l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_V4_OVERHEAD; #endif + l_len += sizeof(struct sctp_chunkhdr); l_len += (2 * sizeof(struct sctp_paramhdr)); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA); if (op_err) { @@ -7961,12 +7964,12 @@ again_one_more_time: switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { #ifdef INET case AF_INET: - mtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr)); + mtu = net->mtu - SCTP_MIN_V4_OVERHEAD; break; #endif #ifdef INET6 case AF_INET6: - mtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)); + mtu = net->mtu - SCTP_MIN_OVERHEAD; break; #endif default: @@ -8513,16 +8516,16 @@ again_one_more_time: switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { #ifdef INET case AF_INET: - if (net->mtu > (sizeof(struct ip) + sizeof(struct sctphdr))) - omtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr)); + if (net->mtu > SCTP_MIN_V4_OVERHEAD) + omtu = net->mtu - SCTP_MIN_V4_OVERHEAD; else omtu = 0; break; #endif #ifdef INET6 case AF_INET6: - if (net->mtu > (sizeof(struct ip6_hdr) + sizeof(struct sctphdr))) - omtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)); + if (net->mtu > SCTP_MIN_OVERHEAD) + omtu = net->mtu - SCTP_MIN_OVERHEAD; else omtu = 0; break; From e30be399be1d292717acb645781b1ca75dbb525f Mon Sep 17 00:00:00 2001 From: slm Date: Thu, 28 May 2015 18:14:55 +0000 Subject: [PATCH 34/65] The wrong commit message was given with r283632. To get the correct commit message synced to the changes in r283632, those changes are now backed out. Another commit will be done that is exactly the same as r283632 except it will have to correct commit message. Approved by: ken, scottl, asomers, gibbs --- sys/dev/mpr/mpi/mpi2.h | 8 +- sys/dev/mpr/mpi/mpi2_cnfg.h | 8 +- sys/dev/mpr/mpi/mpi2_hbd.h | 8 +- sys/dev/mpr/mpi/mpi2_history.txt | 8 +- sys/dev/mpr/mpi/mpi2_init.h | 8 +- sys/dev/mpr/mpi/mpi2_ioc.h | 8 +- sys/dev/mpr/mpi/mpi2_ra.h | 8 +- sys/dev/mpr/mpi/mpi2_raid.h | 8 +- sys/dev/mpr/mpi/mpi2_sas.h | 8 +- sys/dev/mpr/mpi/mpi2_targ.h | 8 +- sys/dev/mpr/mpi/mpi2_tool.h | 8 +- sys/dev/mpr/mpi/mpi2_type.h | 8 +- sys/dev/mpr/mpr.c | 90 +++--- sys/dev/mpr/mpr_config.c | 5 +- sys/dev/mpr/mpr_ioctl.h | 7 +- sys/dev/mpr/mpr_mapping.c | 72 ++--- sys/dev/mpr/mpr_mapping.h | 10 +- sys/dev/mpr/mpr_pci.c | 14 +- sys/dev/mpr/mpr_sas.c | 476 ++++++++++++++----------------- sys/dev/mpr/mpr_sas.h | 31 +- sys/dev/mpr/mpr_sas_lsi.c | 360 +++++++---------------- sys/dev/mpr/mpr_user.c | 41 +-- sys/dev/mpr/mprvar.h | 38 +-- 23 files changed, 473 insertions(+), 767 deletions(-) diff --git a/sys/dev/mpr/mpi/mpi2.h b/sys/dev/mpr/mpi/mpi2.h index 42fdec20c503..10f17aba067e 100644 --- a/sys/dev/mpr/mpi/mpi2.h +++ b/sys/dev/mpr/mpi/mpi2.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2.h diff --git a/sys/dev/mpr/mpi/mpi2_cnfg.h b/sys/dev/mpr/mpi/mpi2_cnfg.h index 3b0eb637a9e2..d82750f80913 100644 --- a/sys/dev/mpr/mpi/mpi2_cnfg.h +++ b/sys/dev/mpr/mpi/mpi2_cnfg.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_cnfg.h diff --git a/sys/dev/mpr/mpi/mpi2_hbd.h b/sys/dev/mpr/mpi/mpi2_hbd.h index 520407b39948..d0cc09f905a0 100644 --- a/sys/dev/mpr/mpi/mpi2_hbd.h +++ b/sys/dev/mpr/mpi/mpi2_hbd.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2009-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2009-2011 LSI Corporation. * * * Name: mpi2_hbd.h diff --git a/sys/dev/mpr/mpi/mpi2_history.txt b/sys/dev/mpr/mpi/mpi2_history.txt index 9fca7966f65a..296b75b87859 100644 --- a/sys/dev/mpr/mpi/mpi2_history.txt +++ b/sys/dev/mpr/mpi/mpi2_history.txt @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -36,8 +35,7 @@ Fusion-MPT MPI 2.0 / 2.5 Header File Change History ============================== - Copyright (c) 2000-2015 LSI Corporation. - Copyright (c) 2013-2015 Avago Technologies + Copyright (c) 2000-2013 LSI Corporation. --------------------------------------- Header Set Release Version: 02.00.33 diff --git a/sys/dev/mpr/mpi/mpi2_init.h b/sys/dev/mpr/mpi/mpi2_init.h index 5f475c0e26ba..62b0cfed120a 100644 --- a/sys/dev/mpr/mpi/mpi2_init.h +++ b/sys/dev/mpr/mpi/mpi2_init.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_init.h diff --git a/sys/dev/mpr/mpi/mpi2_ioc.h b/sys/dev/mpr/mpi/mpi2_ioc.h index 54f39a5adc71..38a46f5280bc 100644 --- a/sys/dev/mpr/mpi/mpi2_ioc.h +++ b/sys/dev/mpr/mpi/mpi2_ioc.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_ioc.h diff --git a/sys/dev/mpr/mpi/mpi2_ra.h b/sys/dev/mpr/mpi/mpi2_ra.h index 02304aaa002e..76db06b71b98 100644 --- a/sys/dev/mpr/mpi/mpi2_ra.h +++ b/sys/dev/mpr/mpi/mpi2_ra.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2012-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2009 LSI Corporation. * * * Name: mpi2_ra.h diff --git a/sys/dev/mpr/mpi/mpi2_raid.h b/sys/dev/mpr/mpi/mpi2_raid.h index 52ebf07ee096..c6bb59864a3c 100644 --- a/sys/dev/mpr/mpi/mpi2_raid.h +++ b/sys/dev/mpr/mpi/mpi2_raid.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_raid.h diff --git a/sys/dev/mpr/mpi/mpi2_sas.h b/sys/dev/mpr/mpi/mpi2_sas.h index 7cae2c3d4adf..2a107f1e1617 100644 --- a/sys/dev/mpr/mpi/mpi2_sas.h +++ b/sys/dev/mpr/mpi/mpi2_sas.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_sas.h diff --git a/sys/dev/mpr/mpi/mpi2_targ.h b/sys/dev/mpr/mpi/mpi2_targ.h index 85b5ac562610..506e64f6370c 100644 --- a/sys/dev/mpr/mpi/mpi2_targ.h +++ b/sys/dev/mpr/mpi/mpi2_targ.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2012 LSI Corporation. * * * Name: mpi2_targ.h diff --git a/sys/dev/mpr/mpi/mpi2_tool.h b/sys/dev/mpr/mpi/mpi2_tool.h index 59917c0077f5..94542cc7959b 100644 --- a/sys/dev/mpr/mpi/mpi2_tool.h +++ b/sys/dev/mpr/mpi/mpi2_tool.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_tool.h diff --git a/sys/dev/mpr/mpi/mpi2_type.h b/sys/dev/mpr/mpi/mpi2_type.h index b063683263d0..da3aefb968f4 100644 --- a/sys/dev/mpr/mpi/mpi2_type.h +++ b/sys/dev/mpr/mpi/mpi2_type.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2000-2007 LSI Corporation. * * * Name: mpi2_type.h diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index 07e73c54e8be..d3fb9a0682b8 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1,7 +1,6 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2012-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,14 +24,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD - * */ #include __FBSDID("$FreeBSD$"); -/* Communications core for Avago Technologies (LSI) MPT3 */ +/* Communications core for LSI MPT2 */ /* TODO Move headers to mprvar */ #include @@ -75,6 +72,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include static int mpr_diag_reset(struct mpr_softc *sc, int sleep_flag); static int mpr_init_queues(struct mpr_softc *sc); @@ -354,9 +352,11 @@ mpr_transition_operational(struct mpr_softc *sc) static int mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) { - int error; + int error, i; Mpi2IOCFactsReply_t saved_facts; uint8_t saved_mode, reallocating; + struct mprsas_lun *lun, *lun_tmp; + struct mprsas_target *targ; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); @@ -513,7 +513,27 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) */ if (reallocating) { mpr_iocfacts_free(sc); - mprsas_realloc_targets(sc, saved_facts.MaxTargets); + + /* + * The number of targets is based on IOC Facts, so free all of + * the allocated LUNs for each target and then the target buffer + * itself. + */ + for (i=0; i< saved_facts.MaxTargets; i++) { + targ = &sc->sassc->targets[i]; + SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, + lun_tmp) { + free(lun, M_MPR); + } + } + free(sc->sassc->targets, M_MPR); + + sc->sassc->targets = malloc(sizeof(struct mprsas_target) * + sc->facts->MaxTargets, M_MPR, M_WAITOK|M_ZERO); + if (!sc->sassc->targets) { + panic("%s failed to alloc targets with error %d\n", + __func__, ENOMEM); + } } /* @@ -755,7 +775,7 @@ mpr_reinit(struct mpr_softc *sc) /* the end of discovery will release the simq, so we're done. */ mpr_dprint(sc, MPR_INFO, "%s finished sc %p post %u free %u\n", __func__, sc, sc->replypostindex, sc->replyfreeindex); - mprsas_release_simq_reinit(sassc); + mprsas_release_simq_reinit(sassc); return 0; } @@ -796,8 +816,7 @@ mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag) * 0.5 milisecond */ if (mtx_owned(&sc->mpr_mtx) && sleep_flag == CAN_SLEEP) - msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", - hz/1000); + msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", hz/1000); else if (sleep_flag == CAN_SLEEP) pause("mprdba", hz/1000); else @@ -963,7 +982,7 @@ mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm) reply_descriptor rd; MPR_FUNCTRACE(sc); - mpr_dprint(sc, MPR_TRACE, "SMID %u cm %p ccb %p\n", + mpr_dprint(sc, MPR_TRACE, "%s SMID %u cm %p ccb %p\n", __func__, cm->cm_desc.Default.SMID, cm, cm->cm_ccb); if (sc->mpr_flags & MPR_FLAGS_ATTACH_DONE && !(sc->mpr_flags & @@ -1353,8 +1372,6 @@ mpr_get_tunables(struct mpr_softc *sc) sc->disable_msix = 0; sc->disable_msi = 0; sc->max_chains = MPR_CHAIN_FRAMES; - sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD; - sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; /* * Grab the global variables. @@ -1363,8 +1380,6 @@ mpr_get_tunables(struct mpr_softc *sc) TUNABLE_INT_FETCH("hw.mpr.disable_msix", &sc->disable_msix); TUNABLE_INT_FETCH("hw.mpr.disable_msi", &sc->disable_msi); TUNABLE_INT_FETCH("hw.mpr.max_chains", &sc->max_chains); - TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu); - TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time); /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level", @@ -1387,14 +1402,6 @@ mpr_get_tunables(struct mpr_softc *sc) snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.exclude_ids", device_get_unit(sc->mpr_dev)); TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids)); - - snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.enable_ssu", - device_get_unit(sc->mpr_dev)); - TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu); - - snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time", - device_get_unit(sc->mpr_dev)); - TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); } static void @@ -1467,20 +1474,11 @@ mpr_setup_sysctl(struct mpr_softc *sc) OID_AUTO, "max_chains", CTLFLAG_RD, &sc->max_chains, 0,"maximum chain frames that will be allocated"); - SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), - OID_AUTO, "enable_ssu", CTLFLAG_RW, &sc->enable_ssu, 0, - "enable SSU to SATA SSD/HDD at shutdown"); - #if __FreeBSD_version >= 900030 SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "chain_alloc_fail", CTLFLAG_RD, &sc->chain_alloc_fail, "chain allocation failures"); #endif //FreeBSD_version >= 900030 - - SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), - OID_AUTO, "spinup_wait_time", CTLFLAG_RD, - &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for " - "spinup after SATA ID error"); } int @@ -2098,7 +2096,7 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle, (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) error = ENXIO; - if (reply) + if(reply) mpr_print_event(sc, reply); mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error); @@ -2165,8 +2163,8 @@ mpr_deregister_events(struct mpr_softc *sc, struct mpr_event_handle *handle) * Add a chain element as the next SGE for the specified command. * Reset cm_sge and cm_sgesize to indicate all the available space. Chains are * only required for IEEE commands. Therefore there is no code for commands - * that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands - * shouldn't be requesting chains). + * that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands shouldn't + * be requesting chains). */ static int mpr_add_chain(struct mpr_command *cm, int segsleft) @@ -2248,9 +2246,9 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) /* * Add one scatter-gather element to the scatter-gather list for a command. - * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the - * next SGE to fill in, respectively. In Gen3, the MPI SGL does not have a - * chain, so don't consider any chain additions. + * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the next + * SGE to fill in, respectively. In Gen3, the MPI SGL does not have a chain, + * so don't consider any chain additions. */ int mpr_push_sge(struct mpr_command *cm, MPI2_SGE_SIMPLE64 *sge, size_t len, @@ -2662,7 +2660,7 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) } } - if (error) { + if(error) { mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__); rc = mpr_reinit(sc); mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? @@ -2719,12 +2717,9 @@ mpr_read_config_page(struct mpr_softc *sc, struct mpr_config_params *params) cm->cm_data = params->buffer; cm->cm_length = params->length; - if (cm->cm_data != NULL) { - cm->cm_sge = &req->PageBufferSGE; - cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); - cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; - } else - cm->cm_sge = NULL; + cm->cm_sge = &req->PageBufferSGE; + cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); + cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_complete_data = params; @@ -2781,12 +2776,9 @@ mpr_config_complete(struct mpr_softc *sc, struct mpr_command *cm) goto done; } params->status = reply->IOCStatus; - if (params->hdr.Struct.PageType == MPI2_CONFIG_PAGETYPE_EXTENDED) { + if (params->hdr.Ext.ExtPageType != 0) { params->hdr.Ext.ExtPageType = reply->ExtPageType; params->hdr.Ext.ExtPageLength = reply->ExtPageLength; - params->hdr.Ext.PageType = reply->Header.PageType; - params->hdr.Ext.PageNumber = reply->Header.PageNumber; - params->hdr.Ext.PageVersion = reply->Header.PageVersion; } else { params->hdr.Struct.PageType = reply->Header.PageType; params->hdr.Struct.PageNumber = reply->Header.PageNumber; diff --git a/sys/dev/mpr/mpr_config.c b/sys/dev/mpr/mpr_config.c index c0ea3d5ffb08..125451608dee 100644 --- a/sys/dev/mpr/mpr_config.c +++ b/sys/dev/mpr/mpr_config.c @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD */ #include diff --git a/sys/dev/mpr/mpr_ioctl.h b/sys/dev/mpr/mpr_ioctl.h index aa1a4cbf7697..5ec482f311b0 100644 --- a/sys/dev/mpr/mpr_ioctl.h +++ b/sys/dev/mpr/mpr_ioctl.h @@ -27,13 +27,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface + * LSI MPT-Fusion Host Adapter FreeBSD userland interface * * $FreeBSD$ */ /*- - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,7 +56,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ diff --git a/sys/dev/mpr/mpr_mapping.c b/sys/dev/mpr/mpr_mapping.c index 110e6a3b943f..7f0fc00a9c52 100644 --- a/sys/dev/mpr/mpr_mapping.c +++ b/sys/dev/mpr/mpr_mapping.c @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD */ #include @@ -327,13 +326,11 @@ _mapping_get_high_missing_mt_idx(struct mpr_softc *sc) { u32 map_idx, high_idx = MPR_ENCTABLE_BAD_IDX; u8 high_missing_count = 0; - u32 start_idx, end_idx, start_idx_ir, end_idx_ir; + u32 start_idx, end_idx, start_idx_ir = 0, end_idx_ir; struct dev_mapping_table *mt_entry; u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); start_idx = 0; - start_idx_ir = 0; - end_idx_ir = 0; end_idx = sc->max_devices; if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) start_idx = 1; @@ -890,14 +887,14 @@ _mapping_get_dev_info(struct mpr_softc *sc, u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; - u8 entry, enc_idx, phy_idx, sata_end_device; + u8 entry, enc_idx, phy_idx; u32 map_idx, index, device_info; struct _map_phy_change *phy_change, *tmp_phy_change; uint64_t sas_address; struct enc_mapping_table *et_entry; struct dev_mapping_table *mt_entry; u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED; - int rc = 1; + int rc; for (entry = 0; entry < topo_change->num_entries; entry++) { phy_change = &topo_change->phy_details[entry]; @@ -911,36 +908,41 @@ _mapping_get_dev_info(struct mpr_softc *sc, continue; } - /* - * Always get SATA Identify information because this is used - * to determine if Start/Stop Unit should be sent to the drive - * when the system is shutdown. - */ device_info = le32toh(sas_device_pg0.DeviceInfo); - sas_address = sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; - sata_end_device = 0; - if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && - (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { - sata_end_device = 1; - rc = mprsas_get_sas_address_for_sata_disk(sc, - &sas_address, phy_change->dev_handle, device_info, - &phy_change->is_SATA_SSD); - if (rc) { - mpr_dprint(sc, MPR_ERROR, "%s: failed to get " - "disk type (SSD or HDD) and SAS Address " - "for SATA device with handle 0x%04x\n", - __func__, phy_change->dev_handle); - } else { + if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == + MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { + if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && + (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { + rc = mprsas_get_sas_address_for_sata_disk(sc, + &sas_address, phy_change->dev_handle, + device_info); + if (rc) { + printf("%s: failed to compute the " + "hashed SAS Address for SATA " + "device with handle 0x%04x\n", + __func__, phy_change->dev_handle); + sas_address = + sas_device_pg0.SASAddress.High; + sas_address = (sas_address << 32) | + sas_device_pg0.SASAddress.Low; + } mpr_dprint(sc, MPR_INFO, "SAS Address for SATA " "device = %jx\n", sas_address); + } else { + sas_address = + sas_device_pg0.SASAddress.High; + sas_address = (sas_address << 32) | + sas_device_pg0.SASAddress.Low; } + } else { + sas_address = sas_device_pg0.SASAddress.High; + sas_address = (sas_address << 32) | + sas_device_pg0.SASAddress.Low; } - phy_change->physical_id = sas_address; phy_change->slot = le16toh(sas_device_pg0.Slot); - phy_change->device_info = le32toh(sas_device_pg0.DeviceInfo); + phy_change->device_info = + le32toh(sas_device_pg0.DeviceInfo); if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { @@ -948,10 +950,10 @@ _mapping_get_dev_info(struct mpr_softc *sc, topo_change->enc_handle); if (enc_idx == MPR_ENCTABLE_BAD_IDX) { phy_change->is_processed = 1; - mpr_dprint(sc, MPR_MAPPING, "%s: failed to add " - "the device with handle 0x%04x because the " - "enclosure is not in the mapping table\n", - __func__, phy_change->dev_handle); + printf("%s: failed to add the device with " + "handle 0x%04x because the enclosure is " + "not in the mapping table\n", __func__, + phy_change->dev_handle); continue; } if (!((phy_change->device_info & diff --git a/sys/dev/mpr/mpr_mapping.h b/sys/dev/mpr/mpr_mapping.h index c00a3b795122..3250c424e2a4 100644 --- a/sys/dev/mpr/mpr_mapping.h +++ b/sys/dev/mpr/mpr_mapping.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -39,7 +38,6 @@ * @dev_handle: device handle for the device pointed by this entry * @slot: slot ID * @is_processed: Flag to indicate whether this entry is processed or not - * @is_SATA_SSD: 1 if this is a SATA device AND an SSD, 0 otherwise */ struct _map_phy_change { uint64_t physical_id; @@ -48,8 +46,6 @@ struct _map_phy_change { uint16_t slot; uint8_t reason; uint8_t is_processed; - uint8_t is_SATA_SSD; - uint8_t reserved; }; /** @@ -70,6 +66,6 @@ struct _map_topology_change { extern int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *ioc, - u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); + u64 *sas_address, u16 handle, u32 device_info); #endif diff --git a/sys/dev/mpr/mpr_pci.c b/sys/dev/mpr/mpr_pci.c index 7430eac03b3a..e19f33adceb4 100644 --- a/sys/dev/mpr/mpr_pci.c +++ b/sys/dev/mpr/mpr_pci.c @@ -27,7 +27,7 @@ #include __FBSDID("$FreeBSD$"); -/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT3 controllers */ +/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */ /* TODO Move headers to mprvar */ #include @@ -99,17 +99,17 @@ struct mpr_ident { const char *desc; } mpr_identifiers[] = { { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, - 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3004" }, + 0xffff, 0xffff, 0, "LSI SAS3004" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008, - 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3008" }, + 0xffff, 0xffff, 0, "LSI SAS3008" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1, - 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_1" }, + 0xffff, 0xffff, 0, "LSI SAS3108_1" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2, - 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_2" }, + 0xffff, 0xffff, 0, "LSI SAS3108_2" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5, - 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" }, + 0xffff, 0xffff, 0, "LSI SAS3108_5" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, - 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" }, + 0xffff, 0xffff, 0, "LSI SAS3108_6" }, { 0, 0, 0, 0, 0, NULL } }; diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index eac336068295..32c3a4633a1f 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -1,7 +1,6 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,15 +23,12 @@ * 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. - * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD - * */ #include __FBSDID("$FreeBSD$"); -/* Communications core for Avago Technologies (LSI) MPT3 */ +/* Communications core for LSI MPT2 */ /* TODO Move headers to mprvar */ #include @@ -126,10 +122,14 @@ static void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); static void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); static void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *); -static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, +static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, struct mpr_command *cm); +static int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, + uint8_t type); static void mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); +static void mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, + struct ccb_getdev *cgd); #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, @@ -142,12 +142,13 @@ static void mprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm); #if __FreeBSD_version >= 900026 -static void mprsas_smpio_complete(struct mpr_softc *sc, - struct mpr_command *cm); +static void +mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); static void mprsas_send_smpcmd(struct mprsas_softc *sassc, - union ccb *ccb, uint64_t sasaddr); -static void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); -#endif //FreeBSD_version >= 900026 + union ccb *ccb, uint64_t sasaddr); +static void +mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); +#endif struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, @@ -229,7 +230,7 @@ mprsas_startup_decrement(struct mprsas_softc *sassc) } } -/* The firmware requires us to stop sending commands when we're doing task +/* LSI's firmware requires us to stop sending commands when we're doing task * management, so refcount the TMs and keep the simq frozen when any are in * use. */ @@ -240,31 +241,35 @@ mprsas_alloc_tm(struct mpr_softc *sc) MPR_FUNCTRACE(sc); tm = mpr_alloc_high_priority_command(sc); + if (tm != NULL) { + if (sc->sassc->tm_count++ == 0) { + mpr_dprint(sc, MPR_RECOVERY, + "%s freezing simq\n", __func__); + xpt_freeze_simq(sc->sassc->sim, 1); + } + mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, + sc->sassc->tm_count); + } return tm; } void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) { - MPR_FUNCTRACE(sc); + mpr_dprint(sc, MPR_TRACE, "%s", __func__); if (tm == NULL) return; - /* - * For TM's the devq is frozen for the device. Unfreeze it here and - * free the resources used for freezing the devq. Must clear the - * INRESET flag as well or scsi I/O will not work. + /* if there are no TMs in use, we can release the simq. We use our + * own refcount so that it's easier for a diag reset to cleanup and + * release the simq. */ - if (tm->cm_targ != NULL) { - tm->cm_targ->flags &= ~MPRSAS_TARGET_INRESET; - } - if (tm->cm_ccb) { - mpr_dprint(sc, MPR_INFO, "Unfreezing devq for target ID %d\n", - tm->cm_targ->tid); - xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); - xpt_free_path(tm->cm_ccb->ccb_h.path); - xpt_free_ccb(tm->cm_ccb); + if (--sc->sassc->tm_count == 0) { + mpr_dprint(sc, MPR_RECOVERY, "%s releasing simq\n", __func__); + xpt_release_simq(sc->sassc->sim, 1); } + mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, + sc->sassc->tm_count); mpr_free_high_priority_command(sc, tm); } @@ -293,8 +298,8 @@ mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ) return; } - if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, - CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, + targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; @@ -468,16 +473,11 @@ mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_volume; cm->cm_complete_data = (void *)(uintptr_t)handle; - - mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", - __func__, targ->tid); - mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); - mpr_map_command(sc, cm); } /* - * The MPT3 firmware performs debounce on the link to avoid transient link + * The MPT2 firmware performs debounce on the link to avoid transient link * errors and false removals. When it does decide that link has been lost * and a device needs to go away, it expects that the host will perform a * target reset and then an op remove. The reset has the side-effect of @@ -532,11 +532,6 @@ mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_device; cm->cm_complete_data = (void *)(uintptr_t)handle; - - mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", - __func__, targ->tid); - mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); - mpr_map_command(sc, cm); } @@ -601,10 +596,10 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_map_command(sc, tm); - mpr_dprint(sc, MPR_INFO, "clearing target %u handle 0x%04x\n", + mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n", targ->tid, handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -613,7 +608,7 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_XINFO, "Completing missed command %p\n", tm); ccb = tm->cm_complete_data; - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + ccb->ccb_h.status = CAM_DEV_NOT_THERE; mprsas_scsiio_complete(sc, tm); } } @@ -731,7 +726,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * XXX MaxTargets could change during a reinit. Since we don't + * XXX MaxTargets could change during a reinit. since we don't * resize the targets[] array during such an event, cache the value * of MaxTargets here so that we don't get into trouble later. This * should move into the reinit logic. @@ -787,7 +782,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * Assume that discovery events will start right away. + * Assume that discovery events will start right away. Freezing * * Hold off boot until discovery is complete. */ @@ -795,7 +790,9 @@ mpr_attach_sas(struct mpr_softc *sc) sc->sassc->startup_refcount = 0; mprsas_startup_increment(sassc); - callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); + callout_init(&sassc->discovery_callout, 1 /*mprafe*/); + + sassc->tm_count = 0; /* * Register for async events so we can determine the EEDP @@ -965,7 +962,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) sassc = cam_sim_softc(sim); MPR_FUNCTRACE(sassc->sc); - mpr_dprint(sassc->sc, MPR_TRACE, "ccb func_code 0x%x\n", + mpr_dprint(sassc->sc, MPR_TRACE, "%s func 0x%x\n", __func__, ccb->ccb_h.func_code); mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); @@ -988,7 +985,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cpi->max_lun = 255; cpi->initiator_id = sassc->maxtargets - 1; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "Avago Tech (LSI)", HBA_IDLEN); + strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = cam_sim_bus(sim); @@ -1008,7 +1005,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) */ cpi->maxio = 256 * 1024; #endif - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + cpi->ccb_h.status = CAM_REQ_CMP; break; } case XPT_GET_TRAN_SETTINGS: @@ -1027,7 +1024,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cts->ccb_h.target_id)); targ = &sassc->targets[cts->ccb_h.target_id]; if (targ->handle == 0x0) { - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + cts->ccb_h.status = CAM_DEV_NOT_THERE; break; } @@ -1057,12 +1054,12 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) scsi->valid = CTS_SCSI_VALID_TQ; scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + cts->ccb_h.status = CAM_REQ_CMP; break; } case XPT_CALC_GEOMETRY: cam_calc_geometry(&ccb->ccg, /*extended*/1); - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + ccb->ccb_h.status = CAM_REQ_CMP; break; case XPT_RESET_DEV: mpr_dprint(sassc->sc, MPR_XINFO, @@ -1074,7 +1071,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) case XPT_TERM_IO: mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success for abort or reset\n"); - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + ccb->ccb_h.status = CAM_REQ_CMP; break; case XPT_SCSI_IO: mprsas_action_scsiio(sassc, ccb); @@ -1085,7 +1082,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) return; #endif default: - mprsas_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL); + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; break; } xpt_done(ccb); @@ -1105,7 +1102,7 @@ mprsas_announce_reset(struct mpr_softc *sc, uint32_t ac_code, if (xpt_create_path(&path, NULL, path_id, target_id, lun_id) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for reset " - "notification\n"); + "notification\n"); return; } @@ -1134,8 +1131,8 @@ mprsas_complete_all_commands(struct mpr_softc *sc) if (cm->cm_complete != NULL) { mprsas_log_command(cm, MPR_RECOVERY, - "completing cm %p state %x ccb %p for diag " - "reset\n", cm, cm->cm_state, cm->cm_ccb); + "completing cm %p state %x ccb %p for diag reset\n", + cm, cm->cm_state, cm->cm_ccb); cm->cm_complete(sc, cm); completed = 1; } @@ -1148,14 +1145,6 @@ mprsas_complete_all_commands(struct mpr_softc *sc) completed = 1; } - if (cm->cm_sc->io_cmds_active != 0) { - cm->cm_sc->io_cmds_active--; - } else { - mpr_dprint(cm->cm_sc, MPR_INFO, "Warning: " - "io_cmds_active is out of sync - resynching to " - "0\n"); - } - if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) { /* this should never happen, but if it does, log */ mprsas_log_command(cm, MPR_RECOVERY, @@ -1191,8 +1180,9 @@ mprsas_handle_reinit(struct mpr_softc *sc) /* complete and cleanup after all outstanding commands */ mprsas_complete_all_commands(sc); - mpr_dprint(sc, MPR_INIT, "%s startup %u after command completion\n", - __func__, sc->sassc->startup_refcount); + mpr_dprint(sc, MPR_INIT, "%s startup %u tm %u after command " + "completion\n", __func__, sc->sassc->startup_refcount, + sc->sassc->tm_count); /* zero all the target handles, since they may change after the * reset, and we have to rediscover all the targets and use the new @@ -1254,6 +1244,7 @@ mprsas_logical_unit_reset_complete(struct mpr_softc *sc, "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ + targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1331,8 +1322,8 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) * task management commands don't have S/G lists. */ if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target " - "reset! This should not happen!\n", __func__, tm->cm_flags); + mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x for target reset! " + "This should not happen!\n", __func__, tm->cm_flags); mprsas_free_tm(sc, tm); return; } @@ -1342,6 +1333,7 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ + targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1357,6 +1349,8 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), le32toh(reply->TerminationCount)); + targ->flags &= ~MPRSAS_TARGET_INRESET; + if (targ->outstanding == 0) { /* we've finished recovery for this target and all * of its logical units. @@ -1384,7 +1378,7 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) #define MPR_RESET_TIMEOUT 30 -int +static int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) { MPI2_SCSI_TASK_MANAGE_REQUEST *req; @@ -1393,8 +1387,8 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) target = tm->cm_targ; if (target->handle == 0) { - mpr_dprint(sc, MPR_ERROR, "%s null devhandle for target_id " - "%d\n", __func__, target->tid); + mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n", + __func__, target->tid); return -1; } @@ -1410,7 +1404,6 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending logical unit reset\n"); tm->cm_complete = mprsas_logical_unit_reset_complete; - mprsas_prepare_for_tm(sc, tm, target, tm->cm_lun); } else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { /* @@ -1419,20 +1412,20 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) */ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; tm->cm_targ->target_resets++; + tm->cm_targ->flags |= MPRSAS_TARGET_INRESET; mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending target reset\n"); tm->cm_complete = mprsas_target_reset_complete; - mprsas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD); } else { mpr_dprint(sc, MPR_ERROR, "unexpected reset type 0x%x\n", type); return -1; } - mpr_dprint(sc, MPR_INFO, "to target %u handle 0x%04x\n", target->tid, + mpr_dprint(sc, MPR_XINFO, "to target %u handle 0x%04x\n", target->tid, target->handle); if (target->encl_level_valid) { - mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", target->encl_level, target->encl_slot, target->connector_name); } @@ -1448,7 +1441,8 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, - "error %d sending reset type %u\n", err, type); + "error %d sending reset type %u\n", + err, type); return err; } @@ -1579,10 +1573,6 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, targ->aborts++; - mpr_dprint(sc, MPR_INFO, "Sending reset from %s for target ID %d\n", - __func__, targ->tid); - mprsas_prepare_for_tm(sc, tm, targ, tm->cm_lun); - err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, @@ -1591,6 +1581,7 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, return err; } + static void mprsas_scsiio_timeout(void *data) { @@ -1626,11 +1617,11 @@ mprsas_scsiio_timeout(void *data) targ = cm->cm_targ; targ->timeouts++; - mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p " + mprsas_log_command(cm, MPR_XINFO, "command timeout cm %p ccb %p " "target %u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, targ->handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -1638,7 +1629,8 @@ mprsas_scsiio_timeout(void *data) /* XXX first, check the firmware state, to see if it's still * operational. if not, do a diag reset. */ - mprsas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT); + + cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT; cm->cm_state = MPR_CM_STATE_TIMEDOUT; TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); @@ -1689,22 +1681,19 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) mtx_assert(&sc->mpr_mtx, MA_OWNED); csio = &ccb->csio; - KASSERT(csio->ccb_h.target_id < sassc->maxtargets, - ("Target %d out of bounds in XPT_SCSI_IO\n", - csio->ccb_h.target_id)); targ = &sassc->targets[csio->ccb_h.target_id]; mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n", __func__, csio->ccb_h.target_id); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + csio->ccb_h.status = CAM_DEV_NOT_THERE; xpt_done(ccb); return; } if (targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT) { - mpr_dprint(sc, MPR_ERROR, "%s Raid component no SCSI IO " + mpr_dprint(sc, MPR_TRACE, "%s Raid component no SCSI IO " "supported %u\n", __func__, csio->ccb_h.target_id); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + csio->ccb_h.status = CAM_DEV_NOT_THERE; xpt_done(ccb); return; } @@ -1713,7 +1702,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) * Progress" and was actually aborted by the upper layer. Check for * this here and complete the command without error. */ - if (mprsas_get_ccbstatus(ccb) != CAM_REQ_INPROG) { + if (ccb->ccb_h.status != CAM_REQ_INPROG) { mpr_dprint(sc, MPR_TRACE, "%s Command is not in progress for " "target %u\n", __func__, csio->ccb_h.target_id); xpt_done(ccb); @@ -1726,29 +1715,16 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) */ if (targ->flags & MPRSAS_TARGET_INREMOVAL) { if (targ->devinfo == 0) - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + csio->ccb_h.status = CAM_REQ_CMP; else - mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); + csio->ccb_h.status = CAM_SEL_TIMEOUT; xpt_done(ccb); return; } if ((sc->mpr_flags & MPR_FLAGS_SHUTDOWN) != 0) { - mpr_dprint(sc, MPR_INFO, "%s shutting down\n", __func__); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); - xpt_done(ccb); - return; - } - - /* - * If target has a reset in progress, freeze the devq and return. The - * devq will be released when the TM reset is finished. - */ - if (targ->flags & MPRSAS_TARGET_INRESET) { - ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; - mpr_dprint(sc, MPR_INFO, "%s: Freezing devq for target ID %d\n", - __func__, targ->tid); - xpt_freeze_devq(ccb->ccb_h.path, 1); + mpr_dprint(sc, MPR_TRACE, "%s shutting down\n", __func__); + csio->ccb_h.status = CAM_DEV_NOT_THERE; xpt_done(ccb); return; } @@ -1831,7 +1807,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) if (MPR_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { mpr_free_command(sc, cm); - mprsas_set_ccbstatus(ccb, CAM_LUN_INVALID); + ccb->ccb_h.status = CAM_LUN_INVALID; xpt_done(ccb); return; } @@ -1928,7 +1904,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) } callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, - mprsas_scsiio_timeout, cm, 0); + mprsas_scsiio_timeout, cm, 0); targ->issued++; targ->outstanding++; @@ -2126,7 +2102,7 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio, desc_scsi_state, scsi_state); if (sc->mpr_debug & MPR_XINFO && - scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { + scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : Start :\n"); scsi_sense_print(csio); mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : End :\n"); @@ -2150,8 +2126,6 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) u8 *TLR_bits, TLR_on; int dir = 0, i; u16 alloc_len; - struct mprsas_target *target; - target_id_t target_id; MPR_FUNCTRACE(sc); mpr_dprint(sc, MPR_TRACE, @@ -2165,7 +2139,6 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) sassc = sc->sassc; ccb = cm->cm_complete_data; csio = &ccb->csio; - target_id = csio->ccb_h.target_id; rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; /* * XXX KDM if the chain allocation fails, does it matter if we do @@ -2224,7 +2197,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * because there can be no reply when we haven't actually * gone out to the hardware. */ - mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); + ccb->ccb_h.status = CAM_REQUEUE_REQ; /* * Currently the only error included in the mask is @@ -2241,7 +2214,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) xpt_freeze_simq(sassc->sim, 1); sassc->flags |= MPRSAS_QUEUE_FROZEN; mpr_dprint(sc, MPR_INFO, "Error sending command, " - "freezing SIM queue\n"); + "freezing SIM queue\n"); } } @@ -2251,7 +2224,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * commands that were sent. All SSU commands should be completed before * shutdown completes, meaning SSU_refcount will be 0 after SSU_started * is TRUE. - */ + */ if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) { mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n"); sc->SSU_refcount--; @@ -2259,12 +2232,12 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Take the fast path to completion */ if (cm->cm_reply == NULL) { - if (mprsas_get_ccbstatus(ccb) == CAM_REQ_INPROG) { + if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) - mprsas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET); + ccb->ccb_h.status = CAM_SCSI_BUS_RESET; else { - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); - csio->scsi_status = SCSI_STATUS_OK; + ccb->ccb_h.status = CAM_REQ_CMP; + ccb->csio.scsi_status = SCSI_STATUS_OK; } if (sassc->flags & MPRSAS_QUEUE_FROZEN) { ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -2279,10 +2252,10 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * CAM_REQ_CMP. The first is if MPR_CM_FLAGS_ERROR_MASK is * set, the second is in the MPR_FLAGS_DIAGRESET above. */ - if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { /* * Freeze the dev queue so that commands are - * executed in the correct order after error + * executed in the correct order with after error * recovery. */ ccb->ccb_h.status |= CAM_DEV_QFRZN; @@ -2312,7 +2285,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Completion failed at the transport level. */ if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | MPI2_SCSI_STATE_TERMINATED)) { - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; break; } @@ -2321,7 +2294,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * recover the command. */ if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { - mprsas_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); + ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; break; } @@ -2333,7 +2306,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) == MPR_SCSI_RI_INVALID_FRAME)) { - sc->mapping_table[target_id].TLR_bits = + sc->mapping_table[csio->ccb_h.target_id].TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; } @@ -2345,16 +2318,16 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) */ if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { - mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); + ccb->ccb_h.status = CAM_REQ_ABORTED; break; } /* Handle normal status and sense */ csio->scsi_status = rep->SCSIStatus; if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + ccb->ccb_h.status = CAM_REQ_CMP; else - mprsas_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); + ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { int sense_len, returned_sense_len; @@ -2389,11 +2362,12 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) (csio->data_ptr != NULL) && ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) && (sc->control_TLR) && - (sc->mapping_table[target_id].device_info & + (sc->mapping_table[csio->ccb_h.target_id].device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { vpd_list = (struct scsi_vpd_supported_page_list *) csio->data_ptr; - TLR_bits = &sc->mapping_table[target_id].TLR_bits; + TLR_bits = &sc->mapping_table[csio->ccb_h.target_id]. + TLR_bits; *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) + @@ -2406,24 +2380,6 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) } } } - - /* - * If this is a SATA direct-access end device, mark it so that - * a SCSI StartStopUnit command will be sent to it when the - * driver is being shutdown. - */ - if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) && - ((csio->data_ptr[0] & 0x1f) == T_DIRECT) && - (sc->mapping_table[target_id].device_info & - MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && - ((sc->mapping_table[target_id].device_info & - MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == - MPI2_SAS_DEVICE_INFO_END_DEVICE)) { - target = &sassc->targets[target_id]; - target->supports_SSU = TRUE; - mpr_dprint(sc, MPR_XINFO, "Target %d supports SSU\n", - target_id); - } break; case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: @@ -2434,13 +2390,13 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * failed. */ if (cm->cm_targ->devinfo == 0) - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + ccb->ccb_h.status = CAM_REQ_CMP; else - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + ccb->ccb_h.status = CAM_DEV_NOT_THERE; break; case MPI2_IOCSTATUS_INVALID_SGL: mpr_print_scsiio_cmd(sc, cm); - mprsas_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); + ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; break; case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: /* @@ -2453,14 +2409,14 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * on the console. */ if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) - mprsas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT); + ccb->ccb_h.status = CAM_CMD_TIMEOUT; else - mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); + ccb->ccb_h.status = CAM_REQ_ABORTED; break; case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: /* resid is ignored for this condition */ csio->resid = 0; - mprsas_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); + ccb->ccb_h.status = CAM_DATA_RUN_ERR; break; case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: @@ -2469,7 +2425,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * transient transport-related) errors, retry these without * decrementing the retry count. */ - mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); + ccb->ccb_h.status = CAM_REQUEUE_REQ; mprsas_log_command(cm, MPR_INFO, "terminated ioc %x scsi %x state %x xfer %u\n", le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, @@ -2491,7 +2447,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, le32toh(rep->TransferCount)); csio->resid = cm->cm_length; - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; break; } @@ -2504,7 +2460,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) "queue\n"); } - if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { ccb->ccb_h.status |= CAM_DEV_QFRZN; xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); } @@ -2531,16 +2487,16 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) * in the standard request size. */ if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x on SMP " - "request!\n", __func__, cm->cm_flags); - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); + mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x on SMP request!\n", + __func__, cm->cm_flags); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; goto bailout; } rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; if (rpl == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: NULL cm_reply!\n", __func__); - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; goto bailout; } @@ -2553,17 +2509,17 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; goto bailout; } - mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address %#jx " - "completed successfully\n", __func__, (uintmax_t)sasaddr); + mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address " + "%#jx completed successfully\n", __func__, (uintmax_t)sasaddr); if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + ccb->ccb_h.status = CAM_REQ_CMP; else - mprsas_set_ccbstatus(ccb, CAM_SMP_STATUS_ERROR); + ccb->ccb_h.status = CAM_SMP_STATUS_ERROR; bailout: /* @@ -2602,7 +2558,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, */ mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " "supported\n", __func__); - mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); + ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); return; case CAM_DATA_SG: @@ -2615,7 +2571,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or response buffer segments " "not supported for SMP\n", __func__); - mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); + ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); return; } @@ -2649,7 +2605,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, response = ccb->smpio.smp_response; break; default: - mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); + ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); return; } @@ -2658,9 +2614,9 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, * XXX We don't yet support physical addresses here. */ if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) { - mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " - "supported\n", __func__); - mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); + mpr_printf(sc, "%s: physical addresses not supported\n", + __func__); + ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); return; } @@ -2679,7 +2635,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " "response buffer segments not supported for SMP\n", __func__); - mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); + ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); return; } @@ -2717,7 +2673,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, if (cm == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n", __func__); - mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); + ccb->ccb_h.status = CAM_RESRC_UNAVAIL; xpt_done(ccb); return; } @@ -2804,7 +2760,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, bailout_error: mpr_free_command(sc, cm); - mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); + ccb->ccb_h.status = CAM_RESRC_UNAVAIL; xpt_done(ccb); return; } @@ -2827,7 +2783,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: target %d does not exist!\n", __func__, ccb->ccb_h.target_id); - mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); + ccb->ccb_h.status = CAM_SEL_TIMEOUT; xpt_done(ccb); return; } @@ -2875,7 +2831,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->parent_handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent handle!\n", __func__, targ->handle); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + ccb->ccb_h.status = CAM_DEV_NOT_THERE; goto bailout; } #ifdef OLD_MPR_PROBE @@ -2885,7 +2841,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (parent_target == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent target!\n", __func__, targ->handle); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + ccb->ccb_h.status = CAM_DEV_NOT_THERE; goto bailout; } @@ -2894,8 +2850,9 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, parent_target->handle); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + ccb->ccb_h.status = CAM_DEV_NOT_THERE; goto bailout; + } sasaddr = parent_target->sasaddr; @@ -2905,7 +2862,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, targ->parent_handle); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + ccb->ccb_h.status = CAM_DEV_NOT_THERE; goto bailout; } @@ -2913,7 +2870,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent handle " "%d does not have a valid SAS address!\n", __func__, targ->handle, targ->parent_handle); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + ccb->ccb_h.status = CAM_DEV_NOT_THERE; goto bailout; } @@ -2925,7 +2882,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (sasaddr == 0) { mpr_dprint(sc, MPR_INFO, "%s: unable to find SAS address for " "handle %d\n", __func__, targ->handle); - mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + ccb->ccb_h.status = CAM_DEV_NOT_THERE; goto bailout; } mprsas_send_smpcmd(sassc, ccb, sasaddr); @@ -2957,7 +2914,7 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) if (tm == NULL) { mpr_dprint(sc, MPR_ERROR, "command alloc failure in mprsas_action_resetdev\n"); - mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); + ccb->ccb_h.status = CAM_RESRC_UNAVAIL; xpt_done(ccb); return; } @@ -2976,12 +2933,7 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; tm->cm_complete = mprsas_resetdev_complete; tm->cm_complete_data = ccb; - - mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", - __func__, targ->tid); tm->cm_targ = targ; - targ->flags |= MPRSAS_TARGET_INRESET; - mpr_map_command(sc, tm); } @@ -3010,7 +2962,7 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " "handle %#04x! This should not happen!\n", __func__, tm->cm_flags, req->DevHandle); - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; goto bailout; } @@ -3019,12 +2971,12 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + ccb->ccb_h.status = CAM_REQ_CMP; mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, CAM_LUN_WILDCARD); } else - mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; bailout: @@ -3043,8 +2995,7 @@ mprsas_poll(struct cam_sim *sim) /* frequent debug messages during a panic just slow * everything down too much. */ - mpr_dprint(sassc->sc, MPR_XINFO, "%s clearing MPR_TRACE\n", - __func__); + mpr_printf(sassc->sc, "%s clearing MPR_TRACE\n", __func__); sassc->sc->mpr_debug &= ~MPR_TRACE; } @@ -3143,7 +3094,7 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE); - if ((mprsas_get_ccbstatus((union ccb *)&cdai) == CAM_REQ_CMP) + if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) && (rcap_buf.prot & SRC16_PROT_EN)) { lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf.length); @@ -3170,6 +3121,8 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, #endif cgd = arg; + mprsas_prepare_ssu(sc, path, cgd); + #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) mprsas_check_eedp(sc, path, cgd); @@ -3181,6 +3134,64 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, } } +static void +mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, + struct ccb_getdev *cgd) +{ + struct mprsas_softc *sassc = sc->sassc; + path_id_t pathid; + target_id_t targetid; + lun_id_t lunid; + struct mprsas_target *target; + struct mprsas_lun *lun; + uint8_t found_lun; + + sassc = sc->sassc; + pathid = cam_sim_path(sassc->sim); + targetid = xpt_path_target_id(path); + lunid = xpt_path_lun_id(path); + + KASSERT(targetid < sassc->maxtargets, + ("Target %d out of bounds in mprsas_prepare_ssu\n", targetid)); + target = &sassc->targets[targetid]; + if (target->handle == 0x0) + return; + + /* + * If LUN is already in list, don't create a new one. + */ + found_lun = FALSE; + SLIST_FOREACH(lun, &target->luns, lun_link) { + if (lun->lun_id == lunid) { + found_lun = TRUE; + break; + } + } + if (!found_lun) { + lun = malloc(sizeof(struct mprsas_lun), M_MPR, + M_NOWAIT | M_ZERO); + if (lun == NULL) { + mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for " + "preparing SSU.\n"); + return; + } + lun->lun_id = lunid; + SLIST_INSERT_HEAD(&target->luns, lun, lun_link); + } + + /* + * If this is a SATA direct-access end device, mark it so that a SCSI + * StartStopUnit command will be sent to it when the driver is being + * shutdown. + */ + if (((cgd->inq_data.device & 0x1F) == T_DIRECT) && + (target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && + ((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == + MPI2_SAS_DEVICE_INFO_END_DEVICE)) { + lun->stop_at_shutdown = TRUE; + } +} + #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void @@ -3201,6 +3212,7 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, uint8_t found_lun; char path_str[64]; + sassc = sc->sassc; pathid = cam_sim_path(sassc->sim); targetid = xpt_path_target_id(path); lunid = xpt_path_lun_id(path); @@ -3276,7 +3288,7 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), M_MPR, M_NOWAIT | M_ZERO); if (rcap_buf == NULL) { - mpr_dprint(sc, MPR_ERROR, "Unable to alloc read capacity " + mpr_dprint(sc, MPR_FAULT, "Unable to alloc read capacity " "buffer for EEDP support.\n"); xpt_free_path(ccb->ccb_h.path); xpt_free_ccb(ccb); @@ -3329,7 +3341,7 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) xpt_release_devq(done_ccb->ccb_h.path, /*count*/ 1, /*run_queue*/TRUE); } - + rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; /* @@ -3347,21 +3359,21 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) /* * Got the LUN in the target's LUN list. Fill it in with EEDP - * info. If the READ CAP 16 command had some SCSI error (common + * info. If the READ CAP 16 command had some SCSI error (common * if command is not supported), mark the lun as not supporting * EEDP and set the block size to 0. */ - if ((mprsas_get_ccbstatus(done_ccb) != CAM_REQ_CMP) || - (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { + if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) + || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { lun->eedp_formatted = FALSE; lun->eedp_block_size = 0; break; } if (rcap_buf->protect & 0x01) { - mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for target ID " - "%d is formatted for EEDP support.\n", - done_ccb->ccb_h.target_lun, + mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for " + "target ID %d is formatted for EEDP " + "support.\n", done_ccb->ccb_h.target_lun, done_ccb->ccb_h.target_id); lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf->length); @@ -3377,34 +3389,6 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) #endif /* (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ -void -mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, - struct mprsas_target *target, lun_id_t lun_id) -{ - union ccb *ccb; - path_id_t path_id; - - /* - * Set the INRESET flag for this target so that no I/O will be sent to - * the target until the reset has completed. If an I/O request does - * happen, the devq will be frozen. The CCB holds the path which is - * used to release the devq. The devq is released and the CCB is freed - * when the TM completes. - */ - ccb = xpt_alloc_ccb_nowait(); - if (ccb) { - path_id = cam_sim_path(sc->sassc->sim); - if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id, - target->tid, lun_id) != CAM_REQ_CMP) { - xpt_free_ccb(ccb); - } else { - tm->cm_ccb = ccb; - tm->cm_targ = target; - target->flags |= MPRSAS_TARGET_INRESET; - } - } -} - int mprsas_startup(struct mpr_softc *sc) { @@ -3505,33 +3489,3 @@ mprsas_check_id(struct mprsas_softc *sassc, int id) return (0); } - -void -mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) -{ - struct mprsas_softc *sassc; - struct mprsas_lun *lun, *lun_tmp; - struct mprsas_target *targ; - int i; - - sassc = sc->sassc; - /* - * The number of targets is based on IOC Facts, so free all of - * the allocated LUNs for each target and then the target buffer - * itself. - */ - for (i=0; i< maxtargets; i++) { - targ = &sassc->targets[i]; - SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { - free(lun, M_MPR); - } - } - free(sassc->targets, M_MPR); - - sassc->targets = malloc(sizeof(struct mprsas_target) * maxtargets, - M_MPR, M_WAITOK|M_ZERO); - if (!sassc->targets) { - panic("%s failed to alloc targets with error %d\n", - __func__, ENOMEM); - } -} diff --git a/sys/dev/mpr/mpr_sas.h b/sys/dev/mpr/mpr_sas.h index ebeed300c9fb..9d3116af29d0 100644 --- a/sys/dev/mpr/mpr_sas.h +++ b/sys/dev/mpr/mpr_sas.h @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -36,6 +35,7 @@ struct mprsas_lun { lun_id_t lun_id; uint8_t eedp_formatted; uint32_t eedp_block_size; + uint8_t stop_at_shutdown; }; struct mprsas_target { @@ -55,10 +55,11 @@ struct mprsas_target { #define MPRSAS_TARGET_INREMOVAL (1 << 3) #define MPR_TARGET_FLAGS_RAID_COMPONENT (1 << 4) #define MPR_TARGET_FLAGS_VOLUME (1 << 5) -#define MPR_TARGET_IS_SATA_SSD (1 << 6) #define MPRSAS_TARGET_INRECOVERY (MPRSAS_TARGET_INABORT | \ MPRSAS_TARGET_INRESET | MPRSAS_TARGET_INCHIPRESET) +#define MPRSAS_TARGET_ADD (1 << 29) +#define MPRSAS_TARGET_REMOVE (1 << 30) uint16_t tid; SLIST_HEAD(, mprsas_lun) luns; TAILQ_HEAD(, mpr_command) commands; @@ -81,8 +82,6 @@ struct mprsas_target { unsigned int logical_unit_resets; unsigned int target_resets; uint8_t scsi_req_desc_type; - uint8_t stop_at_shutdown; - uint8_t supports_SSU; }; struct mprsas_softc { @@ -93,6 +92,7 @@ struct mprsas_softc { #define MPRSAS_DISCOVERY_TIMEOUT_PENDING (1 << 2) #define MPRSAS_QUEUE_FROZEN (1 << 3) #define MPRSAS_SHUTDOWN (1 << 4) +#define MPRSAS_SCANTHREAD (1 << 5) u_int maxtargets; struct mprsas_target *targets; struct cam_devq *devq; @@ -103,6 +103,7 @@ struct mprsas_softc { struct mpr_event_handle *mprsas_eh; u_int startup_refcount; + u_int tm_count; struct proc *sysctl_proc; struct taskqueue *ev_tq; @@ -149,19 +150,6 @@ mprsas_set_lun(uint8_t *lun, u_int ccblun) return (0); } -static __inline void -mprsas_set_ccbstatus(union ccb *ccb, int status) -{ - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= status; -} - -static __inline int -mprsas_get_ccbstatus(union ccb *ccb) -{ - return (ccb->ccb_h.status & CAM_STATUS_MASK); -} - #define MPR_SET_SINGLE_LUN(req, lun) \ do { \ bzero((req)->LUN, 8); \ @@ -170,10 +158,11 @@ do { \ void mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ); void mprsas_discovery_end(struct mprsas_softc *sassc); -void mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, - struct mprsas_target *target, lun_id_t lun_id); void mprsas_startup_increment(struct mprsas_softc *sassc); void mprsas_startup_decrement(struct mprsas_softc *sassc); +void mprsas_release_simq_reinit(struct mprsas_softc *sassc); +struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); +void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); void mprsas_firmware_event_work(void *arg, int pending); int mprsas_check_id(struct mprsas_softc *sassc, int id); diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 7d6ef7070f7d..32e9b3a07804 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,13 +23,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT3 */ +/* Communications core for LSI MPT2 */ /* TODO Move headers to mprvar */ #include @@ -106,9 +105,7 @@ struct _ata_identify_device_data { u16 serial_number[10]; /* 10-19 */ u16 reserved2[7]; /* 20-26 */ u16 model_number[20]; /* 27-46*/ - u16 reserved3[170]; /* 47-216 */ - u16 rotational_speed; /* 217 */ - u16 reserved4[38]; /* 218-255 */ + u16 reserved3[209]; /* 47-255*/ }; static u32 event_count; static void mprsas_fw_work(struct mpr_softc *sc, @@ -119,9 +116,8 @@ static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate); static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo); -static void mprsas_ata_id_timeout(void *data); int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, - u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); + u64 *sas_address, u16 handle, u32 device_info); static int mprsas_volume_add(struct mpr_softc *sc, u16 handle); static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc); @@ -329,7 +325,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) return; } - mpr_dprint(sc, MPR_EVENT, "Sending FP action " + mpr_dprint(sc, MPR_INFO, "Sending FP action " "from " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST " ":\n"); @@ -354,9 +350,9 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) if (reply && (le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { - mpr_dprint(sc, MPR_ERROR, "%s: error " - "sending RaidActionPage; " - "iocstatus = 0x%x\n", __func__, + mpr_dprint(sc, MPR_INFO, "%s: error " + "sending RaidActionPage; iocstatus " + "= 0x%x\n", __func__, le16toh(reply->IOCStatus)); } @@ -364,7 +360,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) mpr_free_command(sc, cm); } skip_fp_send: - mpr_dprint(sc, MPR_EVENT, "Received " + mpr_dprint(sc, MPR_INFO, "Received " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason " "code %x:\n", element->ReasonCode); switch (element->ReasonCode) { @@ -425,6 +421,7 @@ skip_fp_send: break; targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT; mprsas_rescan_target(sc, targ); + break; case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: /* @@ -681,13 +678,14 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ struct mprsas_target *targ; Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t config_page; - uint64_t sas_address, parent_sas_address = 0; + uint64_t sas_address, sata_sas_address; + uint64_t parent_sas_address = 0; + u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); u32 device_info, parent_devinfo = 0; unsigned int id; - int ret = 1, error = 0, i; + int ret; + int error = 0; struct mprsas_lun *lun; - u8 is_SATA_SSD = 0; - struct mpr_command *cm; sassc = sc->sassc; mprsas_startup_increment(sassc); @@ -719,29 +717,26 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ } /* TODO Check proper endianess */ sas_address = config_page.SASAddress.High; - sas_address = (sas_address << 32) | config_page.SASAddress.Low; - mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n", - sas_address); + sas_address = (sas_address << 32) | + config_page.SASAddress.Low; - /* - * Always get SATA Identify information because this is used to - * determine if Start/Stop Unit should be sent to the drive when the - * system is shutdown. - */ - if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { - ret = mprsas_get_sas_address_for_sata_disk(sc, &sas_address, - handle, device_info, &is_SATA_SSD); - if (ret) { - mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type " - "(SSD or HDD) for SATA device with handle 0x%04x\n", - __func__, handle); - } else { - mpr_dprint(sc, MPR_INFO, "SAS Address from SATA " - "device = %jx\n", sas_address); - } - } + if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) + == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { + if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { + ret = mprsas_get_sas_address_for_sata_disk(sc, + &sata_sas_address, handle, device_info); + if (!ret) + id = mpr_mapping_get_sas_id(sc, + sata_sas_address, handle); + else + id = mpr_mapping_get_sas_id(sc, + sas_address, handle); + } else + id = mpr_mapping_get_sas_id(sc, sas_address, + handle); + } else + id = mpr_mapping_get_sas_id(sc, sas_address, handle); - id = mpr_mapping_get_sas_id(sc, sas_address, handle); if (id == MPR_MAP_BAD_ID) { printf("failure at %s:%d/%s()! Could not get ID for device " "with handle 0x%04x\n", __FILE__, __LINE__, __func__, @@ -755,7 +750,7 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ error = ENXIO; goto out; } - + mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; @@ -778,9 +773,6 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ targ->tid = id; targ->linkrate = (linkrate>>4); targ->flags = 0; - if (is_SATA_SSD) { - targ->flags = MPR_TARGET_IS_SATA_SSD; - } if (le16toh(config_page.Flags) & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) { targ->scsi_req_desc_type = @@ -800,12 +792,12 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ SLIST_INIT(&targ->luns); mpr_describe_devinfo(targ->devinfo, devstring, 80); - mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> " + mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "Found device <%s> <%s> " "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring, mpr_describe_table(mpr_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); if (targ->encl_level_valid) { - mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d " + mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "At enclosure level %d " "and connector name (%4s)\n", targ->encl_level, targ->connector_name); } @@ -815,57 +807,15 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ #endif mprsas_rescan_target(sc, targ); mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid); - - /* - * Check all commands to see if the SATA_ID_TIMEOUT flag has been set. - * If so, send a Target Reset TM to the target that was just created. - * An Abort Task TM should be used instead of a Target Reset, but that - * would be much more difficult because targets have not been fully - * discovered yet, and LUN's haven't been setup. So, just reset the - * target instead of the LUN. - */ - for (i = 1; i < sc->num_reqs; i++) { - cm = &sc->commands[i]; - if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { - targ->timeouts++; - cm->cm_state = MPR_CM_STATE_TIMEDOUT; - - if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { - mpr_dprint(sc, MPR_INFO, "%s: sending Target " - "Reset for stuck SATA identify command " - "(cm = %p)\n", __func__, cm); - targ->tm->cm_targ = targ; - mprsas_send_reset(sc, targ->tm, - MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); - } else { - mpr_dprint(sc, MPR_ERROR, "Failed to allocate " - "tm for Target Reset after SATA ID " - "command timed out (cm %p)\n", cm); - } - /* - * No need to check for more since the target is - * already being reset. - */ - break; - } - } out: - /* - * Free the commands that may not have been freed from the SATA ID call - */ - for (i = 1; i < sc->num_reqs; i++) { - cm = &sc->commands[i]; - if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { - mpr_free_command(sc, cm); - } - } mprsas_startup_decrement(sassc); return (error); + } int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, - u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD) + u64 *sas_address, u16 handle, u32 device_info) { Mpi2SataPassthroughReply_t mpi_reply; int i, rc, try_count; @@ -885,16 +835,7 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, ioc_status = le16toh(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; sas_status = mpi_reply.SASStatus; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - if (sc->spinup_wait_time > 0) { - mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds " - "after SATA ID error to wait for spinup\n", - sc->spinup_wait_time); - msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, - "mprid", sc->spinup_wait_time * hz); - } - } - } while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) && + } while ((rc == -EAGAIN || ioc_status || sas_status) && (try_count < 5)); if (rc == 0 && !ioc_status && !sas_status) { @@ -943,10 +884,6 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 | (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 | (u64)hash_address.wwid[7]; - if (ata_identify.rotational_speed == 1) { - *is_SATA_SSD = 1; - } - return 0; } @@ -986,29 +923,14 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = buffer; cm->cm_length = htole32(sz); - - /* - * Start a timeout counter specifically for the SATA ID command. This - * is used to fix a problem where the FW does not send a reply sometimes - * when a bad disk is in the topology. So, this is used to timeout the - * command so that processing can continue normally. - */ - mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID " - "command\n", __func__); - callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz, - mprsas_ata_id_timeout, cm); error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID " - "command\n", __func__); - callout_stop(&cm->cm_callout); - reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* * If the request returns an error then we need to do a diag * reset - */ + */ printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; @@ -1024,66 +946,11 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, goto out; } out: - /* - * If the SATA_ID_TIMEOUT flag has been set for this command, don't free - * it. The command will be freed after sending a target reset TM. If - * the command did timeout, use EWOULDBLOCK. - */ - if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) - mpr_free_command(sc, cm); - else if (error == 0) - error = EWOULDBLOCK; - free(buffer, M_MPR); + mpr_free_command(sc, cm); + free(buffer, M_MPR); return (error); } -static void -mprsas_ata_id_timeout(void *data) -{ - struct mpr_softc *sc; - struct mpr_command *cm; - - cm = (struct mpr_command *)data; - sc = cm->cm_sc; - mtx_assert(&sc->mpr_mtx, MA_OWNED); - - mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n", - __func__, cm, sc); - if ((callout_pending(&cm->cm_callout)) || - (!callout_active(&cm->cm_callout))) { - mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " - "out\n", __func__); - return; - } - callout_deactivate(&cm->cm_callout); - - /* - * Run the interrupt handler to make sure it's not pending. This - * isn't perfect because the command could have already completed - * and been re-used, though this is unlikely. - */ - mpr_intr_locked(sc); - if (cm->cm_state == MPR_CM_STATE_FREE) { - mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " - "out\n", __func__); - return; - } - - mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm); - - /* - * Send wakeup() to the sleeping thread that issued this ATA ID - * command. wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), - * and this will keep reinit() from being called. This way, an Abort - * Task TM can be issued so that the timed out command can be cleared. - * The Abort Task cannot be sent from here because the driver has not - * completed setting up targets. Instead, the command is flagged so - * that special handling will be used to send the abort. - */ - cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT; - wakeup(cm); -} - static int mprsas_volume_add(struct mpr_softc *sc, u16 handle) { @@ -1157,13 +1024,15 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) path_id_t pathid = cam_sim_path(sassc->sim); target_id_t targetid; struct mprsas_target *target; + struct mprsas_lun *lun; char path_str[64]; struct timeval cur_time, start_time; mpr_lock(sc); /* - * For each target, issue a StartStopUnit command to stop the device. + * For each LUN of each target, issue a StartStopUnit command to stop + * the device. */ sc->SSU_started = TRUE; sc->SSU_refcount = 0; @@ -1173,52 +1042,59 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) continue; } - ccb = xpt_alloc_ccb_nowait(); - if (ccb == NULL) { - mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB to stop " - "unit.\n"); - return; - } - - /* - * The stop_at_shutdown flag will be set if this device is - * a SATA direct-access end device. - */ - if (target->stop_at_shutdown) { - if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, - pathid, targetid, CAM_LUN_WILDCARD) != - CAM_REQ_CMP) { - mpr_dprint(sc, MPR_ERROR, "Unable to create " - "path to stop unit.\n"); - xpt_free_ccb(ccb); + SLIST_FOREACH(lun, &target->luns, lun_link) { + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + mpr_unlock(sc); + mpr_dprint(sc, MPR_FAULT, "Unable to alloc " + "CCB to stop unit.\n"); return; } - xpt_path_string(ccb->ccb_h.path, path_str, - sizeof(path_str)); - - mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s " - "handle %d\n", path_str, target->handle); /* - * Issue a START STOP UNIT command for the target. - * Increment the SSU counter to be used to count the - * number of required replies. + * The stop_at_shutdown flag will be set if this LUN is + * a SATA direct-access end device. */ - mpr_dprint(sc, MPR_INFO, "Incrementing SSU count\n"); - sc->SSU_refcount++; - ccb->ccb_h.target_id = - xpt_path_target_id(ccb->ccb_h.path); - ccb->ccb_h.ppriv_ptr1 = sassc; - scsi_start_stop(&ccb->csio, - /*retries*/0, - mprsas_stop_unit_done, - MSG_SIMPLE_Q_TAG, - /*start*/FALSE, - /*load/eject*/0, - /*immediate*/FALSE, - MPR_SENSE_LEN, - /*timeout*/10000); - xpt_action(ccb); + if (lun->stop_at_shutdown) { + if (xpt_create_path(&ccb->ccb_h.path, + xpt_periph, pathid, targetid, + lun->lun_id) != CAM_REQ_CMP) { + mpr_dprint(sc, MPR_FAULT, "Unable to " + "create LUN path to stop unit.\n"); + xpt_free_ccb(ccb); + mpr_unlock(sc); + return; + } + xpt_path_string(ccb->ccb_h.path, path_str, + sizeof(path_str)); + + mpr_dprint(sc, MPR_INFO, "Sending StopUnit: " + "path %s handle %d\n", path_str, + target->handle); + + /* + * Issue a START STOP UNIT command for the LUN. + * Increment the SSU counter to be used to + * count the number of required replies. + */ + mpr_dprint(sc, MPR_INFO, "Incrementing SSU " + "count\n"); + sc->SSU_refcount++; + ccb->ccb_h.target_id = + xpt_path_target_id(ccb->ccb_h.path); + ccb->ccb_h.target_lun = lun->lun_id; + ccb->ccb_h.ppriv_ptr1 = sassc; + scsi_start_stop(&ccb->csio, + /*retries*/0, + mprsas_stop_unit_done, + MSG_SIMPLE_Q_TAG, + /*start*/FALSE, + /*load/eject*/0, + /*immediate*/FALSE, + MPR_SENSE_LEN, + /*timeout*/10000); + xpt_action(ccb); + } } } @@ -1226,7 +1102,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) /* * Wait until all of the SSU commands have completed or time has - * expired (60 seconds). Pause for 100ms each time through. If any + * expired (60 seconds). pause for 100ms each time through. If any * command times out, the target will be reset in the SCSI command * timeout routine. */ @@ -1236,7 +1112,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) getmicrotime(&cur_time); if ((cur_time.tv_sec - start_time.tv_sec) > 60) { - mpr_dprint(sc, MPR_ERROR, "Time has expired waiting " + mpr_dprint(sc, MPR_FAULT, "Time has expired waiting " "for SSU commands to complete.\n"); break; } @@ -1286,8 +1162,6 @@ mprsas_ir_shutdown(struct mpr_softc *sc) unsigned int id, found_volume = 0; struct mpr_command *cm; Mpi2RaidActionRequest_t *action; - target_id_t targetid; - struct mprsas_target *target; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); @@ -1340,47 +1214,5 @@ mprsas_ir_shutdown(struct mpr_softc *sc) mpr_free_command(sc, cm); out: - /* - * All of the targets must have the correct value set for - * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable. - * - * The possible values for the 'enable_ssu' variable are: - * 0: disable to SSD and HDD - * 1: disable only to HDD (default) - * 2: disable only to SSD - * 3: enable to SSD and HDD - * anything else will default to 1. - */ - for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { - target = &sc->sassc->targets[targetid]; - if (target->handle == 0x0) { - continue; - } - - if (target->supports_SSU) { - switch (sc->enable_ssu) { - case MPR_SSU_DISABLE_SSD_DISABLE_HDD: - target->stop_at_shutdown = FALSE; - break; - case MPR_SSU_DISABLE_SSD_ENABLE_HDD: - target->stop_at_shutdown = TRUE; - if (target->flags & MPR_TARGET_IS_SATA_SSD) { - target->stop_at_shutdown = FALSE; - } - break; - case MPR_SSU_ENABLE_SSD_ENABLE_HDD: - target->stop_at_shutdown = TRUE; - break; - case MPR_SSU_ENABLE_SSD_DISABLE_HDD: - default: - target->stop_at_shutdown = TRUE; - if ((target->flags & - MPR_TARGET_IS_SATA_SSD) == 0) { - target->stop_at_shutdown = FALSE; - } - break; - } - } - } mprsas_SSU_to_SATA_devices(sc); } diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 37d946718b23..60680f5288a3 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_user.c @@ -27,11 +27,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface + * LSI MPT-Fusion Host Adapter FreeBSD userland interface */ /*- - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,7 +54,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * LSI MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -91,7 +90,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include @@ -285,7 +284,8 @@ mpr_user_read_cfg_header(struct mpr_softc *sc, static int mpr_user_read_cfg_page(struct mpr_softc *sc, - struct mpr_cfg_page_req *page_req, void *buf) + struct mpr_cfg_page_req *page_req, + void *buf) { MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; struct mpr_config_params params; @@ -328,10 +328,6 @@ mpr_user_read_extcfg_header(struct mpr_softc *sc, hdr->PageNumber = ext_page_req->header.PageNumber; hdr->ExtPageType = ext_page_req->header.ExtPageType; params.page_address = le32toh(ext_page_req->page_address); - params.buffer = NULL; - params.length = 0; - params.callback = NULL; - if ((error = mpr_read_config_page(sc, ¶ms)) != 0) { /* * Leave the request. Without resetting the chip, it's @@ -369,8 +365,8 @@ mpr_user_read_extcfg_page(struct mpr_softc *sc, params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; params.page_address = le32toh(ext_page_req->page_address); hdr->PageVersion = reqhdr->PageVersion; - hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; hdr->PageNumber = reqhdr->PageNumber; + hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; hdr->ExtPageType = reqhdr->ExtPageType; hdr->ExtPageLength = reqhdr->ExtPageLength; params.buffer = buf; @@ -545,8 +541,6 @@ mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd) req->ImageOffset = 0; req->ImageSize = cmd->len; - cm->cm_flags |= MPR_CM_FLAGS_DATAIN; - return (mpr_push_ieee_sge(cm, &req->SGL, 0)); } @@ -840,22 +834,11 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) task->TaskMID = cm->cm_desc.Default.SMID; cm->cm_data = NULL; - cm->cm_desc.HighPriority.RequestFlags = - MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; + cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = NULL; cm->cm_complete_data = NULL; - targ = mprsas_find_target_by_handle(sc->sassc, 0, - task->DevHandle); - if (targ == NULL) { - mpr_dprint(sc, MPR_INFO, - "%s %d : invalid handle for requested TM 0x%x \n", - __func__, __LINE__, task->DevHandle); - err = 1; - } else { - mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); - err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); - } + err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); if (err != 0) { err = EIO; @@ -1046,7 +1029,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) dir = BUS_DMASYNC_POSTREAD; else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT) - dir = BUS_DMASYNC_POSTWRITE; + dir = BUS_DMASYNC_POSTWRITE;; bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); @@ -1368,8 +1351,8 @@ done: } static int -mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, - uint32_t *return_code) +mpr_diag_register(struct mpr_softc *sc, + mpr_fw_diag_register_t *diag_register, uint32_t *return_code) { mpr_fw_diagnostic_buffer_t *pBuffer; uint8_t extended_type, buffer_type, i; diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index acac44c5baec..9752dcd35f6f 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -1,7 +1,6 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2011-2014 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,15 +24,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD - * * $FreeBSD$ */ #ifndef _MPRVAR_H #define _MPRVAR_H -#define MPR_DRIVER_VERSION "09.255.01.00-fbsd" +#define MPR_DRIVER_VERSION "05.255.05.00-fbsd" #define MPR_DB_MAX_WAIT 2500 @@ -50,19 +47,16 @@ #define MPR_FUNCTRACE(sc) \ mpr_dprint((sc), MPR_TRACE, "%s\n", __func__) -#define CAN_SLEEP 1 -#define NO_SLEEP 0 +#define CAN_SLEEP 1 +#define NO_SLEEP 0 #define MPR_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */ -#define MPR_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */ #define IFAULT_IOP_OVER_TEMP_THRESHOLD_EXCEEDED 0x2810 #define MPR_SCSI_RI_INVALID_FRAME (0x00000002) #define MPR_STRING_LENGTH 64 -#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */ - #include /* @@ -219,14 +213,13 @@ struct mpr_command { #define MPR_CM_FLAGS_CHAIN_FAILED (1 << 8) #define MPR_CM_FLAGS_ERROR_MASK MPR_CM_FLAGS_CHAIN_FAILED #define MPR_CM_FLAGS_USE_CCB (1 << 9) -#define MPR_CM_FLAGS_SATA_ID_TIMEOUT (1 << 10) u_int cm_state; #define MPR_CM_STATE_FREE 0 #define MPR_CM_STATE_BUSY 1 #define MPR_CM_STATE_TIMEDOUT 2 bus_dmamap_t cm_dmamap; struct scsi_sense_data *cm_sense; - TAILQ_HEAD(, mpr_chain) cm_chain_list; + TAILQ_HEAD(, mpr_chain) cm_chain_list; uint32_t cm_req_busaddr; uint32_t cm_sense_busaddr; struct callout cm_callout; @@ -263,8 +256,6 @@ struct mpr_softc { int chain_free; int max_chains; int chain_free_lowwater; - u_int enable_ssu; - int spinup_wait_time; #if __FreeBSD_version >= 900030 uint64_t chain_alloc_fail; #endif @@ -279,7 +270,7 @@ struct mpr_softc { char tmp_string[MPR_STRING_LENGTH]; TAILQ_HEAD(, mpr_command) req_list; TAILQ_HEAD(, mpr_command) high_priority_req_list; - TAILQ_HEAD(, mpr_chain) chain_list; + TAILQ_HEAD(, mpr_chain) chain_list; TAILQ_HEAD(, mpr_command) tm_list; int replypostindex; int replyfreeindex; @@ -300,7 +291,7 @@ struct mpr_softc { uint8_t event_mask[16]; TAILQ_HEAD(, mpr_event_handle) event_list; - struct mpr_event_handle *mpr_log_eh; + struct mpr_event_handle *mpr_log_eh; struct mtx mpr_mtx; struct intr_config_hook mpr_ich; @@ -574,11 +565,6 @@ mpr_unlock(struct mpr_softc *sc) #define MPR_MAPPING (1 << 9) /* Trace device mappings */ #define MPR_TRACE (1 << 10) /* Function-by-function trace */ -#define MPR_SSU_DISABLE_SSD_DISABLE_HDD 0 -#define MPR_SSU_ENABLE_SSD_DISABLE_HDD 1 -#define MPR_SSU_DISABLE_SSD_ENABLE_HDD 2 -#define MPR_SSU_ENABLE_SSD_ENABLE_HDD 3 - #define mpr_printf(sc, args...) \ device_printf((sc)->mpr_dev, ##args) @@ -614,6 +600,9 @@ do { \ #define MPR_EVENTFIELD(sc, facts, attr, fmt) \ mpr_dprint_field((sc), MPR_EVENT, #attr ": " #fmt "\n", (facts)->attr) +#define CAN_SLEEP 1 +#define NO_SLEEP 0 + static __inline void mpr_from_u64(uint64_t data, U64 *mpr) { @@ -624,6 +613,7 @@ mpr_from_u64(uint64_t data, U64 *mpr) static __inline uint64_t mpr_to_u64(U64 *data) { + return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low)); } @@ -737,12 +727,6 @@ void mprsas_prepare_volume_remove(struct mprsas_softc *sassc, int mprsas_startup(struct mpr_softc *sc); struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *, int, uint16_t); -void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets); -struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); -void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); -void mprsas_release_simq_reinit(struct mprsas_softc *sassc); -int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, - uint8_t type); SYSCTL_DECL(_hw_mpr); From 05c1c03afa71dc36b5fb0718cbb68399a0e0e9a7 Mon Sep 17 00:00:00 2001 From: slm Date: Thu, 28 May 2015 18:24:22 +0000 Subject: [PATCH 35/65] The wrong commit message was given with r283632. This is the correct message. - Updated all files with 2015 Avago copyright, and updated LSI's copyright dates. - Changed all of the PCI device strings from LSI to Avago Technologies (LSI). - Added a sysctl variable to control how StartStopUnit behavior works. User can select to spin down disks based on if disk is SSD or HDD. - Inquiry data is required to tell if a disk will support SSU at shutdown or not. Due to the addition of mpssas_async, which gets Advanced Info but not Inquiry data, the setting of supports_SSU was moved to the mpssas_scsiio_complete function, which snoops for any Inquiry commands. And, since disks are shutdown as a target and not a LUN, this process was simplified by basing it on targets and not LUNs. - Added a sysctl variable that sets the amount of time to retry after sending a failed SATA ID command. This helps with some bad disks and large disks that require a lot of time to spin up. Part of this change was to add a callout to handle timeouts with the SATA ID command. The callout function is called mpssas_ata_id_timeout(). (Fixes PR 191348) - Changed the way resets work by allowing I/O to continue to devices that are not currently under a reset condition. This uses devq's instead of simq's and makes use of the MPSSAS_TARGET_INRESET flag. This change also adds a function called mpssas_prepare_tm(). - Some changes were made to reduce code duplication when getting a SAS address for a SATA disk. - Fixed some formatting and whitespace. - Bump version of mps driver to 9.255.01.00-fbsd PR: 191348 Reviewed by: ken, scottl Approved by: ken, scottl MFC after: 1 week --- sys/dev/mpr/mpi/mpi2.h | 8 +- sys/dev/mpr/mpi/mpi2_cnfg.h | 8 +- sys/dev/mpr/mpi/mpi2_hbd.h | 8 +- sys/dev/mpr/mpi/mpi2_history.txt | 8 +- sys/dev/mpr/mpi/mpi2_init.h | 8 +- sys/dev/mpr/mpi/mpi2_ioc.h | 8 +- sys/dev/mpr/mpi/mpi2_ra.h | 8 +- sys/dev/mpr/mpi/mpi2_raid.h | 8 +- sys/dev/mpr/mpi/mpi2_sas.h | 8 +- sys/dev/mpr/mpi/mpi2_targ.h | 8 +- sys/dev/mpr/mpi/mpi2_tool.h | 8 +- sys/dev/mpr/mpi/mpi2_type.h | 8 +- sys/dev/mpr/mpr.c | 90 +++--- sys/dev/mpr/mpr_config.c | 5 +- sys/dev/mpr/mpr_ioctl.h | 7 +- sys/dev/mpr/mpr_mapping.c | 72 +++-- sys/dev/mpr/mpr_mapping.h | 10 +- sys/dev/mpr/mpr_pci.c | 14 +- sys/dev/mpr/mpr_sas.c | 476 +++++++++++++++++-------------- sys/dev/mpr/mpr_sas.h | 31 +- sys/dev/mpr/mpr_sas_lsi.c | 360 ++++++++++++++++------- sys/dev/mpr/mpr_user.c | 41 ++- sys/dev/mpr/mprvar.h | 38 ++- 23 files changed, 767 insertions(+), 473 deletions(-) diff --git a/sys/dev/mpr/mpi/mpi2.h b/sys/dev/mpr/mpi/mpi2.h index 10f17aba067e..42fdec20c503 100644 --- a/sys/dev/mpr/mpi/mpi2.h +++ b/sys/dev/mpr/mpi/mpi2.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2.h diff --git a/sys/dev/mpr/mpi/mpi2_cnfg.h b/sys/dev/mpr/mpi/mpi2_cnfg.h index d82750f80913..3b0eb637a9e2 100644 --- a/sys/dev/mpr/mpi/mpi2_cnfg.h +++ b/sys/dev/mpr/mpi/mpi2_cnfg.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_cnfg.h diff --git a/sys/dev/mpr/mpi/mpi2_hbd.h b/sys/dev/mpr/mpi/mpi2_hbd.h index d0cc09f905a0..520407b39948 100644 --- a/sys/dev/mpr/mpi/mpi2_hbd.h +++ b/sys/dev/mpr/mpi/mpi2_hbd.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2009-2011 LSI Corporation. + * Copyright (c) 2009-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_hbd.h diff --git a/sys/dev/mpr/mpi/mpi2_history.txt b/sys/dev/mpr/mpi/mpi2_history.txt index 296b75b87859..9fca7966f65a 100644 --- a/sys/dev/mpr/mpi/mpi2_history.txt +++ b/sys/dev/mpr/mpi/mpi2_history.txt @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,7 +27,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -35,7 +36,8 @@ Fusion-MPT MPI 2.0 / 2.5 Header File Change History ============================== - Copyright (c) 2000-2013 LSI Corporation. + Copyright (c) 2000-2015 LSI Corporation. + Copyright (c) 2013-2015 Avago Technologies --------------------------------------- Header Set Release Version: 02.00.33 diff --git a/sys/dev/mpr/mpi/mpi2_init.h b/sys/dev/mpr/mpi/mpi2_init.h index 62b0cfed120a..5f475c0e26ba 100644 --- a/sys/dev/mpr/mpi/mpi2_init.h +++ b/sys/dev/mpr/mpi/mpi2_init.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_init.h diff --git a/sys/dev/mpr/mpi/mpi2_ioc.h b/sys/dev/mpr/mpi/mpi2_ioc.h index 38a46f5280bc..54f39a5adc71 100644 --- a/sys/dev/mpr/mpi/mpi2_ioc.h +++ b/sys/dev/mpr/mpi/mpi2_ioc.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_ioc.h diff --git a/sys/dev/mpr/mpi/mpi2_ra.h b/sys/dev/mpr/mpi/mpi2_ra.h index 76db06b71b98..02304aaa002e 100644 --- a/sys/dev/mpr/mpi/mpi2_ra.h +++ b/sys/dev/mpr/mpi/mpi2_ra.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2009 LSI Corporation. + * Copyright (c) 2012-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_ra.h diff --git a/sys/dev/mpr/mpi/mpi2_raid.h b/sys/dev/mpr/mpi/mpi2_raid.h index c6bb59864a3c..52ebf07ee096 100644 --- a/sys/dev/mpr/mpi/mpi2_raid.h +++ b/sys/dev/mpr/mpi/mpi2_raid.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_raid.h diff --git a/sys/dev/mpr/mpi/mpi2_sas.h b/sys/dev/mpr/mpi/mpi2_sas.h index 2a107f1e1617..7cae2c3d4adf 100644 --- a/sys/dev/mpr/mpi/mpi2_sas.h +++ b/sys/dev/mpr/mpi/mpi2_sas.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_sas.h diff --git a/sys/dev/mpr/mpi/mpi2_targ.h b/sys/dev/mpr/mpi/mpi2_targ.h index 506e64f6370c..85b5ac562610 100644 --- a/sys/dev/mpr/mpi/mpi2_targ.h +++ b/sys/dev/mpr/mpi/mpi2_targ.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_targ.h diff --git a/sys/dev/mpr/mpi/mpi2_tool.h b/sys/dev/mpr/mpi/mpi2_tool.h index 94542cc7959b..59917c0077f5 100644 --- a/sys/dev/mpr/mpi/mpi2_tool.h +++ b/sys/dev/mpr/mpi/mpi2_tool.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_tool.h diff --git a/sys/dev/mpr/mpi/mpi2_type.h b/sys/dev/mpr/mpi/mpi2_type.h index da3aefb968f4..b063683263d0 100644 --- a/sys/dev/mpr/mpi/mpi2_type.h +++ b/sys/dev/mpr/mpi/mpi2_type.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2007 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_type.h diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index d3fb9a0682b8..07e73c54e8be 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2012-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,12 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #include @@ -72,7 +75,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include static int mpr_diag_reset(struct mpr_softc *sc, int sleep_flag); static int mpr_init_queues(struct mpr_softc *sc); @@ -352,11 +354,9 @@ mpr_transition_operational(struct mpr_softc *sc) static int mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) { - int error, i; + int error; Mpi2IOCFactsReply_t saved_facts; uint8_t saved_mode, reallocating; - struct mprsas_lun *lun, *lun_tmp; - struct mprsas_target *targ; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); @@ -513,27 +513,7 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) */ if (reallocating) { mpr_iocfacts_free(sc); - - /* - * The number of targets is based on IOC Facts, so free all of - * the allocated LUNs for each target and then the target buffer - * itself. - */ - for (i=0; i< saved_facts.MaxTargets; i++) { - targ = &sc->sassc->targets[i]; - SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, - lun_tmp) { - free(lun, M_MPR); - } - } - free(sc->sassc->targets, M_MPR); - - sc->sassc->targets = malloc(sizeof(struct mprsas_target) * - sc->facts->MaxTargets, M_MPR, M_WAITOK|M_ZERO); - if (!sc->sassc->targets) { - panic("%s failed to alloc targets with error %d\n", - __func__, ENOMEM); - } + mprsas_realloc_targets(sc, saved_facts.MaxTargets); } /* @@ -775,7 +755,7 @@ mpr_reinit(struct mpr_softc *sc) /* the end of discovery will release the simq, so we're done. */ mpr_dprint(sc, MPR_INFO, "%s finished sc %p post %u free %u\n", __func__, sc, sc->replypostindex, sc->replyfreeindex); - mprsas_release_simq_reinit(sassc); + mprsas_release_simq_reinit(sassc); return 0; } @@ -816,7 +796,8 @@ mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag) * 0.5 milisecond */ if (mtx_owned(&sc->mpr_mtx) && sleep_flag == CAN_SLEEP) - msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", hz/1000); + msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", + hz/1000); else if (sleep_flag == CAN_SLEEP) pause("mprdba", hz/1000); else @@ -982,7 +963,7 @@ mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm) reply_descriptor rd; MPR_FUNCTRACE(sc); - mpr_dprint(sc, MPR_TRACE, "%s SMID %u cm %p ccb %p\n", __func__, + mpr_dprint(sc, MPR_TRACE, "SMID %u cm %p ccb %p\n", cm->cm_desc.Default.SMID, cm, cm->cm_ccb); if (sc->mpr_flags & MPR_FLAGS_ATTACH_DONE && !(sc->mpr_flags & @@ -1372,6 +1353,8 @@ mpr_get_tunables(struct mpr_softc *sc) sc->disable_msix = 0; sc->disable_msi = 0; sc->max_chains = MPR_CHAIN_FRAMES; + sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD; + sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; /* * Grab the global variables. @@ -1380,6 +1363,8 @@ mpr_get_tunables(struct mpr_softc *sc) TUNABLE_INT_FETCH("hw.mpr.disable_msix", &sc->disable_msix); TUNABLE_INT_FETCH("hw.mpr.disable_msi", &sc->disable_msi); TUNABLE_INT_FETCH("hw.mpr.max_chains", &sc->max_chains); + TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu); + TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time); /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level", @@ -1402,6 +1387,14 @@ mpr_get_tunables(struct mpr_softc *sc) snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.exclude_ids", device_get_unit(sc->mpr_dev)); TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids)); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.enable_ssu", + device_get_unit(sc->mpr_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time", + device_get_unit(sc->mpr_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); } static void @@ -1474,11 +1467,20 @@ mpr_setup_sysctl(struct mpr_softc *sc) OID_AUTO, "max_chains", CTLFLAG_RD, &sc->max_chains, 0,"maximum chain frames that will be allocated"); + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "enable_ssu", CTLFLAG_RW, &sc->enable_ssu, 0, + "enable SSU to SATA SSD/HDD at shutdown"); + #if __FreeBSD_version >= 900030 SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "chain_alloc_fail", CTLFLAG_RD, &sc->chain_alloc_fail, "chain allocation failures"); #endif //FreeBSD_version >= 900030 + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "spinup_wait_time", CTLFLAG_RD, + &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for " + "spinup after SATA ID error"); } int @@ -2096,7 +2098,7 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle, (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) error = ENXIO; - if(reply) + if (reply) mpr_print_event(sc, reply); mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error); @@ -2163,8 +2165,8 @@ mpr_deregister_events(struct mpr_softc *sc, struct mpr_event_handle *handle) * Add a chain element as the next SGE for the specified command. * Reset cm_sge and cm_sgesize to indicate all the available space. Chains are * only required for IEEE commands. Therefore there is no code for commands - * that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands shouldn't - * be requesting chains). + * that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands + * shouldn't be requesting chains). */ static int mpr_add_chain(struct mpr_command *cm, int segsleft) @@ -2246,9 +2248,9 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) /* * Add one scatter-gather element to the scatter-gather list for a command. - * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the next - * SGE to fill in, respectively. In Gen3, the MPI SGL does not have a chain, - * so don't consider any chain additions. + * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the + * next SGE to fill in, respectively. In Gen3, the MPI SGL does not have a + * chain, so don't consider any chain additions. */ int mpr_push_sge(struct mpr_command *cm, MPI2_SGE_SIMPLE64 *sge, size_t len, @@ -2660,7 +2662,7 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) } } - if(error) { + if (error) { mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__); rc = mpr_reinit(sc); mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? @@ -2717,9 +2719,12 @@ mpr_read_config_page(struct mpr_softc *sc, struct mpr_config_params *params) cm->cm_data = params->buffer; cm->cm_length = params->length; - cm->cm_sge = &req->PageBufferSGE; - cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); - cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; + if (cm->cm_data != NULL) { + cm->cm_sge = &req->PageBufferSGE; + cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); + cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; + } else + cm->cm_sge = NULL; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_complete_data = params; @@ -2776,9 +2781,12 @@ mpr_config_complete(struct mpr_softc *sc, struct mpr_command *cm) goto done; } params->status = reply->IOCStatus; - if (params->hdr.Ext.ExtPageType != 0) { + if (params->hdr.Struct.PageType == MPI2_CONFIG_PAGETYPE_EXTENDED) { params->hdr.Ext.ExtPageType = reply->ExtPageType; params->hdr.Ext.ExtPageLength = reply->ExtPageLength; + params->hdr.Ext.PageType = reply->Header.PageType; + params->hdr.Ext.PageNumber = reply->Header.PageNumber; + params->hdr.Ext.PageVersion = reply->Header.PageVersion; } else { params->hdr.Struct.PageType = reply->Header.PageType; params->hdr.Struct.PageNumber = reply->Header.PageNumber; diff --git a/sys/dev/mpr/mpr_config.c b/sys/dev/mpr/mpr_config.c index 125451608dee..c0ea3d5ffb08 100644 --- a/sys/dev/mpr/mpr_config.c +++ b/sys/dev/mpr/mpr_config.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include diff --git a/sys/dev/mpr/mpr_ioctl.h b/sys/dev/mpr/mpr_ioctl.h index 5ec482f311b0..aa1a4cbf7697 100644 --- a/sys/dev/mpr/mpr_ioctl.h +++ b/sys/dev/mpr/mpr_ioctl.h @@ -27,12 +27,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD userland interface + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface * * $FreeBSD$ */ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,7 +57,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ diff --git a/sys/dev/mpr/mpr_mapping.c b/sys/dev/mpr/mpr_mapping.c index 7f0fc00a9c52..110e6a3b943f 100644 --- a/sys/dev/mpr/mpr_mapping.c +++ b/sys/dev/mpr/mpr_mapping.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include @@ -326,11 +327,13 @@ _mapping_get_high_missing_mt_idx(struct mpr_softc *sc) { u32 map_idx, high_idx = MPR_ENCTABLE_BAD_IDX; u8 high_missing_count = 0; - u32 start_idx, end_idx, start_idx_ir = 0, end_idx_ir; + u32 start_idx, end_idx, start_idx_ir, end_idx_ir; struct dev_mapping_table *mt_entry; u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); start_idx = 0; + start_idx_ir = 0; + end_idx_ir = 0; end_idx = sc->max_devices; if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) start_idx = 1; @@ -887,14 +890,14 @@ _mapping_get_dev_info(struct mpr_softc *sc, u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; - u8 entry, enc_idx, phy_idx; + u8 entry, enc_idx, phy_idx, sata_end_device; u32 map_idx, index, device_info; struct _map_phy_change *phy_change, *tmp_phy_change; uint64_t sas_address; struct enc_mapping_table *et_entry; struct dev_mapping_table *mt_entry; u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED; - int rc; + int rc = 1; for (entry = 0; entry < topo_change->num_entries; entry++) { phy_change = &topo_change->phy_details[entry]; @@ -908,41 +911,36 @@ _mapping_get_dev_info(struct mpr_softc *sc, continue; } + /* + * Always get SATA Identify information because this is used + * to determine if Start/Stop Unit should be sent to the drive + * when the system is shutdown. + */ device_info = le32toh(sas_device_pg0.DeviceInfo); - if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == - MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { - if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && - (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { - rc = mprsas_get_sas_address_for_sata_disk(sc, - &sas_address, phy_change->dev_handle, - device_info); - if (rc) { - printf("%s: failed to compute the " - "hashed SAS Address for SATA " - "device with handle 0x%04x\n", - __func__, phy_change->dev_handle); - sas_address = - sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; - } + sas_address = sas_device_pg0.SASAddress.High; + sas_address = (sas_address << 32) | + sas_device_pg0.SASAddress.Low; + sata_end_device = 0; + if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && + (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { + sata_end_device = 1; + rc = mprsas_get_sas_address_for_sata_disk(sc, + &sas_address, phy_change->dev_handle, device_info, + &phy_change->is_SATA_SSD); + if (rc) { + mpr_dprint(sc, MPR_ERROR, "%s: failed to get " + "disk type (SSD or HDD) and SAS Address " + "for SATA device with handle 0x%04x\n", + __func__, phy_change->dev_handle); + } else { mpr_dprint(sc, MPR_INFO, "SAS Address for SATA " "device = %jx\n", sas_address); - } else { - sas_address = - sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; } - } else { - sas_address = sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; } + phy_change->physical_id = sas_address; phy_change->slot = le16toh(sas_device_pg0.Slot); - phy_change->device_info = - le32toh(sas_device_pg0.DeviceInfo); + phy_change->device_info = le32toh(sas_device_pg0.DeviceInfo); if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { @@ -950,10 +948,10 @@ _mapping_get_dev_info(struct mpr_softc *sc, topo_change->enc_handle); if (enc_idx == MPR_ENCTABLE_BAD_IDX) { phy_change->is_processed = 1; - printf("%s: failed to add the device with " - "handle 0x%04x because the enclosure is " - "not in the mapping table\n", __func__, - phy_change->dev_handle); + mpr_dprint(sc, MPR_MAPPING, "%s: failed to add " + "the device with handle 0x%04x because the " + "enclosure is not in the mapping table\n", + __func__, phy_change->dev_handle); continue; } if (!((phy_change->device_info & diff --git a/sys/dev/mpr/mpr_mapping.h b/sys/dev/mpr/mpr_mapping.h index 3250c424e2a4..c00a3b795122 100644 --- a/sys/dev/mpr/mpr_mapping.h +++ b/sys/dev/mpr/mpr_mapping.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -38,6 +39,7 @@ * @dev_handle: device handle for the device pointed by this entry * @slot: slot ID * @is_processed: Flag to indicate whether this entry is processed or not + * @is_SATA_SSD: 1 if this is a SATA device AND an SSD, 0 otherwise */ struct _map_phy_change { uint64_t physical_id; @@ -46,6 +48,8 @@ struct _map_phy_change { uint16_t slot; uint8_t reason; uint8_t is_processed; + uint8_t is_SATA_SSD; + uint8_t reserved; }; /** @@ -66,6 +70,6 @@ struct _map_topology_change { extern int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *ioc, - u64 *sas_address, u16 handle, u32 device_info); + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); #endif diff --git a/sys/dev/mpr/mpr_pci.c b/sys/dev/mpr/mpr_pci.c index e19f33adceb4..7430eac03b3a 100644 --- a/sys/dev/mpr/mpr_pci.c +++ b/sys/dev/mpr/mpr_pci.c @@ -27,7 +27,7 @@ #include __FBSDID("$FreeBSD$"); -/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */ +/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT3 controllers */ /* TODO Move headers to mprvar */ #include @@ -99,17 +99,17 @@ struct mpr_ident { const char *desc; } mpr_identifiers[] = { { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, - 0xffff, 0xffff, 0, "LSI SAS3004" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3004" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008, - 0xffff, 0xffff, 0, "LSI SAS3008" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3008" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1, - 0xffff, 0xffff, 0, "LSI SAS3108_1" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_1" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2, - 0xffff, 0xffff, 0, "LSI SAS3108_2" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_2" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5, - 0xffff, 0xffff, 0, "LSI SAS3108_5" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, - 0xffff, 0xffff, 0, "LSI SAS3108_6" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" }, { 0, 0, 0, 0, 0, NULL } }; diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index 32c3a4633a1f..eac336068295 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,12 +24,15 @@ * 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. + * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #include @@ -122,14 +126,10 @@ static void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); static void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); static void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *); -static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, +static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, struct mpr_command *cm); -static int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, - uint8_t type); static void mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); -static void mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, - struct ccb_getdev *cgd); #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, @@ -142,13 +142,12 @@ static void mprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm); #if __FreeBSD_version >= 900026 -static void -mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); +static void mprsas_smpio_complete(struct mpr_softc *sc, + struct mpr_command *cm); static void mprsas_send_smpcmd(struct mprsas_softc *sassc, - union ccb *ccb, uint64_t sasaddr); -static void -mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); -#endif + union ccb *ccb, uint64_t sasaddr); +static void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); +#endif //FreeBSD_version >= 900026 struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, @@ -230,7 +229,7 @@ mprsas_startup_decrement(struct mprsas_softc *sassc) } } -/* LSI's firmware requires us to stop sending commands when we're doing task +/* The firmware requires us to stop sending commands when we're doing task * management, so refcount the TMs and keep the simq frozen when any are in * use. */ @@ -241,35 +240,31 @@ mprsas_alloc_tm(struct mpr_softc *sc) MPR_FUNCTRACE(sc); tm = mpr_alloc_high_priority_command(sc); - if (tm != NULL) { - if (sc->sassc->tm_count++ == 0) { - mpr_dprint(sc, MPR_RECOVERY, - "%s freezing simq\n", __func__); - xpt_freeze_simq(sc->sassc->sim, 1); - } - mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); - } return tm; } void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) { - mpr_dprint(sc, MPR_TRACE, "%s", __func__); + MPR_FUNCTRACE(sc); if (tm == NULL) return; - /* if there are no TMs in use, we can release the simq. We use our - * own refcount so that it's easier for a diag reset to cleanup and - * release the simq. + /* + * For TM's the devq is frozen for the device. Unfreeze it here and + * free the resources used for freezing the devq. Must clear the + * INRESET flag as well or scsi I/O will not work. */ - if (--sc->sassc->tm_count == 0) { - mpr_dprint(sc, MPR_RECOVERY, "%s releasing simq\n", __func__); - xpt_release_simq(sc->sassc->sim, 1); + if (tm->cm_targ != NULL) { + tm->cm_targ->flags &= ~MPRSAS_TARGET_INRESET; + } + if (tm->cm_ccb) { + mpr_dprint(sc, MPR_INFO, "Unfreezing devq for target ID %d\n", + tm->cm_targ->tid); + xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); + xpt_free_path(tm->cm_ccb->ccb_h.path); + xpt_free_ccb(tm->cm_ccb); } - mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); mpr_free_high_priority_command(sc, tm); } @@ -298,8 +293,8 @@ mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ) return; } - if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, - targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; @@ -473,11 +468,16 @@ mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_volume; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mpr_map_command(sc, cm); } /* - * The MPT2 firmware performs debounce on the link to avoid transient link + * The MPT3 firmware performs debounce on the link to avoid transient link * errors and false removals. When it does decide that link has been lost * and a device needs to go away, it expects that the host will perform a * target reset and then an op remove. The reset has the side-effect of @@ -532,6 +532,11 @@ mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_device; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mpr_map_command(sc, cm); } @@ -596,10 +601,10 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_map_command(sc, tm); - mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n", + mpr_dprint(sc, MPR_INFO, "clearing target %u handle 0x%04x\n", targ->tid, handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -608,7 +613,7 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_XINFO, "Completing missed command %p\n", tm); ccb = tm->cm_complete_data; - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); mprsas_scsiio_complete(sc, tm); } } @@ -726,7 +731,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * XXX MaxTargets could change during a reinit. since we don't + * XXX MaxTargets could change during a reinit. Since we don't * resize the targets[] array during such an event, cache the value * of MaxTargets here so that we don't get into trouble later. This * should move into the reinit logic. @@ -782,7 +787,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * Assume that discovery events will start right away. Freezing + * Assume that discovery events will start right away. * * Hold off boot until discovery is complete. */ @@ -790,9 +795,7 @@ mpr_attach_sas(struct mpr_softc *sc) sc->sassc->startup_refcount = 0; mprsas_startup_increment(sassc); - callout_init(&sassc->discovery_callout, 1 /*mprafe*/); - - sassc->tm_count = 0; + callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); /* * Register for async events so we can determine the EEDP @@ -962,7 +965,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) sassc = cam_sim_softc(sim); MPR_FUNCTRACE(sassc->sc); - mpr_dprint(sassc->sc, MPR_TRACE, "%s func 0x%x\n", __func__, + mpr_dprint(sassc->sc, MPR_TRACE, "ccb func_code 0x%x\n", ccb->ccb_h.func_code); mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); @@ -985,7 +988,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cpi->max_lun = 255; cpi->initiator_id = sassc->maxtargets - 1; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); + strncpy(cpi->hba_vid, "Avago Tech (LSI)", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = cam_sim_bus(sim); @@ -1005,7 +1008,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) */ cpi->maxio = 256 * 1024; #endif - cpi->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_GET_TRAN_SETTINGS: @@ -1024,7 +1027,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cts->ccb_h.target_id)); targ = &sassc->targets[cts->ccb_h.target_id]; if (targ->handle == 0x0) { - cts->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; } @@ -1054,12 +1057,12 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) scsi->valid = CTS_SCSI_VALID_TQ; scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; - cts->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_CALC_GEOMETRY: cam_calc_geometry(&ccb->ccg, /*extended*/1); - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_RESET_DEV: mpr_dprint(sassc->sc, MPR_XINFO, @@ -1071,7 +1074,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) case XPT_TERM_IO: mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success for abort or reset\n"); - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_SCSI_IO: mprsas_action_scsiio(sassc, ccb); @@ -1082,7 +1085,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) return; #endif default: - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + mprsas_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL); break; } xpt_done(ccb); @@ -1102,7 +1105,7 @@ mprsas_announce_reset(struct mpr_softc *sc, uint32_t ac_code, if (xpt_create_path(&path, NULL, path_id, target_id, lun_id) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for reset " - "notification\n"); + "notification\n"); return; } @@ -1131,8 +1134,8 @@ mprsas_complete_all_commands(struct mpr_softc *sc) if (cm->cm_complete != NULL) { mprsas_log_command(cm, MPR_RECOVERY, - "completing cm %p state %x ccb %p for diag reset\n", - cm, cm->cm_state, cm->cm_ccb); + "completing cm %p state %x ccb %p for diag " + "reset\n", cm, cm->cm_state, cm->cm_ccb); cm->cm_complete(sc, cm); completed = 1; } @@ -1145,6 +1148,14 @@ mprsas_complete_all_commands(struct mpr_softc *sc) completed = 1; } + if (cm->cm_sc->io_cmds_active != 0) { + cm->cm_sc->io_cmds_active--; + } else { + mpr_dprint(cm->cm_sc, MPR_INFO, "Warning: " + "io_cmds_active is out of sync - resynching to " + "0\n"); + } + if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) { /* this should never happen, but if it does, log */ mprsas_log_command(cm, MPR_RECOVERY, @@ -1180,9 +1191,8 @@ mprsas_handle_reinit(struct mpr_softc *sc) /* complete and cleanup after all outstanding commands */ mprsas_complete_all_commands(sc); - mpr_dprint(sc, MPR_INIT, "%s startup %u tm %u after command " - "completion\n", __func__, sc->sassc->startup_refcount, - sc->sassc->tm_count); + mpr_dprint(sc, MPR_INIT, "%s startup %u after command completion\n", + __func__, sc->sassc->startup_refcount); /* zero all the target handles, since they may change after the * reset, and we have to rediscover all the targets and use the new @@ -1244,7 +1254,6 @@ mprsas_logical_unit_reset_complete(struct mpr_softc *sc, "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1322,8 +1331,8 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) * task management commands don't have S/G lists. */ if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x for target reset! " - "This should not happen!\n", __func__, tm->cm_flags); + mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target " + "reset! This should not happen!\n", __func__, tm->cm_flags); mprsas_free_tm(sc, tm); return; } @@ -1333,7 +1342,6 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1349,8 +1357,6 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), le32toh(reply->TerminationCount)); - targ->flags &= ~MPRSAS_TARGET_INRESET; - if (targ->outstanding == 0) { /* we've finished recovery for this target and all * of its logical units. @@ -1378,7 +1384,7 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) #define MPR_RESET_TIMEOUT 30 -static int +int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) { MPI2_SCSI_TASK_MANAGE_REQUEST *req; @@ -1387,8 +1393,8 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) target = tm->cm_targ; if (target->handle == 0) { - mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n", - __func__, target->tid); + mpr_dprint(sc, MPR_ERROR, "%s null devhandle for target_id " + "%d\n", __func__, target->tid); return -1; } @@ -1404,6 +1410,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending logical unit reset\n"); tm->cm_complete = mprsas_logical_unit_reset_complete; + mprsas_prepare_for_tm(sc, tm, target, tm->cm_lun); } else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { /* @@ -1412,20 +1419,20 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) */ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; tm->cm_targ->target_resets++; - tm->cm_targ->flags |= MPRSAS_TARGET_INRESET; mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending target reset\n"); tm->cm_complete = mprsas_target_reset_complete; + mprsas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD); } else { mpr_dprint(sc, MPR_ERROR, "unexpected reset type 0x%x\n", type); return -1; } - mpr_dprint(sc, MPR_XINFO, "to target %u handle 0x%04x\n", target->tid, + mpr_dprint(sc, MPR_INFO, "to target %u handle 0x%04x\n", target->tid, target->handle); if (target->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", target->encl_level, target->encl_slot, target->connector_name); } @@ -1441,8 +1448,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, - "error %d sending reset type %u\n", - err, type); + "error %d sending reset type %u\n", err, type); return err; } @@ -1573,6 +1579,10 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, targ->aborts++; + mpr_dprint(sc, MPR_INFO, "Sending reset from %s for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, tm, targ, tm->cm_lun); + err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, @@ -1581,7 +1591,6 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, return err; } - static void mprsas_scsiio_timeout(void *data) { @@ -1617,11 +1626,11 @@ mprsas_scsiio_timeout(void *data) targ = cm->cm_targ; targ->timeouts++; - mprsas_log_command(cm, MPR_XINFO, "command timeout cm %p ccb %p " + mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p " "target %u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, targ->handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -1629,8 +1638,7 @@ mprsas_scsiio_timeout(void *data) /* XXX first, check the firmware state, to see if it's still * operational. if not, do a diag reset. */ - - cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT; + mprsas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT); cm->cm_state = MPR_CM_STATE_TIMEDOUT; TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); @@ -1681,19 +1689,22 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) mtx_assert(&sc->mpr_mtx, MA_OWNED); csio = &ccb->csio; + KASSERT(csio->ccb_h.target_id < sassc->maxtargets, + ("Target %d out of bounds in XPT_SCSI_IO\n", + csio->ccb_h.target_id)); targ = &sassc->targets[csio->ccb_h.target_id]; mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n", __func__, csio->ccb_h.target_id); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } if (targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT) { - mpr_dprint(sc, MPR_TRACE, "%s Raid component no SCSI IO " + mpr_dprint(sc, MPR_ERROR, "%s Raid component no SCSI IO " "supported %u\n", __func__, csio->ccb_h.target_id); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } @@ -1702,7 +1713,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) * Progress" and was actually aborted by the upper layer. Check for * this here and complete the command without error. */ - if (ccb->ccb_h.status != CAM_REQ_INPROG) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_INPROG) { mpr_dprint(sc, MPR_TRACE, "%s Command is not in progress for " "target %u\n", __func__, csio->ccb_h.target_id); xpt_done(ccb); @@ -1715,16 +1726,29 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) */ if (targ->flags & MPRSAS_TARGET_INREMOVAL) { if (targ->devinfo == 0) - csio->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - csio->ccb_h.status = CAM_SEL_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } if ((sc->mpr_flags & MPR_FLAGS_SHUTDOWN) != 0) { - mpr_dprint(sc, MPR_TRACE, "%s shutting down\n", __func__); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mpr_dprint(sc, MPR_INFO, "%s shutting down\n", __func__); + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + xpt_done(ccb); + return; + } + + /* + * If target has a reset in progress, freeze the devq and return. The + * devq will be released when the TM reset is finished. + */ + if (targ->flags & MPRSAS_TARGET_INRESET) { + ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; + mpr_dprint(sc, MPR_INFO, "%s: Freezing devq for target ID %d\n", + __func__, targ->tid); + xpt_freeze_devq(ccb->ccb_h.path, 1); xpt_done(ccb); return; } @@ -1807,7 +1831,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) if (MPR_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { mpr_free_command(sc, cm); - ccb->ccb_h.status = CAM_LUN_INVALID; + mprsas_set_ccbstatus(ccb, CAM_LUN_INVALID); xpt_done(ccb); return; } @@ -1904,7 +1928,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) } callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, - mprsas_scsiio_timeout, cm, 0); + mprsas_scsiio_timeout, cm, 0); targ->issued++; targ->outstanding++; @@ -2102,7 +2126,7 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio, desc_scsi_state, scsi_state); if (sc->mpr_debug & MPR_XINFO && - scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { + scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : Start :\n"); scsi_sense_print(csio); mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : End :\n"); @@ -2126,6 +2150,8 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) u8 *TLR_bits, TLR_on; int dir = 0, i; u16 alloc_len; + struct mprsas_target *target; + target_id_t target_id; MPR_FUNCTRACE(sc); mpr_dprint(sc, MPR_TRACE, @@ -2139,6 +2165,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) sassc = sc->sassc; ccb = cm->cm_complete_data; csio = &ccb->csio; + target_id = csio->ccb_h.target_id; rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; /* * XXX KDM if the chain allocation fails, does it matter if we do @@ -2197,7 +2224,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * because there can be no reply when we haven't actually * gone out to the hardware. */ - ccb->ccb_h.status = CAM_REQUEUE_REQ; + mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); /* * Currently the only error included in the mask is @@ -2214,7 +2241,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) xpt_freeze_simq(sassc->sim, 1); sassc->flags |= MPRSAS_QUEUE_FROZEN; mpr_dprint(sc, MPR_INFO, "Error sending command, " - "freezing SIM queue\n"); + "freezing SIM queue\n"); } } @@ -2224,7 +2251,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * commands that were sent. All SSU commands should be completed before * shutdown completes, meaning SSU_refcount will be 0 after SSU_started * is TRUE. - */ + */ if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) { mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n"); sc->SSU_refcount--; @@ -2232,12 +2259,12 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Take the fast path to completion */ if (cm->cm_reply == NULL) { - if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { + if (mprsas_get_ccbstatus(ccb) == CAM_REQ_INPROG) { if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; + mprsas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET); else { - ccb->ccb_h.status = CAM_REQ_CMP; - ccb->csio.scsi_status = SCSI_STATUS_OK; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + csio->scsi_status = SCSI_STATUS_OK; } if (sassc->flags & MPRSAS_QUEUE_FROZEN) { ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -2252,10 +2279,10 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * CAM_REQ_CMP. The first is if MPR_CM_FLAGS_ERROR_MASK is * set, the second is in the MPR_FLAGS_DIAGRESET above. */ - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { /* * Freeze the dev queue so that commands are - * executed in the correct order with after error + * executed in the correct order after error * recovery. */ ccb->ccb_h.status |= CAM_DEV_QFRZN; @@ -2285,7 +2312,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Completion failed at the transport level. */ if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | MPI2_SCSI_STATE_TERMINATED)) { - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } @@ -2294,7 +2321,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * recover the command. */ if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; + mprsas_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); break; } @@ -2306,7 +2333,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) == MPR_SCSI_RI_INVALID_FRAME)) { - sc->mapping_table[csio->ccb_h.target_id].TLR_bits = + sc->mapping_table[target_id].TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; } @@ -2318,16 +2345,16 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) */ if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { - ccb->ccb_h.status = CAM_REQ_ABORTED; + mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; } /* Handle normal status and sense */ csio->scsi_status = rep->SCSIStatus; if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; + mprsas_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { int sense_len, returned_sense_len; @@ -2362,12 +2389,11 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) (csio->data_ptr != NULL) && ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) && (sc->control_TLR) && - (sc->mapping_table[csio->ccb_h.target_id].device_info & + (sc->mapping_table[target_id].device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { vpd_list = (struct scsi_vpd_supported_page_list *) csio->data_ptr; - TLR_bits = &sc->mapping_table[csio->ccb_h.target_id]. - TLR_bits; + TLR_bits = &sc->mapping_table[target_id].TLR_bits; *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) + @@ -2380,6 +2406,24 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) } } } + + /* + * If this is a SATA direct-access end device, mark it so that + * a SCSI StartStopUnit command will be sent to it when the + * driver is being shutdown. + */ + if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) && + ((csio->data_ptr[0] & 0x1f) == T_DIRECT) && + (sc->mapping_table[target_id].device_info & + MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && + ((sc->mapping_table[target_id].device_info & + MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == + MPI2_SAS_DEVICE_INFO_END_DEVICE)) { + target = &sassc->targets[target_id]; + target->supports_SSU = TRUE; + mpr_dprint(sc, MPR_XINFO, "Target %d supports SSU\n", + target_id); + } break; case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: @@ -2390,13 +2434,13 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * failed. */ if (cm->cm_targ->devinfo == 0) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; case MPI2_IOCSTATUS_INVALID_SGL: mpr_print_scsiio_cmd(sc, cm); - ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; + mprsas_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); break; case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: /* @@ -2409,14 +2453,14 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * on the console. */ if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) - ccb->ccb_h.status = CAM_CMD_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT); else - ccb->ccb_h.status = CAM_REQ_ABORTED; + mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: /* resid is ignored for this condition */ csio->resid = 0; - ccb->ccb_h.status = CAM_DATA_RUN_ERR; + mprsas_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); break; case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: @@ -2425,7 +2469,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * transient transport-related) errors, retry these without * decrementing the retry count. */ - ccb->ccb_h.status = CAM_REQUEUE_REQ; + mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); mprsas_log_command(cm, MPR_INFO, "terminated ioc %x scsi %x state %x xfer %u\n", le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, @@ -2447,7 +2491,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, le32toh(rep->TransferCount)); csio->resid = cm->cm_length; - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } @@ -2460,7 +2504,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) "queue\n"); } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { ccb->ccb_h.status |= CAM_DEV_QFRZN; xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); } @@ -2487,16 +2531,16 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) * in the standard request size. */ if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x on SMP request!\n", - __func__, cm->cm_flags); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x on SMP " + "request!\n", __func__, cm->cm_flags); + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; if (rpl == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: NULL cm_reply!\n", __func__); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } @@ -2509,17 +2553,17 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } - mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address " - "%#jx completed successfully\n", __func__, (uintmax_t)sasaddr); + mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address %#jx " + "completed successfully\n", __func__, (uintmax_t)sasaddr); if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_SMP_STATUS_ERROR; + mprsas_set_ccbstatus(ccb, CAM_SMP_STATUS_ERROR); bailout: /* @@ -2558,7 +2602,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, */ mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " "supported\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; case CAM_DATA_SG: @@ -2571,7 +2615,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or response buffer segments " "not supported for SMP\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2605,7 +2649,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, response = ccb->smpio.smp_response; break; default: - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2614,9 +2658,9 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, * XXX We don't yet support physical addresses here. */ if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) { - mpr_printf(sc, "%s: physical addresses not supported\n", - __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " + "supported\n", __func__); + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2635,7 +2679,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " "response buffer segments not supported for SMP\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2673,7 +2717,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, if (cm == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n", __func__); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2760,7 +2804,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, bailout_error: mpr_free_command(sc, cm); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2783,7 +2827,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: target %d does not exist!\n", __func__, ccb->ccb_h.target_id); - ccb->ccb_h.status = CAM_SEL_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } @@ -2831,7 +2875,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->parent_handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent handle!\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } #ifdef OLD_MPR_PROBE @@ -2841,7 +2885,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (parent_target == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent target!\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2850,9 +2894,8 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, parent_target->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; - } sasaddr = parent_target->sasaddr; @@ -2862,7 +2905,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, targ->parent_handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2870,7 +2913,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent handle " "%d does not have a valid SAS address!\n", __func__, targ->handle, targ->parent_handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2882,7 +2925,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (sasaddr == 0) { mpr_dprint(sc, MPR_INFO, "%s: unable to find SAS address for " "handle %d\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } mprsas_send_smpcmd(sassc, ccb, sasaddr); @@ -2914,7 +2957,7 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) if (tm == NULL) { mpr_dprint(sc, MPR_ERROR, "command alloc failure in mprsas_action_resetdev\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2933,7 +2976,12 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; tm->cm_complete = mprsas_resetdev_complete; tm->cm_complete_data = ccb; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); tm->cm_targ = targ; + targ->flags |= MPRSAS_TARGET_INRESET; + mpr_map_command(sc, tm); } @@ -2962,7 +3010,7 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " "handle %#04x! This should not happen!\n", __func__, tm->cm_flags, req->DevHandle); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } @@ -2971,12 +3019,12 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, CAM_LUN_WILDCARD); } else - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); bailout: @@ -2995,7 +3043,8 @@ mprsas_poll(struct cam_sim *sim) /* frequent debug messages during a panic just slow * everything down too much. */ - mpr_printf(sassc->sc, "%s clearing MPR_TRACE\n", __func__); + mpr_dprint(sassc->sc, MPR_XINFO, "%s clearing MPR_TRACE\n", + __func__); sassc->sc->mpr_debug &= ~MPR_TRACE; } @@ -3094,7 +3143,7 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE); - if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) + if ((mprsas_get_ccbstatus((union ccb *)&cdai) == CAM_REQ_CMP) && (rcap_buf.prot & SRC16_PROT_EN)) { lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf.length); @@ -3121,8 +3170,6 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, #endif cgd = arg; - mprsas_prepare_ssu(sc, path, cgd); - #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) mprsas_check_eedp(sc, path, cgd); @@ -3134,64 +3181,6 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, } } -static void -mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, - struct ccb_getdev *cgd) -{ - struct mprsas_softc *sassc = sc->sassc; - path_id_t pathid; - target_id_t targetid; - lun_id_t lunid; - struct mprsas_target *target; - struct mprsas_lun *lun; - uint8_t found_lun; - - sassc = sc->sassc; - pathid = cam_sim_path(sassc->sim); - targetid = xpt_path_target_id(path); - lunid = xpt_path_lun_id(path); - - KASSERT(targetid < sassc->maxtargets, - ("Target %d out of bounds in mprsas_prepare_ssu\n", targetid)); - target = &sassc->targets[targetid]; - if (target->handle == 0x0) - return; - - /* - * If LUN is already in list, don't create a new one. - */ - found_lun = FALSE; - SLIST_FOREACH(lun, &target->luns, lun_link) { - if (lun->lun_id == lunid) { - found_lun = TRUE; - break; - } - } - if (!found_lun) { - lun = malloc(sizeof(struct mprsas_lun), M_MPR, - M_NOWAIT | M_ZERO); - if (lun == NULL) { - mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for " - "preparing SSU.\n"); - return; - } - lun->lun_id = lunid; - SLIST_INSERT_HEAD(&target->luns, lun, lun_link); - } - - /* - * If this is a SATA direct-access end device, mark it so that a SCSI - * StartStopUnit command will be sent to it when the driver is being - * shutdown. - */ - if (((cgd->inq_data.device & 0x1F) == T_DIRECT) && - (target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && - ((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == - MPI2_SAS_DEVICE_INFO_END_DEVICE)) { - lun->stop_at_shutdown = TRUE; - } -} - #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void @@ -3212,7 +3201,6 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, uint8_t found_lun; char path_str[64]; - sassc = sc->sassc; pathid = cam_sim_path(sassc->sim); targetid = xpt_path_target_id(path); lunid = xpt_path_lun_id(path); @@ -3288,7 +3276,7 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), M_MPR, M_NOWAIT | M_ZERO); if (rcap_buf == NULL) { - mpr_dprint(sc, MPR_FAULT, "Unable to alloc read capacity " + mpr_dprint(sc, MPR_ERROR, "Unable to alloc read capacity " "buffer for EEDP support.\n"); xpt_free_path(ccb->ccb_h.path); xpt_free_ccb(ccb); @@ -3341,7 +3329,7 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) xpt_release_devq(done_ccb->ccb_h.path, /*count*/ 1, /*run_queue*/TRUE); } - + rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; /* @@ -3359,21 +3347,21 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) /* * Got the LUN in the target's LUN list. Fill it in with EEDP - * info. If the READ CAP 16 command had some SCSI error (common + * info. If the READ CAP 16 command had some SCSI error (common * if command is not supported), mark the lun as not supporting * EEDP and set the block size to 0. */ - if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) - || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { + if ((mprsas_get_ccbstatus(done_ccb) != CAM_REQ_CMP) || + (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { lun->eedp_formatted = FALSE; lun->eedp_block_size = 0; break; } if (rcap_buf->protect & 0x01) { - mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for " - "target ID %d is formatted for EEDP " - "support.\n", done_ccb->ccb_h.target_lun, + mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for target ID " + "%d is formatted for EEDP support.\n", + done_ccb->ccb_h.target_lun, done_ccb->ccb_h.target_id); lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf->length); @@ -3389,6 +3377,34 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) #endif /* (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ +void +mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, + struct mprsas_target *target, lun_id_t lun_id) +{ + union ccb *ccb; + path_id_t path_id; + + /* + * Set the INRESET flag for this target so that no I/O will be sent to + * the target until the reset has completed. If an I/O request does + * happen, the devq will be frozen. The CCB holds the path which is + * used to release the devq. The devq is released and the CCB is freed + * when the TM completes. + */ + ccb = xpt_alloc_ccb_nowait(); + if (ccb) { + path_id = cam_sim_path(sc->sassc->sim); + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id, + target->tid, lun_id) != CAM_REQ_CMP) { + xpt_free_ccb(ccb); + } else { + tm->cm_ccb = ccb; + tm->cm_targ = target; + target->flags |= MPRSAS_TARGET_INRESET; + } + } +} + int mprsas_startup(struct mpr_softc *sc) { @@ -3489,3 +3505,33 @@ mprsas_check_id(struct mprsas_softc *sassc, int id) return (0); } + +void +mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) +{ + struct mprsas_softc *sassc; + struct mprsas_lun *lun, *lun_tmp; + struct mprsas_target *targ; + int i; + + sassc = sc->sassc; + /* + * The number of targets is based on IOC Facts, so free all of + * the allocated LUNs for each target and then the target buffer + * itself. + */ + for (i=0; i< maxtargets; i++) { + targ = &sassc->targets[i]; + SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { + free(lun, M_MPR); + } + } + free(sassc->targets, M_MPR); + + sassc->targets = malloc(sizeof(struct mprsas_target) * maxtargets, + M_MPR, M_WAITOK|M_ZERO); + if (!sassc->targets) { + panic("%s failed to alloc targets with error %d\n", + __func__, ENOMEM); + } +} diff --git a/sys/dev/mpr/mpr_sas.h b/sys/dev/mpr/mpr_sas.h index 9d3116af29d0..ebeed300c9fb 100644 --- a/sys/dev/mpr/mpr_sas.h +++ b/sys/dev/mpr/mpr_sas.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -35,7 +36,6 @@ struct mprsas_lun { lun_id_t lun_id; uint8_t eedp_formatted; uint32_t eedp_block_size; - uint8_t stop_at_shutdown; }; struct mprsas_target { @@ -55,11 +55,10 @@ struct mprsas_target { #define MPRSAS_TARGET_INREMOVAL (1 << 3) #define MPR_TARGET_FLAGS_RAID_COMPONENT (1 << 4) #define MPR_TARGET_FLAGS_VOLUME (1 << 5) +#define MPR_TARGET_IS_SATA_SSD (1 << 6) #define MPRSAS_TARGET_INRECOVERY (MPRSAS_TARGET_INABORT | \ MPRSAS_TARGET_INRESET | MPRSAS_TARGET_INCHIPRESET) -#define MPRSAS_TARGET_ADD (1 << 29) -#define MPRSAS_TARGET_REMOVE (1 << 30) uint16_t tid; SLIST_HEAD(, mprsas_lun) luns; TAILQ_HEAD(, mpr_command) commands; @@ -82,6 +81,8 @@ struct mprsas_target { unsigned int logical_unit_resets; unsigned int target_resets; uint8_t scsi_req_desc_type; + uint8_t stop_at_shutdown; + uint8_t supports_SSU; }; struct mprsas_softc { @@ -92,7 +93,6 @@ struct mprsas_softc { #define MPRSAS_DISCOVERY_TIMEOUT_PENDING (1 << 2) #define MPRSAS_QUEUE_FROZEN (1 << 3) #define MPRSAS_SHUTDOWN (1 << 4) -#define MPRSAS_SCANTHREAD (1 << 5) u_int maxtargets; struct mprsas_target *targets; struct cam_devq *devq; @@ -103,7 +103,6 @@ struct mprsas_softc { struct mpr_event_handle *mprsas_eh; u_int startup_refcount; - u_int tm_count; struct proc *sysctl_proc; struct taskqueue *ev_tq; @@ -150,6 +149,19 @@ mprsas_set_lun(uint8_t *lun, u_int ccblun) return (0); } +static __inline void +mprsas_set_ccbstatus(union ccb *ccb, int status) +{ + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= status; +} + +static __inline int +mprsas_get_ccbstatus(union ccb *ccb) +{ + return (ccb->ccb_h.status & CAM_STATUS_MASK); +} + #define MPR_SET_SINGLE_LUN(req, lun) \ do { \ bzero((req)->LUN, 8); \ @@ -158,11 +170,10 @@ do { \ void mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ); void mprsas_discovery_end(struct mprsas_softc *sassc); +void mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, + struct mprsas_target *target, lun_id_t lun_id); void mprsas_startup_increment(struct mprsas_softc *sassc); void mprsas_startup_decrement(struct mprsas_softc *sassc); -void mprsas_release_simq_reinit(struct mprsas_softc *sassc); -struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); -void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); void mprsas_firmware_event_work(void *arg, int pending); int mprsas_check_id(struct mprsas_softc *sassc, int id); diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 32e9b3a07804..7d6ef7070f7d 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for LSI MPT3 */ /* TODO Move headers to mprvar */ #include @@ -105,7 +106,9 @@ struct _ata_identify_device_data { u16 serial_number[10]; /* 10-19 */ u16 reserved2[7]; /* 20-26 */ u16 model_number[20]; /* 27-46*/ - u16 reserved3[209]; /* 47-255*/ + u16 reserved3[170]; /* 47-216 */ + u16 rotational_speed; /* 217 */ + u16 reserved4[38]; /* 218-255 */ }; static u32 event_count; static void mprsas_fw_work(struct mpr_softc *sc, @@ -116,8 +119,9 @@ static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate); static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo); +static void mprsas_ata_id_timeout(void *data); int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, - u64 *sas_address, u16 handle, u32 device_info); + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); static int mprsas_volume_add(struct mpr_softc *sc, u16 handle); static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc); @@ -325,7 +329,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) return; } - mpr_dprint(sc, MPR_INFO, "Sending FP action " + mpr_dprint(sc, MPR_EVENT, "Sending FP action " "from " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST " ":\n"); @@ -350,9 +354,9 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) if (reply && (le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { - mpr_dprint(sc, MPR_INFO, "%s: error " - "sending RaidActionPage; iocstatus " - "= 0x%x\n", __func__, + mpr_dprint(sc, MPR_ERROR, "%s: error " + "sending RaidActionPage; " + "iocstatus = 0x%x\n", __func__, le16toh(reply->IOCStatus)); } @@ -360,7 +364,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) mpr_free_command(sc, cm); } skip_fp_send: - mpr_dprint(sc, MPR_INFO, "Received " + mpr_dprint(sc, MPR_EVENT, "Received " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason " "code %x:\n", element->ReasonCode); switch (element->ReasonCode) { @@ -421,7 +425,6 @@ skip_fp_send: break; targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT; mprsas_rescan_target(sc, targ); - break; case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: /* @@ -678,14 +681,13 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ struct mprsas_target *targ; Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t config_page; - uint64_t sas_address, sata_sas_address; - uint64_t parent_sas_address = 0; - u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); + uint64_t sas_address, parent_sas_address = 0; u32 device_info, parent_devinfo = 0; unsigned int id; - int ret; - int error = 0; + int ret = 1, error = 0, i; struct mprsas_lun *lun; + u8 is_SATA_SSD = 0; + struct mpr_command *cm; sassc = sc->sassc; mprsas_startup_increment(sassc); @@ -717,26 +719,29 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ } /* TODO Check proper endianess */ sas_address = config_page.SASAddress.High; - sas_address = (sas_address << 32) | - config_page.SASAddress.Low; + sas_address = (sas_address << 32) | config_page.SASAddress.Low; + mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n", + sas_address); - if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) - == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { - if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { - ret = mprsas_get_sas_address_for_sata_disk(sc, - &sata_sas_address, handle, device_info); - if (!ret) - id = mpr_mapping_get_sas_id(sc, - sata_sas_address, handle); - else - id = mpr_mapping_get_sas_id(sc, - sas_address, handle); - } else - id = mpr_mapping_get_sas_id(sc, sas_address, - handle); - } else - id = mpr_mapping_get_sas_id(sc, sas_address, handle); + /* + * Always get SATA Identify information because this is used to + * determine if Start/Stop Unit should be sent to the drive when the + * system is shutdown. + */ + if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { + ret = mprsas_get_sas_address_for_sata_disk(sc, &sas_address, + handle, device_info, &is_SATA_SSD); + if (ret) { + mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type " + "(SSD or HDD) for SATA device with handle 0x%04x\n", + __func__, handle); + } else { + mpr_dprint(sc, MPR_INFO, "SAS Address from SATA " + "device = %jx\n", sas_address); + } + } + id = mpr_mapping_get_sas_id(sc, sas_address, handle); if (id == MPR_MAP_BAD_ID) { printf("failure at %s:%d/%s()! Could not get ID for device " "with handle 0x%04x\n", __FILE__, __LINE__, __func__, @@ -750,7 +755,7 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ error = ENXIO; goto out; } - + mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; @@ -773,6 +778,9 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ targ->tid = id; targ->linkrate = (linkrate>>4); targ->flags = 0; + if (is_SATA_SSD) { + targ->flags = MPR_TARGET_IS_SATA_SSD; + } if (le16toh(config_page.Flags) & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) { targ->scsi_req_desc_type = @@ -792,12 +800,12 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ SLIST_INIT(&targ->luns); mpr_describe_devinfo(targ->devinfo, devstring, 80); - mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "Found device <%s> <%s> " + mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> " "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring, mpr_describe_table(mpr_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); if (targ->encl_level_valid) { - mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "At enclosure level %d " + mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d " "and connector name (%4s)\n", targ->encl_level, targ->connector_name); } @@ -807,15 +815,57 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ #endif mprsas_rescan_target(sc, targ); mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid); + + /* + * Check all commands to see if the SATA_ID_TIMEOUT flag has been set. + * If so, send a Target Reset TM to the target that was just created. + * An Abort Task TM should be used instead of a Target Reset, but that + * would be much more difficult because targets have not been fully + * discovered yet, and LUN's haven't been setup. So, just reset the + * target instead of the LUN. + */ + for (i = 1; i < sc->num_reqs; i++) { + cm = &sc->commands[i]; + if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { + targ->timeouts++; + cm->cm_state = MPR_CM_STATE_TIMEDOUT; + + if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { + mpr_dprint(sc, MPR_INFO, "%s: sending Target " + "Reset for stuck SATA identify command " + "(cm = %p)\n", __func__, cm); + targ->tm->cm_targ = targ; + mprsas_send_reset(sc, targ->tm, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); + } else { + mpr_dprint(sc, MPR_ERROR, "Failed to allocate " + "tm for Target Reset after SATA ID " + "command timed out (cm %p)\n", cm); + } + /* + * No need to check for more since the target is + * already being reset. + */ + break; + } + } out: + /* + * Free the commands that may not have been freed from the SATA ID call + */ + for (i = 1; i < sc->num_reqs; i++) { + cm = &sc->commands[i]; + if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { + mpr_free_command(sc, cm); + } + } mprsas_startup_decrement(sassc); return (error); - } int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, - u64 *sas_address, u16 handle, u32 device_info) + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD) { Mpi2SataPassthroughReply_t mpi_reply; int i, rc, try_count; @@ -835,7 +885,16 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, ioc_status = le16toh(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; sas_status = mpi_reply.SASStatus; - } while ((rc == -EAGAIN || ioc_status || sas_status) && + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + if (sc->spinup_wait_time > 0) { + mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds " + "after SATA ID error to wait for spinup\n", + sc->spinup_wait_time); + msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, + "mprid", sc->spinup_wait_time * hz); + } + } + } while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) && (try_count < 5)); if (rc == 0 && !ioc_status && !sas_status) { @@ -884,6 +943,10 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 | (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 | (u64)hash_address.wwid[7]; + if (ata_identify.rotational_speed == 1) { + *is_SATA_SSD = 1; + } + return 0; } @@ -923,14 +986,29 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = buffer; cm->cm_length = htole32(sz); + + /* + * Start a timeout counter specifically for the SATA ID command. This + * is used to fix a problem where the FW does not send a reply sometimes + * when a bad disk is in the topology. So, this is used to timeout the + * command so that processing can continue normally. + */ + mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID " + "command\n", __func__); + callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz, + mprsas_ata_id_timeout, cm); error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); + mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID " + "command\n", __func__); + callout_stop(&cm->cm_callout); + reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* * If the request returns an error then we need to do a diag * reset - */ + */ printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; @@ -946,11 +1024,66 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, goto out; } out: - mpr_free_command(sc, cm); - free(buffer, M_MPR); + /* + * If the SATA_ID_TIMEOUT flag has been set for this command, don't free + * it. The command will be freed after sending a target reset TM. If + * the command did timeout, use EWOULDBLOCK. + */ + if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) + mpr_free_command(sc, cm); + else if (error == 0) + error = EWOULDBLOCK; + free(buffer, M_MPR); return (error); } +static void +mprsas_ata_id_timeout(void *data) +{ + struct mpr_softc *sc; + struct mpr_command *cm; + + cm = (struct mpr_command *)data; + sc = cm->cm_sc; + mtx_assert(&sc->mpr_mtx, MA_OWNED); + + mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n", + __func__, cm, sc); + if ((callout_pending(&cm->cm_callout)) || + (!callout_active(&cm->cm_callout))) { + mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " + "out\n", __func__); + return; + } + callout_deactivate(&cm->cm_callout); + + /* + * Run the interrupt handler to make sure it's not pending. This + * isn't perfect because the command could have already completed + * and been re-used, though this is unlikely. + */ + mpr_intr_locked(sc); + if (cm->cm_state == MPR_CM_STATE_FREE) { + mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " + "out\n", __func__); + return; + } + + mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm); + + /* + * Send wakeup() to the sleeping thread that issued this ATA ID + * command. wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), + * and this will keep reinit() from being called. This way, an Abort + * Task TM can be issued so that the timed out command can be cleared. + * The Abort Task cannot be sent from here because the driver has not + * completed setting up targets. Instead, the command is flagged so + * that special handling will be used to send the abort. + */ + cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT; + wakeup(cm); +} + static int mprsas_volume_add(struct mpr_softc *sc, u16 handle) { @@ -1024,15 +1157,13 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) path_id_t pathid = cam_sim_path(sassc->sim); target_id_t targetid; struct mprsas_target *target; - struct mprsas_lun *lun; char path_str[64]; struct timeval cur_time, start_time; mpr_lock(sc); /* - * For each LUN of each target, issue a StartStopUnit command to stop - * the device. + * For each target, issue a StartStopUnit command to stop the device. */ sc->SSU_started = TRUE; sc->SSU_refcount = 0; @@ -1042,59 +1173,52 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) continue; } - SLIST_FOREACH(lun, &target->luns, lun_link) { - ccb = xpt_alloc_ccb_nowait(); - if (ccb == NULL) { - mpr_unlock(sc); - mpr_dprint(sc, MPR_FAULT, "Unable to alloc " - "CCB to stop unit.\n"); + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB to stop " + "unit.\n"); + return; + } + + /* + * The stop_at_shutdown flag will be set if this device is + * a SATA direct-access end device. + */ + if (target->stop_at_shutdown) { + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, + pathid, targetid, CAM_LUN_WILDCARD) != + CAM_REQ_CMP) { + mpr_dprint(sc, MPR_ERROR, "Unable to create " + "path to stop unit.\n"); + xpt_free_ccb(ccb); return; } + xpt_path_string(ccb->ccb_h.path, path_str, + sizeof(path_str)); + + mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s " + "handle %d\n", path_str, target->handle); /* - * The stop_at_shutdown flag will be set if this LUN is - * a SATA direct-access end device. + * Issue a START STOP UNIT command for the target. + * Increment the SSU counter to be used to count the + * number of required replies. */ - if (lun->stop_at_shutdown) { - if (xpt_create_path(&ccb->ccb_h.path, - xpt_periph, pathid, targetid, - lun->lun_id) != CAM_REQ_CMP) { - mpr_dprint(sc, MPR_FAULT, "Unable to " - "create LUN path to stop unit.\n"); - xpt_free_ccb(ccb); - mpr_unlock(sc); - return; - } - xpt_path_string(ccb->ccb_h.path, path_str, - sizeof(path_str)); - - mpr_dprint(sc, MPR_INFO, "Sending StopUnit: " - "path %s handle %d\n", path_str, - target->handle); - - /* - * Issue a START STOP UNIT command for the LUN. - * Increment the SSU counter to be used to - * count the number of required replies. - */ - mpr_dprint(sc, MPR_INFO, "Incrementing SSU " - "count\n"); - sc->SSU_refcount++; - ccb->ccb_h.target_id = - xpt_path_target_id(ccb->ccb_h.path); - ccb->ccb_h.target_lun = lun->lun_id; - ccb->ccb_h.ppriv_ptr1 = sassc; - scsi_start_stop(&ccb->csio, - /*retries*/0, - mprsas_stop_unit_done, - MSG_SIMPLE_Q_TAG, - /*start*/FALSE, - /*load/eject*/0, - /*immediate*/FALSE, - MPR_SENSE_LEN, - /*timeout*/10000); - xpt_action(ccb); - } + mpr_dprint(sc, MPR_INFO, "Incrementing SSU count\n"); + sc->SSU_refcount++; + ccb->ccb_h.target_id = + xpt_path_target_id(ccb->ccb_h.path); + ccb->ccb_h.ppriv_ptr1 = sassc; + scsi_start_stop(&ccb->csio, + /*retries*/0, + mprsas_stop_unit_done, + MSG_SIMPLE_Q_TAG, + /*start*/FALSE, + /*load/eject*/0, + /*immediate*/FALSE, + MPR_SENSE_LEN, + /*timeout*/10000); + xpt_action(ccb); } } @@ -1102,7 +1226,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) /* * Wait until all of the SSU commands have completed or time has - * expired (60 seconds). pause for 100ms each time through. If any + * expired (60 seconds). Pause for 100ms each time through. If any * command times out, the target will be reset in the SCSI command * timeout routine. */ @@ -1112,7 +1236,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) getmicrotime(&cur_time); if ((cur_time.tv_sec - start_time.tv_sec) > 60) { - mpr_dprint(sc, MPR_FAULT, "Time has expired waiting " + mpr_dprint(sc, MPR_ERROR, "Time has expired waiting " "for SSU commands to complete.\n"); break; } @@ -1162,6 +1286,8 @@ mprsas_ir_shutdown(struct mpr_softc *sc) unsigned int id, found_volume = 0; struct mpr_command *cm; Mpi2RaidActionRequest_t *action; + target_id_t targetid; + struct mprsas_target *target; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); @@ -1214,5 +1340,47 @@ mprsas_ir_shutdown(struct mpr_softc *sc) mpr_free_command(sc, cm); out: + /* + * All of the targets must have the correct value set for + * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable. + * + * The possible values for the 'enable_ssu' variable are: + * 0: disable to SSD and HDD + * 1: disable only to HDD (default) + * 2: disable only to SSD + * 3: enable to SSD and HDD + * anything else will default to 1. + */ + for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { + target = &sc->sassc->targets[targetid]; + if (target->handle == 0x0) { + continue; + } + + if (target->supports_SSU) { + switch (sc->enable_ssu) { + case MPR_SSU_DISABLE_SSD_DISABLE_HDD: + target->stop_at_shutdown = FALSE; + break; + case MPR_SSU_DISABLE_SSD_ENABLE_HDD: + target->stop_at_shutdown = TRUE; + if (target->flags & MPR_TARGET_IS_SATA_SSD) { + target->stop_at_shutdown = FALSE; + } + break; + case MPR_SSU_ENABLE_SSD_ENABLE_HDD: + target->stop_at_shutdown = TRUE; + break; + case MPR_SSU_ENABLE_SSD_DISABLE_HDD: + default: + target->stop_at_shutdown = TRUE; + if ((target->flags & + MPR_TARGET_IS_SATA_SSD) == 0) { + target->stop_at_shutdown = FALSE; + } + break; + } + } + } mprsas_SSU_to_SATA_devices(sc); } diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 60680f5288a3..37d946718b23 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_user.c @@ -27,10 +27,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD userland interface + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface */ /*- - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +55,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -90,7 +91,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include @@ -284,8 +285,7 @@ mpr_user_read_cfg_header(struct mpr_softc *sc, static int mpr_user_read_cfg_page(struct mpr_softc *sc, - struct mpr_cfg_page_req *page_req, - void *buf) + struct mpr_cfg_page_req *page_req, void *buf) { MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; struct mpr_config_params params; @@ -328,6 +328,10 @@ mpr_user_read_extcfg_header(struct mpr_softc *sc, hdr->PageNumber = ext_page_req->header.PageNumber; hdr->ExtPageType = ext_page_req->header.ExtPageType; params.page_address = le32toh(ext_page_req->page_address); + params.buffer = NULL; + params.length = 0; + params.callback = NULL; + if ((error = mpr_read_config_page(sc, ¶ms)) != 0) { /* * Leave the request. Without resetting the chip, it's @@ -365,8 +369,8 @@ mpr_user_read_extcfg_page(struct mpr_softc *sc, params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; params.page_address = le32toh(ext_page_req->page_address); hdr->PageVersion = reqhdr->PageVersion; - hdr->PageNumber = reqhdr->PageNumber; hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + hdr->PageNumber = reqhdr->PageNumber; hdr->ExtPageType = reqhdr->ExtPageType; hdr->ExtPageLength = reqhdr->ExtPageLength; params.buffer = buf; @@ -541,6 +545,8 @@ mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd) req->ImageOffset = 0; req->ImageSize = cmd->len; + cm->cm_flags |= MPR_CM_FLAGS_DATAIN; + return (mpr_push_ieee_sge(cm, &req->SGL, 0)); } @@ -834,11 +840,22 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) task->TaskMID = cm->cm_desc.Default.SMID; cm->cm_data = NULL; - cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; + cm->cm_desc.HighPriority.RequestFlags = + MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = NULL; cm->cm_complete_data = NULL; - err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + targ = mprsas_find_target_by_handle(sc->sassc, 0, + task->DevHandle); + if (targ == NULL) { + mpr_dprint(sc, MPR_INFO, + "%s %d : invalid handle for requested TM 0x%x \n", + __func__, __LINE__, task->DevHandle); + err = 1; + } else { + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + } if (err != 0) { err = EIO; @@ -1029,7 +1046,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) dir = BUS_DMASYNC_POSTREAD; else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT) - dir = BUS_DMASYNC_POSTWRITE;; + dir = BUS_DMASYNC_POSTWRITE; bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); @@ -1351,8 +1368,8 @@ done: } static int -mpr_diag_register(struct mpr_softc *sc, - mpr_fw_diag_register_t *diag_register, uint32_t *return_code) +mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, + uint32_t *return_code) { mpr_fw_diagnostic_buffer_t *pBuffer; uint8_t extended_type, buffer_type, i; diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index 9752dcd35f6f..acac44c5baec 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,13 +25,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * * $FreeBSD$ */ #ifndef _MPRVAR_H #define _MPRVAR_H -#define MPR_DRIVER_VERSION "05.255.05.00-fbsd" +#define MPR_DRIVER_VERSION "09.255.01.00-fbsd" #define MPR_DB_MAX_WAIT 2500 @@ -47,16 +50,19 @@ #define MPR_FUNCTRACE(sc) \ mpr_dprint((sc), MPR_TRACE, "%s\n", __func__) -#define CAN_SLEEP 1 -#define NO_SLEEP 0 +#define CAN_SLEEP 1 +#define NO_SLEEP 0 #define MPR_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */ +#define MPR_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */ #define IFAULT_IOP_OVER_TEMP_THRESHOLD_EXCEEDED 0x2810 #define MPR_SCSI_RI_INVALID_FRAME (0x00000002) #define MPR_STRING_LENGTH 64 +#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */ + #include /* @@ -213,13 +219,14 @@ struct mpr_command { #define MPR_CM_FLAGS_CHAIN_FAILED (1 << 8) #define MPR_CM_FLAGS_ERROR_MASK MPR_CM_FLAGS_CHAIN_FAILED #define MPR_CM_FLAGS_USE_CCB (1 << 9) +#define MPR_CM_FLAGS_SATA_ID_TIMEOUT (1 << 10) u_int cm_state; #define MPR_CM_STATE_FREE 0 #define MPR_CM_STATE_BUSY 1 #define MPR_CM_STATE_TIMEDOUT 2 bus_dmamap_t cm_dmamap; struct scsi_sense_data *cm_sense; - TAILQ_HEAD(, mpr_chain) cm_chain_list; + TAILQ_HEAD(, mpr_chain) cm_chain_list; uint32_t cm_req_busaddr; uint32_t cm_sense_busaddr; struct callout cm_callout; @@ -256,6 +263,8 @@ struct mpr_softc { int chain_free; int max_chains; int chain_free_lowwater; + u_int enable_ssu; + int spinup_wait_time; #if __FreeBSD_version >= 900030 uint64_t chain_alloc_fail; #endif @@ -270,7 +279,7 @@ struct mpr_softc { char tmp_string[MPR_STRING_LENGTH]; TAILQ_HEAD(, mpr_command) req_list; TAILQ_HEAD(, mpr_command) high_priority_req_list; - TAILQ_HEAD(, mpr_chain) chain_list; + TAILQ_HEAD(, mpr_chain) chain_list; TAILQ_HEAD(, mpr_command) tm_list; int replypostindex; int replyfreeindex; @@ -291,7 +300,7 @@ struct mpr_softc { uint8_t event_mask[16]; TAILQ_HEAD(, mpr_event_handle) event_list; - struct mpr_event_handle *mpr_log_eh; + struct mpr_event_handle *mpr_log_eh; struct mtx mpr_mtx; struct intr_config_hook mpr_ich; @@ -565,6 +574,11 @@ mpr_unlock(struct mpr_softc *sc) #define MPR_MAPPING (1 << 9) /* Trace device mappings */ #define MPR_TRACE (1 << 10) /* Function-by-function trace */ +#define MPR_SSU_DISABLE_SSD_DISABLE_HDD 0 +#define MPR_SSU_ENABLE_SSD_DISABLE_HDD 1 +#define MPR_SSU_DISABLE_SSD_ENABLE_HDD 2 +#define MPR_SSU_ENABLE_SSD_ENABLE_HDD 3 + #define mpr_printf(sc, args...) \ device_printf((sc)->mpr_dev, ##args) @@ -600,9 +614,6 @@ do { \ #define MPR_EVENTFIELD(sc, facts, attr, fmt) \ mpr_dprint_field((sc), MPR_EVENT, #attr ": " #fmt "\n", (facts)->attr) -#define CAN_SLEEP 1 -#define NO_SLEEP 0 - static __inline void mpr_from_u64(uint64_t data, U64 *mpr) { @@ -613,7 +624,6 @@ mpr_from_u64(uint64_t data, U64 *mpr) static __inline uint64_t mpr_to_u64(U64 *data) { - return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low)); } @@ -727,6 +737,12 @@ void mprsas_prepare_volume_remove(struct mprsas_softc *sassc, int mprsas_startup(struct mpr_softc *sc); struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *, int, uint16_t); +void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets); +struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); +void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); +void mprsas_release_simq_reinit(struct mprsas_softc *sassc); +int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, + uint8_t type); SYSCTL_DECL(_hw_mpr); From 9794079730310dcf8d02f0659d77684f389f8eb7 Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 May 2015 18:34:02 +0000 Subject: [PATCH 36/65] Fix a bug where messages would not be sent in SHUTDOWN_RECEIVED state. This problem was reported by Mark Bonnekessel and Markus Boese. Thanks to Irene Ruengeler for helping me to fix the cause of the problem. It can be tested with the following packetdrill script: +0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 +0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) +0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 // Check the handshake with an empty(!) cookie +0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) +0.0 > sctp: INIT[flgs=0, tag=1, a_rwnd=..., os=..., is=..., tsn=0, ...] +0.1 < sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=10000, os=1, is=1, tsn=0, STATE_COOKIE[len=4, val=...]] +0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...] +0.1 < sctp: COOKIE_ACK[flgs=0] +0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 +0.0 write(3, ..., 1024) = 1024 +0.0 > sctp: DATA[flgs=BE, len=1040, tsn=0, sid=0, ssn=0, ppid=0] +0.0 write(3, ..., 1024) = 1024 // Pending due to Nagle +0.0 < sctp: SHUTDOWN[flgs=0, cum_tsn=0] +0.0 > sctp: DATA[flgs=BE, len=1040, tsn=1, sid=0, ssn=1, ppid=0] +0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=10000, gaps=[], dups=[]] // Do we need another SHUTDOWN here? +0.0 > sctp: SHUTDOWN_ACK[flgs=0] +0.0 < sctp: SHUTDOWN_COMPLETE[flgs=0] +0.0 close(3) = 0 MFC after: 3 days --- sys/netinet/sctp_asconf.c | 12 ++++++++---- sys/netinet/sctp_output.c | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index 10bb0a26f471..21add4329ccd 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -1977,7 +1977,8 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * sent when the state goes open. */ if (status == 0 && - SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { + ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED))) { #ifdef SCTP_TIMER_BASED_ASCONF sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, stcb, stcb->asoc.primary_destination); @@ -2225,7 +2226,8 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * count of queued params. If in the non-open * state, these get sent when the assoc goes open. */ - if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { if (status >= 0) { num_queued++; } @@ -2285,7 +2287,8 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) "set_primary_ip_address_sa: queued on tcb=%p, ", (void *)stcb); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); - if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { #ifdef SCTP_TIMER_BASED_ASCONF sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, @@ -2321,7 +2324,8 @@ sctp_set_primary_ip_address(struct sctp_ifa *ifa) SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ", (void *)stcb); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa); - if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { #ifdef SCTP_TIMER_BASED_ASCONF sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index ebc66923b9d7..4a7c6827df59 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -8535,7 +8535,8 @@ again_one_more_time: omtu = 0; break; } - if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) && + if ((((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || + (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) && (skip_data_for_this_net == 0)) || (cookie)) { TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { From 2ff25b445e021df14558d0b4a1ce700d67e36907 Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 May 2015 18:52:32 +0000 Subject: [PATCH 37/65] Retire SCTP_DONT_DO_PRIVADDR_SCOPE which was never defined. MFC after: 3 days --- sys/netinet/sctp_output.c | 8 -------- sys/netinet/sctp_pcb.c | 4 ---- 2 files changed, 12 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 4a7c6827df59..47a341ceef26 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -5591,11 +5591,7 @@ do_a_abort: stc.ipv6_addr_legal = 0; stc.ipv4_addr_legal = 1; } -#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE - stc.ipv4_scope = 1; -#else stc.ipv4_scope = 0; -#endif if (net == NULL) { to = src; switch (dst->sa_family) { @@ -5616,13 +5612,9 @@ do_a_abort: stc.laddr_type = SCTP_IPV4_ADDRESS; /* scope_id is only for v6 */ stc.scope_id = 0; -#ifndef SCTP_DONT_DO_PRIVADDR_SCOPE if (IN4_ISPRIVATE_ADDRESS(&src4->sin_addr)) { stc.ipv4_scope = 1; } -#else - stc.ipv4_scope = 1; -#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ /* Must use the address in this case */ if (sctp_is_address_on_local_host(src, vrf_id)) { stc.loopback_scope = 1; diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index f6e9e326f8d3..6fcb6d2eebe3 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -3792,13 +3792,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, /* assure len is set */ sin->sin_len = sizeof(struct sockaddr_in); if (set_scope) { -#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE - stcb->asoc.scope.ipv4_local_scope = 1; -#else if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { stcb->asoc.scope.ipv4_local_scope = 1; } -#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ } else { /* Validate the address is in scope */ if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && From a864af135831528ff3a72d962567b12fbb560d6b Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 May 2015 19:28:08 +0000 Subject: [PATCH 38/65] Take source and destination address into account when determining the scope. This fixes a problem when a client with a global address connects to a server with a private address. Thanks to Irene Ruengeler in helping me to find the issue. MFC after: 3 days --- sys/netinet/sctp_output.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 47a341ceef26..d2ada5d7fcb5 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -5612,7 +5612,8 @@ do_a_abort: stc.laddr_type = SCTP_IPV4_ADDRESS; /* scope_id is only for v6 */ stc.scope_id = 0; - if (IN4_ISPRIVATE_ADDRESS(&src4->sin_addr)) { + if ((IN4_ISPRIVATE_ADDRESS(&src4->sin_addr)) || + (IN4_ISPRIVATE_ADDRESS(&dst4->sin_addr))) { stc.ipv4_scope = 1; } /* Must use the address in this case */ @@ -5636,16 +5637,18 @@ do_a_abort: stc.local_scope = 0; stc.site_scope = 1; stc.ipv4_scope = 1; - } else if (IN6_IS_ADDR_LINKLOCAL(&src6->sin6_addr)) { + } else if (IN6_IS_ADDR_LINKLOCAL(&src6->sin6_addr) || + IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) { /* - * If the new destination is a - * LINK_LOCAL we must have common - * both site and local scope. Don't - * set local scope though since we - * must depend on the source to be - * added implicitly. We cannot - * assure just because we share one - * link that all links are common. + * If the new destination or source + * is a LINK_LOCAL we must have + * common both site and local scope. + * Don't set local scope though + * since we must depend on the + * source to be added implicitly. We + * cannot assure just because we + * share one link that all links are + * common. */ stc.local_scope = 0; stc.site_scope = 1; @@ -5661,11 +5664,12 @@ do_a_abort: * pull out the scope_id from * incoming pkt */ - } else if (IN6_IS_ADDR_SITELOCAL(&src6->sin6_addr)) { + } else if (IN6_IS_ADDR_SITELOCAL(&src6->sin6_addr) || + IN6_IS_ADDR_SITELOCAL(&dst6->sin6_addr)) { /* - * If the new destination is - * SITE_LOCAL then we must have site - * scope in common. + * If the new destination or source + * is SITE_LOCAL then we must have + * site scope in common. */ stc.site_scope = 1; } From 0de1f8c7b54ba528685a87f26767f96440dcc65d Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 May 2015 20:33:28 +0000 Subject: [PATCH 39/65] Report the MTU consistently as specified in https://tools.ietf.org/html/rfc6458 Thanks to Irene Ruengeler for helping me to fix this bug. MFC after: 3 days --- sys/netinet/sctp_usrreq.c | 99 +++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 25 deletions(-) diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 50059101712d..2a59e13133b7 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -2439,17 +2439,23 @@ flags_out: /* Applies to the specific association */ paddrp->spp_flags = 0; if (net != NULL) { - int ovh; - - if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - ovh = SCTP_MED_OVERHEAD; - } else { - ovh = SCTP_MED_V4_OVERHEAD; - } - paddrp->spp_hbinterval = net->heart_beat_delay; paddrp->spp_pathmaxrxt = net->failure_threshold; - paddrp->spp_pathmtu = net->mtu - ovh; + paddrp->spp_pathmtu = net->mtu; + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD; + break; +#endif +#ifdef INET6 + case AF_INET6: + paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD; + break; +#endif + default: + break; + } /* get flags for HB */ if (net->dest_state & SCTP_ADDR_NOHB) { paddrp->spp_flags |= SPP_HB_DISABLE; @@ -2479,7 +2485,7 @@ flags_out: * value */ paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure; - paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc); + paddrp->spp_pathmtu = 0; if (stcb->asoc.default_dscp & 0x01) { paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc; paddrp->spp_flags |= SPP_DSCP; @@ -2615,6 +2621,20 @@ flags_out: paddri->spinfo_rto = net->RTO; paddri->spinfo_assoc_id = sctp_get_associd(stcb); paddri->spinfo_mtu = net->mtu; + switch (addr->sa_family) { +#if defined(INET) + case AF_INET: + paddri->spinfo_mtu -= SCTP_MIN_V4_OVERHEAD; + break; +#endif +#if defined(INET6) + case AF_INET6: + paddri->spinfo_mtu -= SCTP_MIN_OVERHEAD; + break; +#endif + default: + break; + } SCTP_TCB_UNLOCK(stcb); *optsize = sizeof(struct sctp_paddrinfo); } else { @@ -2691,6 +2711,20 @@ flags_out: sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT; sstat->sstat_primary.spinfo_rto = net->RTO; sstat->sstat_primary.spinfo_mtu = net->mtu; + switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) { +#if defined(INET) + case AF_INET: + sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD; + break; +#endif +#if defined(INET6) + case AF_INET6: + sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD; + break; +#endif + default: + break; + } sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb); SCTP_TCB_UNLOCK(stcb); *optsize = sizeof(struct sctp_status); @@ -5188,19 +5222,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } if (stcb != NULL) { /************************TCB SPECIFIC SET ******************/ - /* - * do we change the timer for HB, we run - * only one? - */ - int ovh = 0; - - if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - ovh = SCTP_MED_OVERHEAD; - } else { - ovh = SCTP_MED_V4_OVERHEAD; - } - - /* network sets ? */ if (net != NULL) { /************************NET SPECIFIC SET ******************/ if (paddrp->spp_flags & SPP_HB_DISABLE) { @@ -5234,7 +5255,21 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11); } net->dest_state |= SCTP_ADDR_NO_PMTUD; - net->mtu = paddrp->spp_pathmtu + ovh; + net->mtu = paddrp->spp_pathmtu; + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + net->mtu += SCTP_MIN_V4_OVERHEAD; + break; +#endif +#ifdef INET6 + case AF_INET6: + net->mtu += SCTP_MIN_OVERHEAD; + break; +#endif + default: + break; + } if (net->mtu < stcb->asoc.smallest_mtu) { sctp_pathmtu_adjustment(stcb, net->mtu); } @@ -5362,7 +5397,21 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16); } net->dest_state |= SCTP_ADDR_NO_PMTUD; - net->mtu = paddrp->spp_pathmtu + ovh; + net->mtu = paddrp->spp_pathmtu; + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + net->mtu += SCTP_MIN_V4_OVERHEAD; + break; +#endif +#ifdef INET6 + case AF_INET6: + net->mtu += SCTP_MIN_OVERHEAD; + break; +#endif + default: + break; + } if (net->mtu < stcb->asoc.smallest_mtu) { sctp_pathmtu_adjustment(stcb, net->mtu); } From dce46f40950ace53058f9271895013fe4fb7fd13 Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 28 May 2015 21:06:59 +0000 Subject: [PATCH 40/65] Provide VOP_GETPAGES_ASYNC() for extfs. Merge the filesystem specific part from r274914 to ext2fs. I only did regular testing with the change but UFS and our ext2fs are similar enough that the code should just work with the new sendfile. Discussed with: glebius --- sys/fs/ext2fs/ext2_vnops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index dd30aea279c4..5b8990ee84c4 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -128,6 +128,7 @@ struct vop_vector ext2_vnodeops = { .vop_create = ext2_create, .vop_fsync = ext2_fsync, .vop_getpages = vnode_pager_local_getpages, + .vop_getpages_async = vnode_pager_local_getpages_async, .vop_getattr = ext2_getattr, .vop_inactive = ext2_inactive, .vop_ioctl = ext2_ioctl, From a2158a48ce1a105bab12222bc489bdf3416ae2cc Mon Sep 17 00:00:00 2001 From: jhb Date: Thu, 28 May 2015 22:01:50 +0000 Subject: [PATCH 41/65] Create a separate kobj interface for leaf-driver PCI IOV methods. Leaf drivers should not import the PCI bus interface to add IOV handling. Instead, move the IOV client methods to a separate kobj interface. Differential Revision: https://reviews.freebsd.org/D2584 Reviewed by: rstone --- ObsoleteFiles.inc | 4 ++ share/man/man9/Makefile | 6 +-- .../man9/{PCI_ADD_VF.9 => PCI_IOV_ADD_VF.9} | 31 ++++++----- .../man9/{PCI_INIT_IOV.9 => PCI_IOV_INIT.9} | 19 ++++--- .../{PCI_UNINIT_IOV.9 => PCI_IOV_UNINIT.9} | 23 ++++---- share/man/man9/pci.9 | 17 +++--- share/man/man9/pci_iov_schema.9 | 6 +-- sys/conf/files | 1 + sys/conf/kmod.mk | 2 +- sys/dev/ixl/if_ixl.c | 14 ++--- sys/dev/ixl/ixl.h | 1 + sys/dev/pci/pci_if.m | 17 ------ sys/dev/pci/pci_iov.c | 14 ++--- sys/dev/pci/pci_iov.h | 49 +++++++++++++++++ sys/dev/pci/pci_iov_if.m | 52 +++++++++++++++++++ sys/dev/pci/pcivar.h | 15 ------ sys/modules/ixl/Makefile | 2 +- 17 files changed, 173 insertions(+), 100 deletions(-) rename share/man/man9/{PCI_ADD_VF.9 => PCI_IOV_ADD_VF.9} (91%) rename share/man/man9/{PCI_INIT_IOV.9 => PCI_IOV_INIT.9} (92%) rename share/man/man9/{PCI_UNINIT_IOV.9 => PCI_IOV_UNINIT.9} (89%) create mode 100644 sys/dev/pci/pci_iov.h create mode 100644 sys/dev/pci/pci_iov_if.m mode change 100755 => 100644 sys/modules/ixl/Makefile diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index a3b9fdcda0ec..f8de1b3863e8 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,10 @@ # xargs -n1 | sort | uniq -d; # done +# 20150528: PCI IOV device driver methods moved to a separate kobj interface. +OLD_FILES+=usr/share/man/man9/PCI_ADD_VF.9 +OLD_FILES+=usr/share/man/man9/PCI_INIT_IOV.9 +OLD_FILES+=usr/share/man/man9/PCI_UNINIT_IOV.9 # 20150525: new clang import which bumps version from 3.6.0 to 3.6.1. OLD_FILES+=usr/lib/clang/3.6.0/include/__stddef_max_align_t.h OLD_FILES+=usr/lib/clang/3.6.0/include/__wmmintrin_aes.h diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 11dcb01b3a6d..d0e204f99586 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -195,10 +195,10 @@ MAN= accept_filter.9 \ p_candebug.9 \ p_cansee.9 \ pci.9 \ - PCI_ADD_VF.9 \ - PCI_INIT_IOV.9 \ + PCI_IOV_ADD_VF.9 \ + PCI_IOV_INIT.9 \ pci_iov_schema.9 \ - PCI_UNINIT_IOV.9 \ + PCI_IOV_UNINIT.9 \ pfil.9 \ pfind.9 \ pget.9 \ diff --git a/share/man/man9/PCI_ADD_VF.9 b/share/man/man9/PCI_IOV_ADD_VF.9 similarity index 91% rename from share/man/man9/PCI_ADD_VF.9 rename to share/man/man9/PCI_IOV_ADD_VF.9 index 72a3a9740ef2..d99a1065a6a2 100644 --- a/share/man/man9/PCI_ADD_VF.9 +++ b/share/man/man9/PCI_IOV_ADD_VF.9 @@ -25,38 +25,37 @@ .\" .\" $FreeBSD$ .\" -.Dd May 24, 2014 -.Dt PCI_ADD_VF 9 +.Dd May 28, 2015 +.Dt PCI_IOV_ADD_VF 9 .Os .Sh NAME -.Nm PCI_ADD_VF +.Nm PCI_IOV_ADD_VF .Nd inform a PF driver that a VF is being created .Sh SYNOPSIS .In sys/bus.h .In machine/stdarg.h .In sys/nv.h -.In dev/pci/pcireg.h -.In dev/pci/pcivar.h +.In dev/pci/pci_iov.h .Ft int -.Fn PCI_ADD_VF "device_t dev" "uint16_t vfnum" "const nvlist_t *vf_config" +.Fn PCI_IOV_ADD_VF "device_t dev" "uint16_t vfnum" "const nvlist_t *vf_config" .Sh DESCRIPTION The -.Fn PCI_ADD_VF +.Fn PCI_IOV_ADD_VF method is called by the PCI Single-Root I/O Virtualization .Pq SR-IOV infrastructure when it is initializating a new Virtual Function (VF) as a child of the given Physical Function (PF) device. This method will not be called until a successful call to -.Xr PCI_INIT_IOV 9 +.Xr PCI_IOV_INIT 9 has been made. It is not guaranteed that this method will be called following a successful call to -.Xr PCI_INIT_IOV 9 . +.Xr PCI_IOV_INIT 9 . If the infrastructure encounters a failure to allocate resources following the call to -.Xr PCI_INIT_IOV 9 , +.Xr PCI_IOV_INIT 9 , the VF creation will be aborted and -.Xr PCI_UNINIT_IOV 9 +.Xr PCI_IOV_UNINIT 9 will be called immediately without any preceding calls to .Nm . .Pp @@ -87,15 +86,15 @@ Note that it is possible for the user to set different configuration values on different VF devices that are children of the same PF. The PF driver must not cache configuration parameters passed in previous calls to -.Fn PCI_ADD_VF +.Fn PCI_IOV_ADD_VF for other VFs and apply those parameters to the current VF. .Pp This function will not be called twice for the same .Fa vf_num on the same PF device without -.Xr PCI_UNINIT_IOV 9 +.Xr PCI_IOV_UNINIT 9 and -.Xr PCI_INIT_IOV 9 +.Xr PCI_IOV_INIT 9 first being called, in that order. .Sh RETURN VALUES This method returns 0 on success, otherwise an appropriate error is returned. @@ -106,8 +105,8 @@ the PF. .Xr nv 9 , .Xr pci 9 , .Xr pci_iov_schema 9 , -.Xr PCI_INIT_IOV 9 , -.Xr PCI_UNINIT_IOV 9 +.Xr PCI_IOV_INIT 9 , +.Xr PCI_IOV_UNINIT 9 .Sh AUTHORS This manual page was written by .An Ryan Stone Aq Mt rstone@FreeBSD.org . diff --git a/share/man/man9/PCI_INIT_IOV.9 b/share/man/man9/PCI_IOV_INIT.9 similarity index 92% rename from share/man/man9/PCI_INIT_IOV.9 rename to share/man/man9/PCI_IOV_INIT.9 index 1c8c64e5fdbb..f9daa24f0578 100644 --- a/share/man/man9/PCI_INIT_IOV.9 +++ b/share/man/man9/PCI_IOV_INIT.9 @@ -25,23 +25,22 @@ .\" .\" $FreeBSD$ .\" -.Dd May 24, 2014 -.Dt PCI_INIT_IOV 9 +.Dd May 28, 2015 +.Dt PCI_IOV_INIT 9 .Os .Sh NAME -.Nm PCI_INIT_IOV +.Nm PCI_IOV_INIT .Nd enable SR-IOV on a PF device .Sh SYNOPSIS .In sys/bus.h .In machine/stdarg.h .In sys/nv.h -.In dev/pci/pcireg.h -.In dev/pci/pcivar.h +.In dev/pci/pci_iov.h .Ft int -.Fn PCI_INIT_IOV "device_t dev" "uint16_t num_vfs" "const nvlist_t *pf_config" +.Fn PCI_IOV_INIT "device_t dev" "uint16_t num_vfs" "const nvlist_t *pf_config" .Sh DESCRIPTION The -.Fn PCI_INIT_IOV +.Fn PCI_IOV_INIT method is called by the PCI Single-Root I/O Virtualization (SR-IOV) infrastucture when the user requests that SR-IOV be enabled on a Physical Function (PF). @@ -70,7 +69,7 @@ valid values specified in the schema. .Pp If this method returns successfully, then this method will not be called again on the same device until after a call to -.Xr PCI_UNINIT_IOV . +.Xr PCI_IOV_UNINIT . .Sh RETURN VALUES Returns 0 on success, otherwise an appropriate error is returned. If this method returns an error then the SR-IOV configuration will be aborted @@ -79,8 +78,8 @@ and no VFs will be created. .Xr nv 9 , .Xr pci 9 , .Xr pci_iov_schema 9 , -.Xr PCI_ADD_VF 9 , -.Xr PCI_UNINIT_IOV 9 +.Xr PCI_IOV_ADD_VF 9 , +.Xr PCI_IOV_UNINIT 9 .Sh AUTHORS This manual page was written by .An Ryan Stone Aq Mt rstone@FreeBSD.org . diff --git a/share/man/man9/PCI_UNINIT_IOV.9 b/share/man/man9/PCI_IOV_UNINIT.9 similarity index 89% rename from share/man/man9/PCI_UNINIT_IOV.9 rename to share/man/man9/PCI_IOV_UNINIT.9 index fc4cc8508fbb..b95914ee4d52 100644 --- a/share/man/man9/PCI_UNINIT_IOV.9 +++ b/share/man/man9/PCI_IOV_UNINIT.9 @@ -25,21 +25,20 @@ .\" .\" $FreeBSD$ .\" -.Dd May 24, 2014 -.Dt PCI_UNINIT_IOV 9 +.Dd May 28, 2015 +.Dt PCI_IOV_UNINIT 9 .Os .Sh NAME -.Nm PCI_UNINIT_IOV +.Nm PCI_IOV_UNINIT .Nd disable SR-IOV on a PF device .Sh SYNOPSIS .In sys/bus.h -.In dev/pci/pcireg.h -.In dev/pci/pcivar.h +.In dev/pci/pci_iov.h .Ft void -.Fn PCI_UNINIT_IOV "device_t dev" +.Fn PCI_IOV_UNINIT "device_t dev" .Sh DESCRIPTION The -.Fn PCI_UNINIT_IOV +.Fn PCI_IOV_UNINIT method is called by the PCI Single-Root I/O Virtualization (SR-IOV) infrastructure when the user requests that SR-IOV be disabled on a Physical Function (PF). @@ -48,17 +47,17 @@ resources that it has allocated and disable any device-specific SR-IOV configuration in the device. .Pp This method will only be called following a successful call to -.Xr PCI_INIT_IOV . +.Xr PCI_IOV_INIT . It is not guaranteed that -.Xr PCI_ADD_VF +.Xr PCI_IOV_ADD_VF will have been called for any Virtual Function (VF) after the call to -.Xr PCI_INIT_IOV +.Xr PCI_IOV_INIT and before the call to .Nm . .Sh SEE ALSO .Xr pci 9 , -.Xr PCI_ADD_VF 9 , -.Xr PCI_INIT_IOV 9 +.Xr PCI_IOV_ADD_VF 9 , +.Xr PCI_IOV_INIT 9 .Sh AUTHORS This manual page was written by .An Ryan Stone Aq Mt rstone@FreeBSD.org . diff --git a/share/man/man9/pci.9 b/share/man/man9/pci.9 index a33d2edaf33f..14500b53f7b9 100644 --- a/share/man/man9/pci.9 +++ b/share/man/man9/pci.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 24, 2014 +.Dd May 28, 2015 .Dt PCI 9 .Os .Sh NAME @@ -97,10 +97,6 @@ .Ft int .Fn pci_get_vpd_readonly "device_t dev" "const char *kw" "const char **vptr" .Ft int -.Fn pci_iov_attach "device_t dev" "nvlist_t *pf_schema" "nvlist_t *vf_schema" -.Ft int -.Fn pci_iov_detach "device_t dev" -.Ft int .Fn pci_msi_count "device_t dev" .Ft int .Fn pci_msix_count "device_t dev" @@ -122,6 +118,11 @@ .Fn pci_set_powerstate "device_t dev" "int state" .Ft void .Fn pci_write_config "device_t dev" "int reg" "uint32_t val" "int width" +.In dev/pci/pci_iov.h +.Ft int +.Fn pci_iov_attach "device_t dev" "nvlist_t *pf_schema" "nvlist_t *vf_schema" +.Ft int +.Fn pci_iov_detach "device_t dev" .Sh DESCRIPTION The .Nm @@ -446,10 +447,10 @@ function is used to advertise that the given device supports PCI Single-Root I/O Virtualization .Po SR-IOV Pc . A driver that supports SR-IOV must implement the -.Xr PCI_INIT_IOV 9 , -.Xr PCI_ADD_VF 9 +.Xr PCI_IOV_INIT 9 , +.Xr PCI_IOV_ADD_VF 9 and -.Xr PCI_UNIT_IOV 9 +.Xr PCI_IOV_UNINIT 9 methods. This function should be called during the .Xr DEVICE_ATTACH 9 diff --git a/share/man/man9/pci_iov_schema.9 b/share/man/man9/pci_iov_schema.9 index f2f1f303fdf4..36c0189d62f4 100644 --- a/share/man/man9/pci_iov_schema.9 +++ b/share/man/man9/pci_iov_schema.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 25, 2014 +.Dd May 28, 2015 .Dt pci_iov_schema 9 .Os .Sh NAME @@ -258,8 +258,8 @@ The function returns a pointer to the allocated schema, or NULL if a failure occurs. .Sh SEE ALSO .Xr pci 9 , -.Xr PCI_ADD_VF 9 , -.Xr PCI_INIT_IOV 9 +.Xr PCI_IOV_ADD_VF 9 , +.Xr PCI_IOV_INIT 9 .Sh AUTHORS This manual page was written by .An Ryan Stone Aq rstone@FreeBSD.org . diff --git a/sys/conf/files b/sys/conf/files index 0a63a1c2dd2d..5dcb6a43d75d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2024,6 +2024,7 @@ dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_iov.c optional pci pci_iov +dev/pci/pci_iov_if.m standard dev/pci/pci_iov_schema.c optional pci pci_iov dev/pci/pci_pci.c optional pci dev/pci/pci_subr.c optional pci diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 0f27113e3960..900974509fc9 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -349,7 +349,7 @@ MFILES?= dev/acpica/acpi_if.m dev/acpi_support/acpi_wmi_if.m \ dev/mbox/mbox_if.m dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \ dev/mii/miibus_if.m dev/mvs/mvs_if.m dev/ofw/ofw_bus_if.m \ dev/pccard/card_if.m dev/pccard/power_if.m dev/pci/pci_if.m \ - dev/pci/pcib_if.m dev/ppbus/ppbus_if.m \ + dev/pci/pci_iov_if.m dev/pci/pcib_if.m dev/ppbus/ppbus_if.m \ dev/sdhci/sdhci_if.m dev/smbus/smbus_if.m dev/spibus/spibus_if.m \ dev/sound/pci/hda/hdac_if.m \ dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \ diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c index de4ee2450668..026bc9ed9f68 100644 --- a/sys/dev/ixl/if_ixl.c +++ b/sys/dev/ixl/if_ixl.c @@ -199,8 +199,8 @@ static int ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS); #ifdef PCI_IOV static int ixl_adminq_err_to_errno(enum i40e_admin_queue_err err); -static int ixl_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t*); -static void ixl_uninit_iov(device_t dev); +static int ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t*); +static void ixl_iov_uninit(device_t dev); static int ixl_add_vf(device_t dev, uint16_t vfnum, const nvlist_t*); static void ixl_handle_vf_msg(struct ixl_pf *, @@ -222,9 +222,9 @@ static device_method_t ixl_methods[] = { DEVMETHOD(device_detach, ixl_detach), DEVMETHOD(device_shutdown, ixl_shutdown), #ifdef PCI_IOV - DEVMETHOD(pci_init_iov, ixl_init_iov), - DEVMETHOD(pci_uninit_iov, ixl_uninit_iov), - DEVMETHOD(pci_add_vf, ixl_add_vf), + DEVMETHOD(pci_iov_init, ixl_iov_init), + DEVMETHOD(pci_iov_uninit, ixl_iov_uninit), + DEVMETHOD(pci_iov_add_vf, ixl_add_vf), #endif {0, 0} }; @@ -6456,7 +6456,7 @@ ixl_adminq_err_to_errno(enum i40e_admin_queue_err err) } static int -ixl_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t *params) +ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params) { struct ixl_pf *pf; struct i40e_hw *hw; @@ -6504,7 +6504,7 @@ fail: } static void -ixl_uninit_iov(device_t dev) +ixl_iov_uninit(device_t dev) { struct ixl_pf *pf; struct i40e_hw *hw; diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h index 1ddfbca3d7d7..3348e1abae27 100644 --- a/sys/dev/ixl/ixl.h +++ b/sys/dev/ixl/ixl.h @@ -93,6 +93,7 @@ #ifdef PCI_IOV #include #include +#include #endif #include "i40e_type.h" diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m index 9f97d9a86f4e..aeeff2cf3258 100644 --- a/sys/dev/pci/pci_if.m +++ b/sys/dev/pci/pci_if.m @@ -214,22 +214,6 @@ METHOD int iov_detach { device_t child; }; -METHOD int init_iov { - device_t dev; - uint16_t num_vfs; - const struct nvlist *config; -}; - -METHOD void uninit_iov { - device_t dev; -}; - -METHOD int add_vf { - device_t dev; - uint16_t vfnum; - const struct nvlist *config; -}; - METHOD device_t create_iov_child { device_t bus; device_t pf; @@ -237,4 +221,3 @@ METHOD device_t create_iov_child { uint16_t vid; uint16_t did; } DEFAULT null_create_iov_child; - diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index 4672e55e5996..58e692649df5 100644 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -53,11 +53,11 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include -#include "pci_if.h" #include "pcib_if.h" static MALLOC_DEFINE(M_SRIOV, "sr_iov", "PCI SR-IOV allocations"); @@ -483,13 +483,13 @@ pci_iov_config_page_size(struct pci_devinfo *dinfo) } static int -pci_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t *config) +pci_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *config) { const nvlist_t *device, *driver_config; device = nvlist_get_nvlist(config, PF_CONFIG_NAME); driver_config = nvlist_get_nvlist(device, DRIVER_CONFIG_NAME); - return (PCI_INIT_IOV(dev, num_vfs, driver_config)); + return (PCI_IOV_INIT(dev, num_vfs, driver_config)); } static int @@ -595,7 +595,7 @@ pci_iov_enumerate_vfs(struct pci_devinfo *dinfo, const nvlist_t *config, pci_iov_add_bars(iov, vfinfo); - error = PCI_ADD_VF(dev, i, driver_config); + error = PCI_IOV_ADD_VF(dev, i, driver_config); if (error != 0) { device_printf(dev, "Failed to add VF %d\n", i); pci_delete_child(bus, vf); @@ -652,7 +652,7 @@ pci_iov_config(struct cdev *cdev, struct pci_iov_arg *arg) if (error != 0) goto out; - error = pci_init_iov(dev, num_vfs, config); + error = pci_iov_init(dev, num_vfs, config); if (error != 0) goto out; iov_inited = 1; @@ -700,7 +700,7 @@ pci_iov_config(struct cdev *cdev, struct pci_iov_arg *arg) return (0); out: if (iov_inited) - PCI_UNINIT_IOV(dev); + PCI_IOV_UNINIT(dev); for (i = 0; i <= PCIR_MAX_BAR_0; i++) { if (iov->iov_bar[i].res != NULL) { @@ -793,7 +793,7 @@ pci_iov_delete(struct cdev *cdev) if (pci_iov_is_child_vf(iov, vf)) pci_delete_child(bus, vf); } - PCI_UNINIT_IOV(dev); + PCI_IOV_UNINIT(dev); iov_ctl = IOV_READ(dinfo, PCIR_SRIOV_CTL, 2); iov_ctl &= ~(PCIM_SRIOV_VF_EN | PCIM_SRIOV_VF_MSE); diff --git a/sys/dev/pci/pci_iov.h b/sys/dev/pci/pci_iov.h new file mode 100644 index 000000000000..fd2f8fba8876 --- /dev/null +++ b/sys/dev/pci/pci_iov.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2013-2015 Sandvine Inc. + * 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 _PCI_IOV_H_ +#define _PCI_IOV_H_ + +#include "pci_iov_if.h" + +struct nvlist; + +static __inline int +pci_iov_attach(device_t dev, struct nvlist *pf_schema, struct nvlist *vf_schema) +{ + return (PCI_IOV_ATTACH(device_get_parent(dev), dev, pf_schema, + vf_schema)); +} + +static __inline int +pci_iov_detach(device_t dev) +{ + return (PCI_IOV_DETACH(device_get_parent(dev), dev)); +} + +#endif /* !_PCI_IOV_H_ */ diff --git a/sys/dev/pci/pci_iov_if.m b/sys/dev/pci/pci_iov_if.m new file mode 100644 index 000000000000..3b6796badcec --- /dev/null +++ b/sys/dev/pci/pci_iov_if.m @@ -0,0 +1,52 @@ +#- +# Copyright (c) 2013-2015 Sandvine Inc. +# 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$ +# + +#include + +INTERFACE pci_iov; + +HEADER { + struct nvlist; +} + + +METHOD int init { + device_t dev; + uint16_t num_vfs; + const struct nvlist *config; +}; + +METHOD void uninit { + device_t dev; +}; + +METHOD int add_vf { + device_t dev; + uint16_t vfnum; + const struct nvlist *config; +}; diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 2fd76b6bf8cd..7f2e95836a30 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -39,8 +39,6 @@ typedef uint64_t pci_addr_t; -struct nvlist; - /* Config registers for PCI-PCI and PCI-Cardbus bridges. */ struct pcicfg_bridge { uint8_t br_seclat; @@ -536,19 +534,6 @@ pci_child_added(device_t dev) return (PCI_CHILD_ADDED(device_get_parent(dev), dev)); } -static __inline int -pci_iov_attach(device_t dev, struct nvlist *pf_schema, struct nvlist *vf_schema) -{ - return (PCI_IOV_ATTACH(device_get_parent(dev), dev, pf_schema, - vf_schema)); -} - -static __inline int -pci_iov_detach(device_t dev) -{ - return (PCI_IOV_DETACH(device_get_parent(dev), dev)); -} - device_t pci_find_bsf(uint8_t, uint8_t, uint8_t); device_t pci_find_dbsf(uint32_t, uint8_t, uint8_t, uint8_t); device_t pci_find_device(uint16_t, uint16_t); diff --git a/sys/modules/ixl/Makefile b/sys/modules/ixl/Makefile old mode 100755 new mode 100644 index 7d2fca994d0b..13be8ab6fc4c --- a/sys/modules/ixl/Makefile +++ b/sys/modules/ixl/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../dev/ixl KMOD = if_ixl -SRCS = device_if.h bus_if.h pci_if.h opt_bdg.h +SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h opt_bdg.h SRCS += opt_inet.h opt_inet6.h opt_rss.h SRCS += if_ixl.c ixl_txrx.c i40e_osdep.c From 48b4aaac1c6732be629fabc9564ae6276fa46afa Mon Sep 17 00:00:00 2001 From: brooks Date: Thu, 28 May 2015 22:06:05 +0000 Subject: [PATCH 42/65] Revert r102953 The bitfile padding was always unallocated on real-world FreeBSD systems and depended on the assumption that (abs(sizeof(long) - sizeof(char*)) <= 32). Differential Revision: https://reviews.freebsd.org/D2667 Reviewed by: eadler Sponsored by: DARPA, AFRL --- sys/sys/nlist_aout.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/sys/nlist_aout.h b/sys/sys/nlist_aout.h index fc7a3c781c57..cb3dd8591252 100644 --- a/sys/sys/nlist_aout.h +++ b/sys/sys/nlist_aout.h @@ -56,8 +56,6 @@ struct nlist { } n_un; #else const char *n_name; /* symbol name (in memory) */ - int : 8 * (sizeof(long) > sizeof(char *) ? - sizeof(long) - sizeof(char *) : sizeof(char *) - sizeof(long)); #endif unsigned char n_type; /* type defines */ char n_other; /* ".type" and binding information */ From 7861506d9f81a298829d6dba53c4223204277a34 Mon Sep 17 00:00:00 2001 From: gjb Date: Fri, 29 May 2015 02:15:05 +0000 Subject: [PATCH 43/65] Sort configuration options for consistency with other boards. MFC after: 3 days Sponsored by: The FreeBSD Foundation --- release/arm/PANDABOARD.conf | 2 +- release/arm/RPI2.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release/arm/PANDABOARD.conf b/release/arm/PANDABOARD.conf index b5a120e9041b..6b75566319f8 100644 --- a/release/arm/PANDABOARD.conf +++ b/release/arm/PANDABOARD.conf @@ -8,13 +8,13 @@ EMBEDDED_TARGET="arm" EMBEDDED_TARGET_ARCH="armv6" EMBEDDEDPORTS="sysutils/u-boot-pandaboard" KERNEL="PANDABOARD" -NODOC=1 WORLD_FLAGS="${WORLD_FLAGS} UBLDR_LOADADDR=0x88000000" IMAGE_SIZE="1G" PART_SCHEME="MBR" FAT_SIZE="2m" FAT_TYPE="12" MD_ARGS="-x 63 -y 255" +NODOC=1 arm_install_uboot() { UBOOT_DIR="/usr/local/share/u-boot/u-boot-pandaboard" diff --git a/release/arm/RPI2.conf b/release/arm/RPI2.conf index e1d15d124425..2da7e96988b1 100644 --- a/release/arm/RPI2.conf +++ b/release/arm/RPI2.conf @@ -8,13 +8,13 @@ EMBEDDED_TARGET="arm" EMBEDDED_TARGET_ARCH="armv6" EMBEDDEDPORTS="sysutils/u-boot-rpi2" KERNEL="RPI2" -NODOC=1 WORLD_FLAGS="${WORLD_FLAGS} UBLDR_LOADADDR=0x2000000" IMAGE_SIZE="1G" PART_SCHEME="MBR" FAT_SIZE="50m" FAT_TYPE="16" MD_ARGS="-x 63 -y 255" +NODOC=1 arm_install_uboot() { UBOOT_DIR="/usr/local/share/u-boot/u-boot-rpi2" From 5ef8cb28c14a8a93f2b09b51b83086dca54dfc41 Mon Sep 17 00:00:00 2001 From: gjb Date: Fri, 29 May 2015 02:16:40 +0000 Subject: [PATCH 44/65] Export 'BOARDNAME' when differs from the KERNCONF. MFC after: 3 days Sponsored by: The FreeBSD Foundation --- release/arm/WANDBOARD.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/release/arm/WANDBOARD.conf b/release/arm/WANDBOARD.conf index 42b452310a16..7ea3807a9dbd 100644 --- a/release/arm/WANDBOARD.conf +++ b/release/arm/WANDBOARD.conf @@ -15,6 +15,7 @@ FAT_SIZE="50m -b 16384" FAT_TYPE="16" MD_ARGS="-x 63 -y 255" NODOC=1 +export BOARDNAME="WANDBOARD" arm_install_uboot() { UBOOT_DIR="/usr/local/share/u-boot/u-boot-wandboard" From 6c7b64f2db6789364fc45e59f52141640f57fad4 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Fri, 29 May 2015 05:28:24 +0000 Subject: [PATCH 45/65] acpi_ibm: add per-model default events mask. Add support for the hotkeys on a Lenovo X1 3rd gen. This also enables event reporting by default. --- sys/dev/acpi_support/acpi_ibm.c | 57 +++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c index c2f90d1d4bce..11636815c318 100644 --- a/sys/dev/acpi_support/acpi_ibm.c +++ b/sys/dev/acpi_support/acpi_ibm.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include +#include #include #include #include @@ -261,6 +262,37 @@ static struct { { NULL, 0, NULL, 0 } }; +/* + * Per-model default list of event mask. + */ +#define ACPI_IBM_HKEY_RFKILL_MASK (1 << 4) +#define ACPI_IBM_HKEY_DSWITCH_MASK (1 << 6) +#define ACPI_IBM_HKEY_BRIGHTNESS_UP_MASK (1 << 15) +#define ACPI_IBM_HKEY_BRIGHTNESS_DOWN_MASK (1 << 16) +#define ACPI_IBM_HKEY_SEARCH_MASK (1 << 18) +#define ACPI_IBM_HKEY_MICMUTE_MASK (1 << 26) +#define ACPI_IBM_HKEY_SETTINGS_MASK (1 << 28) +#define ACPI_IBM_HKEY_VIEWOPEN_MASK (1 << 30) +#define ACPI_IBM_HKEY_VIEWALL_MASK (1 << 31) + +struct acpi_ibm_models { + const char *maker; + const char *product; + uint32_t eventmask; +} acpi_ibm_models[] = { + { "LENOVO", "20BSCTO1WW", + ACPI_IBM_HKEY_RFKILL_MASK | + ACPI_IBM_HKEY_DSWITCH_MASK | + ACPI_IBM_HKEY_BRIGHTNESS_UP_MASK | + ACPI_IBM_HKEY_BRIGHTNESS_DOWN_MASK | + ACPI_IBM_HKEY_SEARCH_MASK | + ACPI_IBM_HKEY_MICMUTE_MASK | + ACPI_IBM_HKEY_SETTINGS_MASK | + ACPI_IBM_HKEY_VIEWOPEN_MASK | + ACPI_IBM_HKEY_VIEWALL_MASK + } +}; + ACPI_SERIAL_DECL(ibm, "ACPI IBM extras"); static int acpi_ibm_probe(device_t dev); @@ -354,7 +386,9 @@ acpi_ibm_probe(device_t dev) static int acpi_ibm_attach(device_t dev) { + int i; struct acpi_ibm_softc *sc; + char *maker, *product; devclass_t ec_devclass; ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); @@ -448,6 +482,27 @@ acpi_ibm_attach(device_t dev) sc->led_dev = led_create_state(ibm_led, sc, "thinklight", (sc->light_val ? 1 : 0)); + /* Enable per-model events. */ + maker = kern_getenv("smbios.system.maker"); + product = kern_getenv("smbios.system.product"); + for (i = 0; i < nitems(acpi_ibm_models); i++) { + if (strcmp(maker, acpi_ibm_models[i].maker) == 0 && + strcmp(product, acpi_ibm_models[i].product) == 0) { + ACPI_SERIAL_BEGIN(ibm); + acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, + acpi_ibm_models[i].eventmask); + ACPI_SERIAL_END(ibm); + } + } + freeenv(maker); + freeenv(product); + + /* Enable events by default. */ + ACPI_SERIAL_BEGIN(ibm); + acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTS, 1); + ACPI_SERIAL_END(ibm); + + return (0); } @@ -770,7 +825,6 @@ acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method) switch (method) { case ACPI_IBM_METHOD_EVENTS: - /* Events are disabled by default */ return (TRUE); case ACPI_IBM_METHOD_EVENTMASK: @@ -1229,7 +1283,6 @@ acpi_ibm_notify(ACPI_HANDLE h, UINT32 notify, void *context) for (;;) { acpi_GetInteger(acpi_get_handle(dev), IBM_NAME_EVENTS_GET, &event); - if (event == 0) break; From d46efc22146351599cd9294a2646ec8d41fe979d Mon Sep 17 00:00:00 2001 From: arybchik Date: Fri, 29 May 2015 05:44:56 +0000 Subject: [PATCH 46/65] sfxge: do not use DEBUG_FLAGS to enable extra debug checks DEBUG_FLAGS are set to DEBUG option value when kernel is built. For example, it is -g in GENERIC config to have debug symbols. Also DEBUG_FLAGS are used to determine if ctfconvert should keep debug symbols. Since we redefined DEBUG_FLAGS, debug symbols were always missing. ctfconvert complains about it during kernel build. It is incorrect to append DEBUG_FLAGS, since if DEBUG has no -g (or similar), we'll have no debug symbols and ctfconvert will complain. If it incorrect to always have -g in our DEBUG_FLAGS, since debug symbols presence should be controllable by kernel config. So, just add disabled by default addition of -DDEBUG=1 to CFLAGS. Reviewed by: imp Sponsored by: Solarflare Communications, Inc. MFC after: 2 days Differential Revision: https://reviews.freebsd.org/D2666 --- sys/dev/sfxge/sfxge_version.h | 2 +- sys/modules/sfxge/Makefile | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/dev/sfxge/sfxge_version.h b/sys/dev/sfxge/sfxge_version.h index 5228fff0e5ec..f5f4882b47d8 100644 --- a/sys/dev/sfxge/sfxge_version.h +++ b/sys/dev/sfxge/sfxge_version.h @@ -36,6 +36,6 @@ #ifndef _SFXGE_VERSION_H #define _SFXGE_VERSION_H -#define SFXGE_VERSION_STRING "v4.5.1.1018" +#define SFXGE_VERSION_STRING "v4.5.2.1000" #endif /* _SFXGE_DRIVER_VERSION_H */ diff --git a/sys/modules/sfxge/Makefile b/sys/modules/sfxge/Makefile index 31d91be9ec9f..b2116d8e7e97 100644 --- a/sys/modules/sfxge/Makefile +++ b/sys/modules/sfxge/Makefile @@ -34,6 +34,7 @@ SRCS+= hunt_nvram.c hunt_rx.c hunt_phy.c hunt_sram.c hunt_tx.c hunt_vpd.c SRCS+= hunt_filter.c SRCS+= hunt_impl.h -DEBUG_FLAGS= -DDEBUG=1 +# Extra debug checks +#CFLAGS += -DDEBUG=1 .include From 410750a368491570655c5269cdb7ed58dc4d25e9 Mon Sep 17 00:00:00 2001 From: dchagin Date: Fri, 29 May 2015 05:46:58 +0000 Subject: [PATCH 47/65] Move linux64 and linux_common to it's right place and make them not depend on bhyve. Submitted by: Oliver Pinter --- sys/modules/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/modules/Makefile b/sys/modules/Makefile index c0217cc8c598..0c2d94e71f9e 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -517,6 +517,7 @@ _ixv= ixv _linprocfs= linprocfs _linsysfs= linsysfs _linux= linux +_linux_common= linux_common .if ${MK_OFED} != "no" _linuxapi= linuxapi .endif @@ -621,6 +622,7 @@ _x86bios= x86bios .if ${MACHINE_CPUARCH} == "amd64" _ixl= ixl _ixlv= ixlv +_linux64= linux64 _ntb= ntb _qlxge= qlxge _qlxgb= qlxgb @@ -629,8 +631,6 @@ _sfxge= sfxge .if ${MK_BHYVE} != "no" || defined(ALL_MODULES) _vmm= vmm -_linux_common= linux_common -_linux64= linux64 .endif .endif From 7df70b740f3dbe5105c0069882e59ca84d99df5e Mon Sep 17 00:00:00 2001 From: dchagin Date: Fri, 29 May 2015 05:50:33 +0000 Subject: [PATCH 48/65] The linux_common module only for 64bit Linuxulators. Its my fault. --- sys/modules/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 0c2d94e71f9e..7091c3ce0a24 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -517,7 +517,6 @@ _ixv= ixv _linprocfs= linprocfs _linsysfs= linsysfs _linux= linux -_linux_common= linux_common .if ${MK_OFED} != "no" _linuxapi= linuxapi .endif @@ -623,6 +622,7 @@ _x86bios= x86bios _ixl= ixl _ixlv= ixlv _linux64= linux64 +_linux_common= linux_common _ntb= ntb _qlxge= qlxge _qlxgb= qlxgb From e78026ed4c85b68858dd06f087f2b2252a19a8c6 Mon Sep 17 00:00:00 2001 From: tuexen Date: Fri, 29 May 2015 08:31:15 +0000 Subject: [PATCH 49/65] Remove printf() noise... MFC after: 3 days --- sys/netinet/sctp_output.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index d2ada5d7fcb5..515ee130aa29 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -3160,8 +3160,6 @@ again_with_private_addresses_allowed: sifa = NULL; continue; } - } else { - SCTP_PRINTF("Stcb is null - no print\n"); } atomic_add_int(&sifa->refcount, 1); goto out; From 7856dd8122c785631fb89280aaf2b183f5a01b0a Mon Sep 17 00:00:00 2001 From: kib Date: Fri, 29 May 2015 09:17:59 +0000 Subject: [PATCH 50/65] Explicitely enable queued invalidation completion interrupt when the queue is started, not relying on the interrupt remaping method to happen. Also disable interrupts when shooting down the queue. Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/x86/iommu/intel_qi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/x86/iommu/intel_qi.c b/sys/x86/iommu/intel_qi.c index ce7b041d24c1..293e2be32a9f 100644 --- a/sys/x86/iommu/intel_qi.c +++ b/sys/x86/iommu/intel_qi.c @@ -411,6 +411,7 @@ dmar_init_qi(struct dmar_unit *unit) ics = DMAR_ICS_IWC; dmar_write4(unit, DMAR_ICS_REG, ics); } + dmar_enable_qi_intr(unit); DMAR_UNLOCK(unit); return (0); @@ -434,6 +435,7 @@ dmar_fini_qi(struct dmar_unit *unit) dmar_qi_advance_tail(unit); dmar_qi_wait_for_seq(unit, &gseq, false); /* only after the quisce, disable queue */ + dmar_disable_qi_intr(unit); dmar_disable_qi(unit); KASSERT(unit->inv_seq_waiters == 0, ("dmar%d: waiters on disabled queue", unit->unit)); From ac994cae1dd37f33737245b73c93680c33390f95 Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 29 May 2015 09:23:20 +0000 Subject: [PATCH 51/65] Fix __isinfl on architectures where double == long double. This is the case on at least ARM and PowerPC. MFC after: 1 week --- lib/libc/gen/isinf.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/libc/gen/isinf.c b/lib/libc/gen/isinf.c index 4a4152a5a032..0eb8b9f13ccb 100644 --- a/lib/libc/gen/isinf.c +++ b/lib/libc/gen/isinf.c @@ -26,6 +26,8 @@ * $FreeBSD$ */ +#include + #include #include "fpmath.h" @@ -62,9 +64,9 @@ __isinfl(long double e) u.e = e; mask_nbit_l(u); -#ifndef __alpha__ - return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0); -#else +#if LDBL_MANT_DIG == 53 return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0); +#else + return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0); #endif } From 665a8e93e63df1276d15a72d6027f1568fa4f77b Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 29 May 2015 09:26:10 +0000 Subject: [PATCH 52/65] Fix __fpclassifyl when double == long double. As with r283693 this is needed on ARM and PowerPC. MFC after: 1 Week --- lib/libc/gen/fpclassify.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/libc/gen/fpclassify.c b/lib/libc/gen/fpclassify.c index 754a1df50a2f..444b5513ddf4 100644 --- a/lib/libc/gen/fpclassify.c +++ b/lib/libc/gen/fpclassify.c @@ -29,6 +29,8 @@ #include +#include + #include #include @@ -84,10 +86,18 @@ __fpclassifyl(long double e) return (FP_SUBNORMAL); } mask_nbit_l(u); /* Mask normalization bit if applicable. */ +#if LDBL_MANT_DIG == 53 + if (u.bits.exp == 2047) { + if ((u.bits.manl | u.bits.manh) == 0) + return (FP_INFINITE); + return (FP_NAN); + } +#else if (u.bits.exp == 32767) { if ((u.bits.manl | u.bits.manh) == 0) return (FP_INFINITE); return (FP_NAN); } +#endif return (FP_NORMAL); } From 3a4c3ed84fbd303c0b76173fe4691ac663da9f2e Mon Sep 17 00:00:00 2001 From: bapt Date: Fri, 29 May 2015 10:07:20 +0000 Subject: [PATCH 53/65] Remove dead declaration PR: 195928 MFC after: 2 days --- usr.sbin/pw/pwupd.h | 1 - 1 file changed, 1 deletion(-) diff --git a/usr.sbin/pw/pwupd.h b/usr.sbin/pw/pwupd.h index d6e39ce99b0e..1d135117bc56 100644 --- a/usr.sbin/pw/pwupd.h +++ b/usr.sbin/pw/pwupd.h @@ -93,7 +93,6 @@ char * getpwpath(char const * file); int addgrent(struct group * grp); int delgrent(struct group * grp); int chggrent(char const * name, struct group * grp); -int editgroups(char *name, char **groups); int setgrdir(const char * dir); char * getgrpath(const char *file); From a1e13e9e590c569e31b8bf4ccd7679b392a2d815 Mon Sep 17 00:00:00 2001 From: ae Date: Fri, 29 May 2015 10:24:16 +0000 Subject: [PATCH 54/65] Move RTM announces into generic code to be independent from Layer2 code. This fixes bug introduced in 274988, when announces about new addresses don't sent for tunneling interfaces. Reported by: tuexen@ MFC after: 1 week --- sys/netinet6/in6.c | 2 ++ sys/netinet6/nd6.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index d2570c4a2b1b..fe98f0c8c51c 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1279,6 +1279,7 @@ in6_broadcast_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, nd6_dad_start((struct ifaddr *)ia, delay); } + in6_newaddrmsg(ia, RTM_ADD); ifa_free(&ia->ia_ifa); return (error); } @@ -1327,6 +1328,7 @@ in6_purgeaddr(struct ifaddr *ifa) ia->ia_flags &= ~IFA_ROUTE; } + in6_newaddrmsg(ia, RTM_DELETE); in6_unlink_ifa(ia, ifp); } diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 83dda1a18427..daac188f5812 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -2185,7 +2185,6 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia) ln->la_expire = 0; /* for IPv6 this means permanent */ ln->ln_state = ND6_LLINFO_REACHABLE; LLE_WUNLOCK(ln); - in6_newaddrmsg(ia, RTM_ADD); return (0); } @@ -2205,8 +2204,6 @@ nd6_rem_ifa_lle(struct in6_ifaddr *ia) struct sockaddr_in6 mask, addr; struct ifnet *ifp; - in6_newaddrmsg(ia, RTM_DELETE); - ifp = ia->ia_ifa.ifa_ifp; memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr)); memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask)); From e2f56205b5cb974ce90bb8e1753845d84f4401cf Mon Sep 17 00:00:00 2001 From: kib Date: Fri, 29 May 2015 13:24:17 +0000 Subject: [PATCH 55/65] Remove several write-only variables, all reported by the gcc 4.9 buildkernel run. Some of them were write-only under some kernel options, e.g. variables keeping values only used by CTR() macros. It costs nothing to the code readability and correctness to eliminate the warnings in those cases too by removing the local cached values used only for single-access. Review: https://reviews.freebsd.org/D2665 Reviewed by: rodrigc Looked at by: bjk Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/amd64/amd64/pmap.c | 6 ++---- sys/amd64/amd64/vm_machdep.c | 2 -- sys/amd64/ia32/ia32_reg.c | 6 +----- sys/dev/pci/pci.c | 14 +++++--------- sys/kern/kern_exit.c | 2 -- sys/kern/kern_synch.c | 6 ++---- sys/kern/vfs_cluster.c | 2 -- sys/kern/vfs_init.c | 4 +--- sys/ufs/ffs/ffs_softdep.c | 6 ------ sys/ufs/ffs/ffs_suspend.c | 2 -- sys/ufs/ffs/ffs_vfsops.c | 10 ++-------- sys/ufs/ffs/ffs_vnops.c | 14 -------------- sys/ufs/ufs/ufs_bmap.c | 2 -- sys/ufs/ufs/ufs_dirhash.c | 4 ---- sys/x86/iommu/busdma_dmar.c | 4 ---- sys/x86/iommu/intel_idpgtbl.c | 8 +++----- 16 files changed, 16 insertions(+), 76 deletions(-) diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 5f9ee9166286..7f256cd5bd4e 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -3935,7 +3935,6 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, pd_entry_t newpde; pt_entry_t *firstpte, oldpte, pa, *pte; pt_entry_t PG_G, PG_A, PG_M, PG_RW, PG_V; - vm_offset_t oldpteva; vm_page_t mpte; int PG_PTE_CACHE; @@ -3995,10 +3994,9 @@ setpte: if (!atomic_cmpset_long(pte, oldpte, oldpte & ~PG_RW)) goto setpte; oldpte &= ~PG_RW; - oldpteva = (oldpte & PG_FRAME & PDRMASK) | - (va & ~PDRMASK); CTR2(KTR_PMAP, "pmap_promote_pde: protect for va %#lx" - " in pmap %p", oldpteva, pmap); + " in pmap %p", (oldpte & PG_FRAME & PDRMASK) | + (va & ~PDRMASK), pmap); } if ((oldpte & PG_PTE_PROMOTE) != (newpde & PG_PTE_PROMOTE)) { atomic_add_long(&pmap_pde_p_failures, 1); diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c index 0d03ed60a425..1fb701611392 100644 --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -155,7 +155,6 @@ cpu_fork(td1, p2, td2, flags) struct pcb *pcb2; struct mdproc *mdp1, *mdp2; struct proc_ldt *pldt; - pmap_t pmap2; p1 = td1->td_proc; if ((flags & RFPROC) == 0) { @@ -218,7 +217,6 @@ cpu_fork(td1, p2, td2, flags) * Set registers for trampoline to user mode. Leave space for the * return address on stack. These are the kernel mode register values. */ - pmap2 = vmspace_pmap(p2->p_vmspace); pcb2->pcb_r12 = (register_t)fork_return; /* fork_trampoline argument */ pcb2->pcb_rbp = 0; pcb2->pcb_rsp = (register_t)td2->td_frame - sizeof(void *); diff --git a/sys/amd64/ia32/ia32_reg.c b/sys/amd64/ia32/ia32_reg.c index 5bc18f12118a..d0e6bfe1318c 100644 --- a/sys/amd64/ia32/ia32_reg.c +++ b/sys/amd64/ia32/ia32_reg.c @@ -79,11 +79,9 @@ __FBSDID("$FreeBSD$"); int fill_regs32(struct thread *td, struct reg32 *regs) { - struct pcb *pcb; struct trapframe *tp; tp = td->td_frame; - pcb = td->td_pcb; if (tp->tf_flags & TF_HASSEGS) { regs->r_gs = tp->tf_gs; regs->r_fs = tp->tf_fs; @@ -113,18 +111,16 @@ fill_regs32(struct thread *td, struct reg32 *regs) int set_regs32(struct thread *td, struct reg32 *regs) { - struct pcb *pcb; struct trapframe *tp; tp = td->td_frame; if (!EFL_SECURE(regs->r_eflags, tp->tf_rflags) || !CS_SECURE(regs->r_cs)) return (EINVAL); - pcb = td->td_pcb; tp->tf_gs = regs->r_gs; tp->tf_fs = regs->r_fs; tp->tf_es = regs->r_es; tp->tf_ds = regs->r_ds; - set_pcb_flags(pcb, PCB_FULL_IRET); + set_pcb_flags(td->td_pcb, PCB_FULL_IRET); tp->tf_flags = TF_HASSEGS; tp->tf_rdi = regs->r_edi; tp->tf_rsi = regs->r_esi; diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index b4c6151210db..98b6b53a0724 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -2389,7 +2389,7 @@ pci_set_powerstate_method(device_t dev, device_t child, int state) struct pci_devinfo *dinfo = device_get_ivars(child); pcicfgregs *cfg = &dinfo->cfg; uint16_t status; - int result, oldstate, highest, delay; + int oldstate, highest, delay; if (cfg->pp.pp_cap == 0) return (EOPNOTSUPP); @@ -2424,7 +2424,6 @@ pci_set_powerstate_method(device_t dev, device_t child, int state) delay = 0; status = PCI_READ_CONFIG(dev, child, cfg->pp.pp_status, 2) & ~PCIM_PSTAT_DMASK; - result = 0; switch (state) { case PCI_POWERSTATE_D0: status |= PCIM_PSTAT_D0; @@ -2989,7 +2988,6 @@ static void pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force, uint32_t prefetchmask) { - struct resource *r; int rid, type, progif; #if 0 /* if this device supports PCI native addressing use it */ @@ -3012,11 +3010,11 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force, } else { rid = PCIR_BAR(0); resource_list_add(rl, type, rid, 0x1f0, 0x1f7, 8); - r = resource_list_reserve(rl, bus, dev, type, &rid, 0x1f0, + (void)resource_list_reserve(rl, bus, dev, type, &rid, 0x1f0, 0x1f7, 8, 0); rid = PCIR_BAR(1); resource_list_add(rl, type, rid, 0x3f6, 0x3f6, 1); - r = resource_list_reserve(rl, bus, dev, type, &rid, 0x3f6, + (void)resource_list_reserve(rl, bus, dev, type, &rid, 0x3f6, 0x3f6, 1, 0); } if (progif & PCIP_STORAGE_IDE_MODESEC) { @@ -3027,11 +3025,11 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force, } else { rid = PCIR_BAR(2); resource_list_add(rl, type, rid, 0x170, 0x177, 8); - r = resource_list_reserve(rl, bus, dev, type, &rid, 0x170, + (void)resource_list_reserve(rl, bus, dev, type, &rid, 0x170, 0x177, 8, 0); rid = PCIR_BAR(3); resource_list_add(rl, type, rid, 0x376, 0x376, 1); - r = resource_list_reserve(rl, bus, dev, type, &rid, 0x376, + (void)resource_list_reserve(rl, bus, dev, type, &rid, 0x376, 0x376, 1, 0); } pci_add_map(bus, dev, PCIR_BAR(4), rl, force, @@ -3727,7 +3725,6 @@ pci_detach(device_t dev) static void pci_set_power_child(device_t dev, device_t child, int state) { - struct pci_devinfo *dinfo; device_t pcib; int dstate; @@ -3739,7 +3736,6 @@ pci_set_power_child(device_t dev, device_t child, int state) * are handled separately. */ pcib = device_get_parent(dev); - dinfo = device_get_ivars(child); dstate = state; if (device_is_attached(child) && PCIB_POWER_FOR_SLEEP(pcib, child, &dstate) == 0) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index a2742c2cb8e3..9ce6d343c1f4 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -964,12 +964,10 @@ proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id, int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo, int check_only) { - struct proc *q; struct rusage *rup; sx_assert(&proctree_lock, SA_XLOCKED); - q = td->td_proc; PROC_LOCK(p); switch (idtype) { diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index e0ee2dc0dc86..8c847736f9da 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -414,11 +414,9 @@ mi_switch(int flags, struct thread *newtd) { uint64_t runtime, new_switchtime; struct thread *td; - struct proc *p; td = curthread; /* XXX */ THREAD_LOCK_ASSERT(td, MA_OWNED | MA_NOTRECURSED); - p = td->td_proc; /* XXX */ KASSERT(!TD_ON_RUNQ(td), ("mi_switch: called by old code")); #ifdef INVARIANTS if (!TD_ON_LOCK(td) && !TD_IS_RUNNING(td)) @@ -458,7 +456,7 @@ mi_switch(int flags, struct thread *newtd) PCPU_INC(cnt.v_swtch); PCPU_SET(switchticks, ticks); CTR4(KTR_PROC, "mi_switch: old thread %ld (td_sched %p, pid %ld, %s)", - td->td_tid, td->td_sched, p->p_pid, td->td_name); + td->td_tid, td->td_sched, td->td_proc->p_pid, td->td_name); #if (KTR_COMPILE & KTR_SCHED) != 0 if (TD_IS_IDLETHREAD(td)) KTR_STATE1(KTR_SCHED, "thread", sched_tdname(td), "idle", @@ -474,7 +472,7 @@ mi_switch(int flags, struct thread *newtd) "prio:%d", td->td_priority); CTR4(KTR_PROC, "mi_switch: new thread %ld (td_sched %p, pid %ld, %s)", - td->td_tid, td->td_sched, p->p_pid, td->td_name); + td->td_tid, td->td_sched, td->td_proc->p_pid, td->td_name); /* * If the last thread was exiting, finish cleaning it up. diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 960108253e72..362ebb7ba671 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -310,7 +310,6 @@ static struct buf * cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn, daddr_t blkno, long size, int run, int gbflags, struct buf *fbp) { - struct bufobj *bo; struct buf *bp, *tbp; daddr_t bn; off_t off; @@ -376,7 +375,6 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn, bp->b_npages = 0; inc = btodb(size); - bo = &vp->v_bufobj; for (bn = blkno, i = 0; i < run; ++i, bn += inc) { if (i == 0) { VM_OBJECT_WLOCK(tbp->b_bufobj->bo_object); diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index cf3928ee91e4..f935954fcef2 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -311,9 +311,7 @@ static int vfs_unregister(struct vfsconf *vfc) { struct vfsconf *vfsp; - int error, i, maxtypenum; - - i = vfc->vfc_typenum; + int error, maxtypenum; vfsconf_lock(); vfsp = vfs_byname_locked(vfc->vfc_name); diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index b0005f1d2b2c..515857d59221 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -4691,12 +4691,10 @@ softdep_setup_dotdot_link(dp, ip) struct inodedep *inodedep; struct jaddref *jaddref; struct vnode *dvp; - struct vnode *vp; KASSERT(MOUNTEDSOFTDEP(UFSTOVFS(dp->i_ump)) != 0, ("softdep_setup_dotdot_link called on non-softdep filesystem")); dvp = ITOV(dp); - vp = ITOV(ip); jaddref = NULL; /* * We don't set MKDIR_PARENT as this is not tied to a mkdir and @@ -7052,7 +7050,6 @@ trunc_dependencies(ip, freeblks, lastlbn, lastoff, flags) struct bufobj *bo; struct vnode *vp; struct buf *bp; - struct fs *fs; int blkoff; /* @@ -7061,7 +7058,6 @@ trunc_dependencies(ip, freeblks, lastlbn, lastoff, flags) * Once they are all there, walk the list and get rid of * any dependencies. */ - fs = ip->i_fs; vp = ITOV(ip); bo = &vp->v_bufobj; BO_LOCK(bo); @@ -9493,12 +9489,10 @@ handle_written_sbdep(sbdep, bp) struct buf *bp; { struct inodedep *inodedep; - struct mount *mp; struct fs *fs; LOCK_OWNED(sbdep->sb_ump); fs = sbdep->sb_fs; - mp = UFSTOVFS(sbdep->sb_ump); /* * If the superblock doesn't match the in-memory list start over. */ diff --git a/sys/ufs/ffs/ffs_suspend.c b/sys/ufs/ffs/ffs_suspend.c index b50fadcf3fa1..450282ceb179 100644 --- a/sys/ufs/ffs/ffs_suspend.c +++ b/sys/ufs/ffs/ffs_suspend.c @@ -177,7 +177,6 @@ out: static int ffs_susp_suspend(struct mount *mp) { - struct fs *fs; struct ufsmount *ump; int error; @@ -189,7 +188,6 @@ ffs_susp_suspend(struct mount *mp) return (EBUSY); ump = VFSTOUFS(mp); - fs = ump->um_fs; /* * Make sure the calling thread is permitted to access the mounted diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 2a368bd980fb..ce43bcd8a6ab 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1486,7 +1486,7 @@ ffs_sync(mp, waitfor) struct inode *ip; struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; - int error, count, wait, lockreq, allerror = 0; + int error, count, lockreq, allerror = 0; int suspend; int suspended; int secondary_writes; @@ -1495,7 +1495,6 @@ ffs_sync(mp, waitfor) int softdep_accdeps; struct bufobj *bo; - wait = 0; suspend = 0; suspended = 0; td = curthread; @@ -1517,10 +1516,8 @@ ffs_sync(mp, waitfor) suspend = 1; waitfor = MNT_WAIT; } - if (waitfor == MNT_WAIT) { - wait = 1; + if (waitfor == MNT_WAIT) lockreq = LK_EXCLUSIVE; - } lockreq |= LK_INTERLOCK | LK_SLEEPFAIL; loop: /* Grab snapshot of secondary write counts */ @@ -2024,7 +2021,6 @@ static int ffs_bufwrite(struct buf *bp) { struct buf *newbp; - int oldflags; CTR3(KTR_BUF, "bufwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); if (bp->b_flags & B_INVAL) { @@ -2032,8 +2028,6 @@ ffs_bufwrite(struct buf *bp) return (0); } - oldflags = bp->b_flags; - if (!BUF_ISLOCKED(bp)) panic("bufwrite: buffer is not busy???"); /* diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 6b34a40256d2..80f32697d820 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -1366,11 +1366,6 @@ struct vop_openextattr_args { }; */ { - struct inode *ip; - struct fs *fs; - - ip = VTOI(ap->a_vp); - fs = ip->i_fs; if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) return (EOPNOTSUPP); @@ -1394,11 +1389,6 @@ struct vop_closeextattr_args { }; */ { - struct inode *ip; - struct fs *fs; - - ip = VTOI(ap->a_vp); - fs = ip->i_fs; if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) return (EOPNOTSUPP); @@ -1512,13 +1502,11 @@ vop_getextattr { */ { struct inode *ip; - struct fs *fs; u_char *eae, *p; unsigned easize; int error, ealen; ip = VTOI(ap->a_vp); - fs = ip->i_fs; if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) return (EOPNOTSUPP); @@ -1567,14 +1555,12 @@ vop_listextattr { */ { struct inode *ip; - struct fs *fs; u_char *eae, *p, *pe, *pn; unsigned easize; uint32_t ul; int error, ealen; ip = VTOI(ap->a_vp); - fs = ip->i_fs; if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) return (EOPNOTSUPP); diff --git a/sys/ufs/ufs/ufs_bmap.c b/sys/ufs/ufs/ufs_bmap.c index 22887c8ad9be..9819ef5eb8e5 100644 --- a/sys/ufs/ufs/ufs_bmap.c +++ b/sys/ufs/ufs/ufs_bmap.c @@ -114,7 +114,6 @@ ufs_bmaparray(vp, bn, bnp, nbp, runp, runb) struct buf *bp; struct ufsmount *ump; struct mount *mp; - struct vnode *devvp; struct indir a[NIADDR+1], *ap; ufs2_daddr_t daddr; ufs_lbn_t metalbn; @@ -125,7 +124,6 @@ ufs_bmaparray(vp, bn, bnp, nbp, runp, runb) ip = VTOI(vp); mp = vp->v_mount; ump = VFSTOUFS(mp); - devvp = ump->um_devvp; if (runp) { maxrun = mp->mnt_iosize_max / mp->mnt_stat.f_iosize - 1; diff --git a/sys/ufs/ufs/ufs_dirhash.c b/sys/ufs/ufs/ufs_dirhash.c index 39f29d09b1fb..766fe54b8997 100644 --- a/sys/ufs/ufs/ufs_dirhash.c +++ b/sys/ufs/ufs/ufs_dirhash.c @@ -190,9 +190,7 @@ ufsdirhash_create(struct inode *ip) struct dirhash *ndh; struct dirhash *dh; struct vnode *vp; - int error; - error = 0; ndh = dh = NULL; vp = ip->i_vnode; for (;;) { @@ -274,11 +272,9 @@ static struct dirhash * ufsdirhash_acquire(struct inode *ip) { struct dirhash *dh; - struct vnode *vp; ASSERT_VOP_ELOCKED(ip->i_vnode, __FUNCTION__); - vp = ip->i_vnode; dh = ip->i_dirhash; if (dh == NULL) return (NULL); diff --git a/sys/x86/iommu/busdma_dmar.c b/sys/x86/iommu/busdma_dmar.c index 96b0bcea394f..3ef81075a349 100644 --- a/sys/x86/iommu/busdma_dmar.c +++ b/sys/x86/iommu/busdma_dmar.c @@ -818,7 +818,6 @@ dmar_bus_task_dmamap(void *arg, int pending) struct bus_dma_tag_dmar *tag; struct bus_dmamap_dmar *map; struct dmar_unit *unit; - struct dmar_ctx *ctx; unit = arg; DMAR_LOCK(unit); @@ -826,7 +825,6 @@ dmar_bus_task_dmamap(void *arg, int pending) TAILQ_REMOVE(&unit->delayed_maps, map, delay_link); DMAR_UNLOCK(unit); tag = map->tag; - ctx = map->tag->ctx; map->cansleep = true; map->locked = false; bus_dmamap_load_mem((bus_dma_tag_t)tag, (bus_dmamap_t)map, @@ -847,9 +845,7 @@ dmar_bus_task_dmamap(void *arg, int pending) static void dmar_bus_schedule_dmamap(struct dmar_unit *unit, struct bus_dmamap_dmar *map) { - struct dmar_ctx *ctx; - ctx = map->tag->ctx; map->locked = false; DMAR_LOCK(unit); TAILQ_INSERT_TAIL(&unit->delayed_maps, map, delay_link); diff --git a/sys/x86/iommu/intel_idpgtbl.c b/sys/x86/iommu/intel_idpgtbl.c index 6621b1720215..b9492dd6456a 100644 --- a/sys/x86/iommu/intel_idpgtbl.c +++ b/sys/x86/iommu/intel_idpgtbl.c @@ -108,7 +108,7 @@ static void ctx_idmap_nextlvl(struct idpgtbl *tbl, int lvl, vm_pindex_t idx, dmar_gaddr_t addr) { - vm_page_t m, m1; + vm_page_t m1; dmar_pte_t *pte; struct sf_buf *sf; dmar_gaddr_t f, pg_sz; @@ -118,7 +118,7 @@ ctx_idmap_nextlvl(struct idpgtbl *tbl, int lvl, vm_pindex_t idx, VM_OBJECT_ASSERT_LOCKED(tbl->pgtbl_obj); if (addr >= tbl->maxaddr) return; - m = dmar_pgalloc(tbl->pgtbl_obj, idx, DMAR_PGF_OBJL | DMAR_PGF_WAITOK | + (void)dmar_pgalloc(tbl->pgtbl_obj, idx, DMAR_PGF_OBJL | DMAR_PGF_WAITOK | DMAR_PGF_ZERO); base = idx * DMAR_NPTEPG + 1; /* Index of the first child page of idx */ pg_sz = pglvl_page_size(tbl->pglvl, lvl); @@ -598,7 +598,7 @@ ctx_unmap_buf_locked(struct dmar_ctx *ctx, dmar_gaddr_t base, dmar_pte_t *pte; struct sf_buf *sf; vm_pindex_t idx; - dmar_gaddr_t pg_sz, base1, size1; + dmar_gaddr_t pg_sz; int lvl; DMAR_CTX_ASSERT_PGLOCKED(ctx); @@ -625,8 +625,6 @@ ctx_unmap_buf_locked(struct dmar_ctx *ctx, dmar_gaddr_t base, KASSERT((flags & ~DMAR_PGF_WAITOK) == 0, ("invalid flags %x", flags)); pg_sz = 0; /* silence gcc */ - base1 = base; - size1 = size; flags |= DMAR_PGF_OBJL; TD_PREP_PINNED_ASSERT; From 565f2a5f315bd7ad69ec0a6844b98d40f04e1896 Mon Sep 17 00:00:00 2001 From: maxim Date: Fri, 29 May 2015 14:02:37 +0000 Subject: [PATCH 56/65] arm64 added to CSCOPE_ARCHDIR. --- sys/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/Makefile b/sys/Makefile index 46d883e1e74d..2475f9f62850 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -8,7 +8,7 @@ CSCOPEDIRS= boot bsm cam cddl compat conf contrib crypto ddb dev fs gdb \ rpc security sys ufs vm xdr xen ${CSCOPE_ARCHDIR} .if !defined(CSCOPE_ARCHDIR) .if defined(ALL_ARCH) -CSCOPE_ARCHDIR = amd64 arm i386 mips pc98 powerpc sparc64 x86 +CSCOPE_ARCHDIR = amd64 arm arm64 i386 mips pc98 powerpc sparc64 x86 .else CSCOPE_ARCHDIR = ${MACHINE} .if ${MACHINE} != ${MACHINE_CPUARCH} From 0c8e8a4de07a4d17f9bcd5a5fa2a8cd2cb503954 Mon Sep 17 00:00:00 2001 From: maxim Date: Fri, 29 May 2015 14:03:07 +0000 Subject: [PATCH 57/65] Kill EoL whitespace. --- sys/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/Makefile b/sys/Makefile index 2475f9f62850..75757463779c 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -10,7 +10,7 @@ CSCOPEDIRS= boot bsm cam cddl compat conf contrib crypto ddb dev fs gdb \ .if defined(ALL_ARCH) CSCOPE_ARCHDIR = amd64 arm arm64 i386 mips pc98 powerpc sparc64 x86 .else -CSCOPE_ARCHDIR = ${MACHINE} +CSCOPE_ARCHDIR = ${MACHINE} .if ${MACHINE} != ${MACHINE_CPUARCH} CSCOPE_ARCHDIR += ${MACHINE_CPUARCH} .endif From 3204066bc60e76bd37da67813fe7ef4d7a76d424 Mon Sep 17 00:00:00 2001 From: glebius Date: Fri, 29 May 2015 14:35:16 +0000 Subject: [PATCH 58/65] Use device_printf() instead of if_printf(). No functional changes. --- sys/dev/ath/ath_rate/sample/sample.c | 13 ++- sys/dev/ath/if_ath.c | 151 ++++++++++++++------------- sys/dev/ath/if_ath_rx.c | 4 +- sys/dev/ath/if_ath_tdma.c | 2 +- sys/dev/ath/if_ath_tx.c | 4 +- 5 files changed, 94 insertions(+), 80 deletions(-) diff --git a/sys/dev/ath/ath_rate/sample/sample.c b/sys/dev/ath/ath_rate/sample/sample.c index 36cd679bc0ba..3606e14c28c3 100644 --- a/sys/dev/ath/ath_rate/sample/sample.c +++ b/sys/dev/ath/ath_rate/sample/sample.c @@ -843,9 +843,11 @@ update_stats(struct ath_softc *sc, struct ath_node *an, } static void -badrate(struct ifnet *ifp, int series, int hwrate, int tries, int status) +badrate(struct ath_softc *sc, int series, int hwrate, int tries, int status) { - if_printf(ifp, "bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n", + + device_printf(sc->sc_dev, + "bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n", series, hwrate, tries, status); } @@ -891,9 +893,10 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, if (!mrr || ts->ts_finaltsi == 0) { if (!IS_RATE_DEFINED(sn, final_rix)) { - device_printf(sc->sc_dev, "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n", + device_printf(sc->sc_dev, + "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n", __func__, ts->ts_rate, ts->ts_finaltsi, final_rix); - badrate(ifp, 0, ts->ts_rate, long_tries, status); + badrate(sc, 0, ts->ts_rate, long_tries, status); return; } /* @@ -945,7 +948,7 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, for (i = 0; i < 4; i++) { if (rc[i].tries && !IS_RATE_DEFINED(sn, rc[i].rix)) - badrate(ifp, 0, rc[i].ratecode, rc[i].tries, + badrate(sc, 0, rc[i].ratecode, rc[i].tries, status); } diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 03c793e0a2f5..4aac93bb0f5b 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -595,7 +595,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ic->ic_softc = sc; ic->ic_name = device_get_nameunit(sc->sc_dev); - /* set these up early for if_printf use */ if_initname(ifp, device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev)); CURVNET_RESTORE(); @@ -612,8 +611,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh, sc->sc_eepromdata, &ah_config, &status); if (ah == NULL) { - if_printf(ifp, "unable to attach hardware; HAL status %u\n", - status); + device_printf(sc->sc_dev, + "unable to attach hardware; HAL status %u\n", status); error = ENXIO; goto bad; } @@ -664,8 +663,9 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) */ sc->sc_keymax = ath_hal_keycachesize(ah); if (sc->sc_keymax > ATH_KEYMAX) { - if_printf(ifp, "Warning, using only %u of %u key cache slots\n", - ATH_KEYMAX, sc->sc_keymax); + device_printf(sc->sc_dev, + "Warning, using only %u of %u key cache slots\n", + ATH_KEYMAX, sc->sc_keymax); sc->sc_keymax = ATH_KEYMAX; } /* @@ -704,14 +704,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) */ error = ath_desc_alloc(sc); if (error != 0) { - if_printf(ifp, "failed to allocate TX descriptors: %d\n", - error); + device_printf(sc->sc_dev, + "failed to allocate TX descriptors: %d\n", error); goto bad; } error = ath_txdma_setup(sc); if (error != 0) { - if_printf(ifp, "failed to allocate TX descriptors: %d\n", - error); + device_printf(sc->sc_dev, + "failed to allocate TX descriptors: %d\n", error); goto bad; } @@ -720,8 +720,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) */ error = ath_rxdma_setup(sc); if (error != 0) { - if_printf(ifp, "failed to allocate RX descriptors: %d\n", - error); + device_printf(sc->sc_dev, + "failed to allocate RX descriptors: %d\n", error); goto bad; } @@ -752,20 +752,22 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) */ sc->sc_bhalq = ath_beaconq_setup(sc); if (sc->sc_bhalq == (u_int) -1) { - if_printf(ifp, "unable to setup a beacon xmit queue!\n"); + device_printf(sc->sc_dev, + "unable to setup a beacon xmit queue!\n"); error = EIO; goto bad2; } sc->sc_cabq = ath_txq_setup(sc, HAL_TX_QUEUE_CAB, 0); if (sc->sc_cabq == NULL) { - if_printf(ifp, "unable to setup CAB xmit queue!\n"); + device_printf(sc->sc_dev, "unable to setup CAB xmit queue!\n"); error = EIO; goto bad2; } /* NB: insure BK queue is the lowest priority h/w queue */ if (!ath_tx_setup(sc, WME_AC_BK, HAL_WME_AC_BK)) { - if_printf(ifp, "unable to setup xmit queue for %s traffic!\n", - ieee80211_wme_acnames[WME_AC_BK]); + device_printf(sc->sc_dev, + "unable to setup xmit queue for %s traffic!\n", + ieee80211_wme_acnames[WME_AC_BK]); error = EIO; goto bad2; } @@ -1828,8 +1830,8 @@ ath_vap_delete(struct ieee80211vap *vap) * be reset if we just destroyed the last vap). */ if (ath_startrecv(sc) != 0) - if_printf(ifp, "%s: unable to restart recv logic\n", - __func__); + device_printf(sc->sc_dev, + "%s: unable to restart recv logic\n", __func__); if (sc->sc_beacons) { /* restart beacons */ #ifdef IEEE80211_SUPPORT_TDMA if (sc->sc_tdma) @@ -2316,7 +2318,7 @@ ath_fatal_proc(void *arg, int pending) u_int32_t len; void *sp; - if_printf(ifp, "hardware error; resetting\n"); + device_printf(sc->sc_dev, "hardware error; resetting\n"); /* * Fatal errors are unrecoverable. Typically these * are caused by DMA errors. Collect h/w state from @@ -2325,9 +2327,9 @@ ath_fatal_proc(void *arg, int pending) if (ath_hal_getfatalstate(sc->sc_ah, &sp, &len)) { KASSERT(len >= 6*sizeof(u_int32_t), ("len %u bytes", len)); state = sp; - if_printf(ifp, "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n", - state[0], state[1] , state[2], state[3], - state[4], state[5]); + device_printf(sc->sc_dev, + "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n", state[0], + state[1] , state[2], state[3], state[4], state[5]); } ath_reset(ifp, ATH_RESET_NOLOSS); } @@ -2434,7 +2436,8 @@ ath_bmiss_proc(void *arg, int pending) */ if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) { ath_reset(ifp, ATH_RESET_NOLOSS); - if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs); + device_printf(sc->sc_dev, + "bb hang detected (0x%x), resetting\n", hangs); } else { ath_reset(ifp, ATH_RESET_NOLOSS); ieee80211_beacon_miss(ifp->if_l2com); @@ -2509,9 +2512,10 @@ ath_init(void *arg) ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, sc->sc_cur_rxchainmask); - if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, &status)) { - if_printf(ifp, "unable to reset hardware; hal status %u\n", - status); + if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, + &status)) { + device_printf(sc->sc_dev, + "unable to reset hardware; hal status %u\n", status); ATH_UNLOCK(sc); return; } @@ -2569,7 +2573,7 @@ ath_init(void *arg) * here except setup the interrupt mask. */ if (ath_startrecv(sc) != 0) { - if_printf(ifp, "unable to start recv logic\n"); + device_printf(sc->sc_dev, "unable to start recv logic\n"); ath_power_restore_power_state(sc); ATH_UNLOCK(sc); return; @@ -2911,8 +2915,9 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, sc->sc_cur_rxchainmask); if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, &status)) - if_printf(ifp, "%s: unable to reset hardware; hal status %u\n", - __func__, status); + device_printf(sc->sc_dev, + "%s: unable to reset hardware; hal status %u\n", + __func__, status); sc->sc_diversity = ath_hal_getdiversity(ah); ATH_RX_LOCK(sc); @@ -2941,7 +2946,8 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ath_hal_setenforcetxop(sc->sc_ah, 0); if (ath_startrecv(sc) != 0) /* restart recv */ - if_printf(ifp, "%s: unable to start recv logic\n", __func__); + device_printf(sc->sc_dev, + "%s: unable to start recv logic\n", __func__); /* * We may be doing a reset in response to an ioctl * that changes the channel so update any state that @@ -3747,7 +3753,7 @@ ath_reset_proc(void *arg, int pending) struct ifnet *ifp = sc->sc_ifp; #if 0 - if_printf(ifp, "%s: resetting\n", __func__); + device_printf(sc->sc_dev, "%s: resetting\n", __func__); #endif ath_reset(ifp, ATH_RESET_NOLOSS); } @@ -3763,15 +3769,15 @@ ath_bstuck_proc(void *arg, int pending) uint32_t hangs = 0; if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) - if_printf(ifp, "bb hang detected (0x%x)\n", hangs); + device_printf(sc->sc_dev, "bb hang detected (0x%x)\n", hangs); #ifdef ATH_DEBUG_ALQ if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_STUCK_BEACON)) if_ath_alq_post(&sc->sc_alq, ATH_ALQ_STUCK_BEACON, 0, NULL); #endif - if_printf(ifp, "stuck beacon; resetting (bmiss count %u)\n", - sc->sc_bmisscount); + device_printf(sc->sc_dev, "stuck beacon; resetting (bmiss count %u)\n", + sc->sc_bmisscount); sc->sc_stats.ast_bstuck++; /* * This assumes that there's no simultaneous channel mode change @@ -3803,7 +3809,6 @@ ath_descdma_alloc_desc(struct ath_softc *sc, ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) #define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \ ((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0) - struct ifnet *ifp = sc->sc_ifp; int error; dd->dd_descsize = ds_size; @@ -3844,7 +3849,8 @@ ath_descdma_alloc_desc(struct ath_softc *sc, NULL, /* lockarg */ &dd->dd_dmat); if (error != 0) { - if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name); + device_printf(sc->sc_dev, + "cannot allocate %s DMA tag\n", dd->dd_name); return error; } @@ -3853,8 +3859,9 @@ ath_descdma_alloc_desc(struct ath_softc *sc, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dd->dd_dmamap); if (error != 0) { - if_printf(ifp, "unable to alloc memory for %u %s descriptors, " - "error %u\n", ndesc, dd->dd_name, error); + device_printf(sc->sc_dev, + "unable to alloc memory for %u %s descriptors, error %u\n", + ndesc, dd->dd_name, error); goto fail1; } @@ -3863,8 +3870,9 @@ ath_descdma_alloc_desc(struct ath_softc *sc, ath_load_cb, &dd->dd_desc_paddr, BUS_DMA_NOWAIT); if (error != 0) { - if_printf(ifp, "unable to map %s descriptors, error %u\n", - dd->dd_name, error); + device_printf(sc->sc_dev, + "unable to map %s descriptors, error %u\n", + dd->dd_name, error); goto fail2; } @@ -3894,7 +3902,6 @@ ath_descdma_setup(struct ath_softc *sc, ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) #define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \ ((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0) - struct ifnet *ifp = sc->sc_ifp; uint8_t *ds; struct ath_buf *bf; int i, bsize, error; @@ -3914,8 +3921,9 @@ ath_descdma_setup(struct ath_softc *sc, bsize = sizeof(struct ath_buf) * nbuf; bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO); if (bf == NULL) { - if_printf(ifp, "malloc of %s buffers failed, size %u\n", - dd->dd_name, bsize); + device_printf(sc->sc_dev, + "malloc of %s buffers failed, size %u\n", + dd->dd_name, bsize); goto fail3; } dd->dd_bufptr = bf; @@ -3941,8 +3949,9 @@ ath_descdma_setup(struct ath_softc *sc, error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &bf->bf_dmamap); if (error != 0) { - if_printf(ifp, "unable to create dmamap for %s " - "buffer %u, error %u\n", dd->dd_name, i, error); + device_printf(sc->sc_dev, "unable to create dmamap " + "for %s buffer %u, error %u\n", + dd->dd_name, i, error); ath_descdma_cleanup(sc, dd, head); return error; } @@ -3978,7 +3987,6 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc, struct ath_descdma *dd, ath_bufhead *head, const char *name, int nbuf, int rx_status_len) { - struct ifnet *ifp = sc->sc_ifp; struct ath_buf *bf; int i, bsize, error; @@ -4001,8 +4009,9 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc, bsize = sizeof(struct ath_buf) * nbuf; bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO); if (bf == NULL) { - if_printf(ifp, "malloc of %s buffers failed, size %u\n", - dd->dd_name, bsize); + device_printf(sc->sc_dev, + "malloc of %s buffers failed, size %u\n", + dd->dd_name, bsize); error = ENOMEM; goto fail3; } @@ -4017,8 +4026,9 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc, error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &bf->bf_dmamap); if (error != 0) { - if_printf(ifp, "unable to create dmamap for %s " - "buffer %u, error %u\n", dd->dd_name, i, error); + device_printf(sc->sc_dev, "unable to create dmamap " + "for %s buffer %u, error %u\n", + dd->dd_name, i, error); ath_descdma_cleanup(sc, dd, head); return error; } @@ -4392,9 +4402,8 @@ ath_txq_update(struct ath_softc *sc, int ac) qi.tqi_aifs, qi.tqi_cwmin, qi.tqi_cwmax, qi.tqi_burstTime); if (!ath_hal_settxqueueprops(ah, txq->axq_qnum, &qi)) { - if_printf(ifp, "unable to update hardware queue " - "parameters for %s traffic!\n", - ieee80211_wme_acnames[ac]); + device_printf(sc->sc_dev, "unable to update hardware queue " + "parameters for %s traffic!\n", ieee80211_wme_acnames[ac]); return 0; } else { ath_hal_resettxqueue(ah, txq->axq_qnum); /* push to h/w */ @@ -5560,7 +5569,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, sc->sc_cur_rxchainmask); if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) { - if_printf(ifp, "%s: unable to reset " + device_printf(sc->sc_dev, "%s: unable to reset " "channel %u (%u MHz, flags 0x%x), hal status %u\n", __func__, ieee80211_chan2ieee(ic, chan), chan->ic_freq, chan->ic_flags, status); @@ -5599,8 +5608,8 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) * Re-enable rx framework. */ if (ath_startrecv(sc) != 0) { - if_printf(ifp, "%s: unable to restart recv logic\n", - __func__); + device_printf(sc->sc_dev, + "%s: unable to restart recv logic\n", __func__); ret = EIO; goto finish; } @@ -6375,8 +6384,9 @@ ath_getchannels(struct ath_softc *sc) status = ath_hal_init_channels(ah, ic->ic_channels, IEEE80211_CHAN_MAX, &ic->ic_nchans, HAL_MODE_ALL, CTRY_DEFAULT, SKU_NONE, AH_TRUE); if (status != HAL_OK) { - if_printf(ifp, "%s: unable to collect channel list from hal, " - "status %d\n", __func__, status); + device_printf(sc->sc_dev, + "%s: unable to collect channel list from hal, status %d\n", + __func__, status); return EINVAL; } (void) ath_hal_getregdomain(ah, &sc->sc_eerd); @@ -6538,10 +6548,10 @@ ath_watchdog(void *arg) if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) && hangs != 0) { - if_printf(ifp, "%s hang detected (0x%x)\n", + device_printf(sc->sc_dev, "%s hang detected (0x%x)\n", hangs & 0xff ? "bb" : "mac", hangs); } else - if_printf(ifp, "device timeout\n"); + device_printf(sc->sc_dev, "device timeout\n"); do_reset = 1; if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); sc->sc_stats.ast_watchdog++; @@ -6786,31 +6796,32 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) static void ath_announce(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; struct ath_hal *ah = sc->sc_ah; - if_printf(ifp, "AR%s mac %d.%d RF%s phy %d.%d\n", + device_printf(sc->sc_dev, "AR%s mac %d.%d RF%s phy %d.%d\n", ath_hal_mac_name(ah), ah->ah_macVersion, ah->ah_macRev, ath_hal_rf_name(ah), ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf); - if_printf(ifp, "2GHz radio: 0x%.4x; 5GHz radio: 0x%.4x\n", + device_printf(sc->sc_dev, "2GHz radio: 0x%.4x; 5GHz radio: 0x%.4x\n", ah->ah_analog2GhzRev, ah->ah_analog5GhzRev); if (bootverbose) { int i; for (i = 0; i <= WME_AC_VO; i++) { struct ath_txq *txq = sc->sc_ac2q[i]; - if_printf(ifp, "Use hw queue %u for %s traffic\n", - txq->axq_qnum, ieee80211_wme_acnames[i]); + device_printf(sc->sc_dev, + "Use hw queue %u for %s traffic\n", + txq->axq_qnum, ieee80211_wme_acnames[i]); } - if_printf(ifp, "Use hw queue %u for CAB traffic\n", - sc->sc_cabq->axq_qnum); - if_printf(ifp, "Use hw queue %u for beacons\n", sc->sc_bhalq); + device_printf(sc->sc_dev, "Use hw queue %u for CAB traffic\n", + sc->sc_cabq->axq_qnum); + device_printf(sc->sc_dev, "Use hw queue %u for beacons\n", + sc->sc_bhalq); } if (ath_rxbuf != ATH_RXBUF) - if_printf(ifp, "using %u rx buffers\n", ath_rxbuf); + device_printf(sc->sc_dev, "using %u rx buffers\n", ath_rxbuf); if (ath_txbuf != ATH_TXBUF) - if_printf(ifp, "using %u tx buffers\n", ath_txbuf); + device_printf(sc->sc_dev, "using %u tx buffers\n", ath_txbuf); if (sc->sc_mcastkey && bootverbose) - if_printf(ifp, "using multicast key search\n"); + device_printf(sc->sc_dev, "using multicast key search\n"); } static void diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c index 07a4abee3458..2779b7a59053 100644 --- a/sys/dev/ath/if_ath_rx.c +++ b/sys/dev/ath/if_ath_rx.c @@ -1037,7 +1037,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) bf = TAILQ_FIRST(&sc->sc_rxbuf); if (sc->sc_rxslink && bf == NULL) { /* NB: shouldn't happen */ - if_printf(ifp, "%s: no buffer!\n", __func__); + device_printf(sc->sc_dev, "%s: no buffer!\n", __func__); break; } else if (bf == NULL) { /* @@ -1054,7 +1054,7 @@ ath_rx_proc(struct ath_softc *sc, int resched) * will be no mbuf; try again to re-populate it. */ /* XXX make debug msg */ - if_printf(ifp, "%s: no mbuf!\n", __func__); + device_printf(sc->sc_dev, "%s: no mbuf!\n", __func__); TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); goto rx_proc_next; } diff --git a/sys/dev/ath/if_ath_tdma.c b/sys/dev/ath/if_ath_tdma.c index de1a91ca02e9..fd23db1977da 100644 --- a/sys/dev/ath/if_ath_tdma.c +++ b/sys/dev/ath/if_ath_tdma.c @@ -259,7 +259,7 @@ ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap) if (vap == NULL) { vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */ if (vap == NULL) { - if_printf(ifp, "%s: no vaps?\n", __func__); + device_printf(sc->sc_dev, "%s: no vaps?\n", __func__); return; } } diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index 096278eb4519..c15b1583761a 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -1691,8 +1691,8 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, flags |= HAL_TXDESC_NOACK; break; default: - if_printf(ifp, "bogus frame type 0x%x (%s)\n", - wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); + device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n", + wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); /* XXX statistic */ /* XXX free tx dmamap */ ath_freetx(m0); From 34f7242bc8ae873d6bd3289d141bbd64b96318a3 Mon Sep 17 00:00:00 2001 From: kib Date: Fri, 29 May 2015 16:26:08 +0000 Subject: [PATCH 59/65] When delivering a signal with default disposition to the thread, tdsigwakeup() increases the priority of the low-priority threads, to give them a chance to be terminated timely. Also, kernel allows user to signal kernel processes. The combined effect is that signalling idle process bump a priority of the selected delivery thread, which starts eating CPU. Check for the delivery thread be an idle thread and do not raise its priority then. The signal delivery to the kernel threads must be opt-in feature. Kernel thread should explicitely declare the ability to handle signals directed to it. E.g., nfsd threads check for signal as an indication of exit request. Most threads do not handle signals at all, and queuing the signal to them causes odd side-effects. Most innocent consequence is the memory leak due to queued ksiginfo, which is never deleted from the sigqueue. Code to prevent even queuing signals to the kernel threads is trivial, but it requires careful examination of each call to kproc/kthread creation to decide should the signalling be allowed. The commit is a stop-gap measure which fixes the immediate case for now. PR: 200493 Reported and tested by: trasz Discussed with: trasz, emaste Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/kern/kern_sig.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index b30e1ed75461..5d480604ea98 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2368,9 +2368,12 @@ tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval) thread_lock(td); /* * Bring the priority of a thread up if we want it to get - * killed in this lifetime. + * killed in this lifetime. Be careful to avoid bumping the + * priority of the idle thread, since we still allow to signal + * kernel processes. */ - if (action == SIG_DFL && (prop & SA_KILL) && td->td_priority > PUSER) + if (action == SIG_DFL && (prop & SA_KILL) != 0 && + td->td_priority > PUSER && !TD_IS_IDLETHREAD(td)) sched_prio(td, PUSER); if (TD_ON_SLEEPQ(td)) { /* @@ -2408,7 +2411,7 @@ tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval) /* * Give low priority threads a better chance to run. */ - if (td->td_priority > PUSER) + if (td->td_priority > PUSER && !TD_IS_IDLETHREAD(td)) sched_prio(td, PUSER); wakeup_swapper = sleepq_abort(td, intrval); From c7531f5a91b593af6ab0f307f7486b617d426410 Mon Sep 17 00:00:00 2001 From: brooks Date: Fri, 29 May 2015 19:42:55 +0000 Subject: [PATCH 60/65] Removed unused special fork() implementations. The arm version hasn't been used in ages. The mips version uses a valid, but pointless check of v1 and has been unhooked from the build since r276630. Differential Revision: https://reviews.freebsd.org/D2592 Reviewed by: emaste Sponsored by: DARPA, AFRL --- lib/libc/arm/sys/fork.S | 49 ----------------------------- lib/libc/mips/sys/Makefile.inc | 2 +- lib/libc/mips/sys/fork.S | 57 ---------------------------------- 3 files changed, 1 insertion(+), 107 deletions(-) delete mode 100644 lib/libc/arm/sys/fork.S delete mode 100644 lib/libc/mips/sys/fork.S diff --git a/lib/libc/arm/sys/fork.S b/lib/libc/arm/sys/fork.S deleted file mode 100644 index a5ae1f0aa419..000000000000 --- a/lib/libc/arm/sys/fork.S +++ /dev/null @@ -1,49 +0,0 @@ -/* $NetBSD: fork.S,v 1.5 2003/08/07 16:42:04 agc Exp $ */ - -/*- - * Copyright (c) 1990 The Regents of the University of California. - * 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. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * from: @(#)fork.s 5.1 (Berkeley) 4/23/90 - */ - -#include -__FBSDID("$FreeBSD$"); -#include "SYS.h" - -/* - * pid = fork(); - * - * On return from the SWI: - * r1 == 0 in parent process, r1 == 1 in child process. - * r0 == pid of child in parent, r0 == pid of parent in child. - */ - -_SYSCALL(fork) - sub r1, r1, #1 /* r1 == 0xffffffff if parent, 0 if child */ - and r0, r0, r1 /* r0 == 0 if child, else unchanged */ - RET diff --git a/lib/libc/mips/sys/Makefile.inc b/lib/libc/mips/sys/Makefile.inc index 460e69b33fbf..c0bd5ad9cc09 100644 --- a/lib/libc/mips/sys/Makefile.inc +++ b/lib/libc/mips/sys/Makefile.inc @@ -3,7 +3,7 @@ SRCS+= trivial-vdso_tc.c MDASM= Ovfork.S brk.S cerror.S exect.S \ - fork.S pipe.S ptrace.S sbrk.S syscall.S + pipe.S ptrace.S sbrk.S syscall.S # Don't generate default code for these syscalls: NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o vfork.o yield.o diff --git a/lib/libc/mips/sys/fork.S b/lib/libc/mips/sys/fork.S deleted file mode 100644 index 7636bd379292..000000000000 --- a/lib/libc/mips/sys/fork.S +++ /dev/null @@ -1,57 +0,0 @@ -/* $NetBSD: fork.S,v 1.11 2003/08/07 16:42:17 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell. - * - * 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. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - */ - -#include -__FBSDID("$FreeBSD$"); -#include "SYS.h" - -#if defined(LIBC_SCCS) && !defined(lint) - ASMSTR("from: @(#)fork.s 8.1 (Berkeley) 6/4/93") - ASMSTR("$NetBSD: fork.S,v 1.11 2003/08/07 16:42:17 agc Exp $") -#endif /* LIBC_SCCS and not lint */ - -LEAF(__sys_fork) - WEAK_ALIAS(fork, __sys_fork) - WEAK_ALIAS(_fork, __sys_fork) - PIC_PROLOGUE(__sys_fork) - li v0, SYS_fork # pid = fork() - syscall - bne a3, zero, 2f - beq v1, zero, 1f # v1 == 0 in parent, 1 in child - move v0, zero -1: - PIC_RETURN() -2: - PIC_TAILCALL(__cerror) -END(__sys_fork) From d7f3fa6b201b38738f0f5cfd150354399b691ea2 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Fri, 29 May 2015 20:22:53 +0000 Subject: [PATCH 61/65] Make the NFS server use shared vnode locks for a few cases that are allowed by the VFS/VOP interface instead of using exclusive locks. MFC after: 2 weeks --- sys/fs/nfsserver/nfs_nfsdsocket.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c index 9c00a0c09b31..4497161f6dd0 100644 --- a/sys/fs/nfsserver/nfs_nfsdsocket.c +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -440,9 +440,12 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen, if (nd->nd_procnum == NFSPROC_READ || nd->nd_procnum == NFSPROC_WRITE || nd->nd_procnum == NFSPROC_READDIR || + nd->nd_procnum == NFSPROC_READDIRPLUS || nd->nd_procnum == NFSPROC_READLINK || nd->nd_procnum == NFSPROC_GETATTR || - nd->nd_procnum == NFSPROC_ACCESS) + nd->nd_procnum == NFSPROC_ACCESS || + nd->nd_procnum == NFSPROC_FSSTAT || + nd->nd_procnum == NFSPROC_FSINFO) lktype = LK_SHARED; else lktype = LK_EXCLUSIVE; @@ -544,7 +547,7 @@ static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p) { - int i, op, op0 = 0; + int i, lktype, op, op0 = 0; u_int32_t *tl; struct nfsclient *clp, *nclp; int numops, error = 0, igotlock; @@ -953,11 +956,15 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, panic("nfsrvd_compound"); if (nfsv4_opflag[op].needscfh) { if (vp != NULL) { - if (nfsv4_opflag[op].modifyfs) + lktype = nfsv4_opflag[op].lktype; + if (nfsv4_opflag[op].modifyfs) { vn_start_write(vp, &temp_mp, V_WAIT); - if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype) - == 0) + if (op == NFSV4OP_WRITE && + MNT_SHARED_WRITES(temp_mp)) + lktype = LK_SHARED; + } + if (NFSVOPLOCK(vp, lktype) == 0) VREF(vp); else nd->nd_repstat = NFSERR_PERM; From 9a1d54a1000576601d35cb26c877936608660cf6 Mon Sep 17 00:00:00 2001 From: marcel Date: Fri, 29 May 2015 20:50:41 +0000 Subject: [PATCH 62/65] Do not set d_fwsectors nor d_fwheads. Primarily because the values tend to be invalid. On a Beaglebone Black, we get 8192 sectors per track and that causes major breakages. Differential Revision: D2646 Reviewed by: ian@ imp@ --- sys/dev/mmc/mmcsd.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/sys/dev/mmc/mmcsd.c b/sys/dev/mmc/mmcsd.c index 3be21585a105..4ca0c2492797 100644 --- a/sys/dev/mmc/mmcsd.c +++ b/sys/dev/mmc/mmcsd.c @@ -163,33 +163,10 @@ mmcsd_attach(device_t dev) d->d_sectorsize = mmc_get_sector_size(dev); d->d_maxsize = mmc_get_max_data(dev) * d->d_sectorsize; d->d_mediasize = (off_t)mmc_get_media_size(dev) * d->d_sectorsize; - d->d_stripeoffset = 0; d->d_stripesize = mmc_get_erase_sector(dev) * d->d_sectorsize; d->d_unit = device_get_unit(dev); d->d_flags = DISKFLAG_CANDELETE; - d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize * 1; /* conservative */ - /* - * The d_fw* values are fake. However, layout is aided by making the - * number of fwsectors equal to the erase sectors from the drive since - * we set the stripe size equal to that. We set fwheads such that there - * are ~20 cylinder groups since all values are somewhat arbitrary here - * and this gives good behavior with ffs without wasting too much - * space. Sadly, geom_part wants to round partitions to these - * values. While not bad, in and of itself, the values we present here - * will almost certainly be different then the values that USB SD - * adapters use and there's too much variation between brands to just - * use those values here. Also SD to ATA adapters favor traditional - * ata sizes, which are different again from the USB adapters (which - * favor SCSI values). This rounding leads to a loss of up to 5% of the - * usable space (usually much less, but that's why 20 was selected: to - * limit this effect at a few percent). gpart needs a way to override - * this behavior for situations like this, but doesn't provide - * one. Perhaps this behavior should be tunable as well, but maybe that - * belongs in the disk layer. These values will be much better than - * the default ones. - */ - d->d_fwsectors = mmc_get_erase_sector(dev); - d->d_fwheads = mmc_get_media_size(dev) / (d->d_fwsectors * 20); + d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize; strlcpy(d->d_ident, mmc_get_card_sn_string(dev), sizeof(d->d_ident)); strlcpy(d->d_descr, mmc_get_card_id_string(dev), sizeof(d->d_descr)); From 551209395dee553219c1523835556ac65906be46 Mon Sep 17 00:00:00 2001 From: grembo Date: Sat, 30 May 2015 12:17:18 +0000 Subject: [PATCH 63/65] ig4 - Intel fourth gen integrated I2C SMBus driver. Differential Revision: https://reviews.freebsd.org/D2372 Reviewed by: jhb, wblock, adrian Approved by: jhb, wblock Relnotes: yes --- share/man/man4/Makefile | 1 + share/man/man4/ig4.4 | 79 ++ sys/conf/files | 2 + sys/dev/ichiic/ig4_iic.c | 966 ++++++++++++++++++++ sys/dev/ichiic/ig4_pci.c | 192 ++++ sys/dev/ichiic/ig4_reg.h | 622 +++++++++++++ sys/dev/ichiic/ig4_var.h | 96 ++ sys/modules/i2c/controllers/Makefile | 2 +- sys/modules/i2c/controllers/ichiic/Makefile | 8 + 9 files changed, 1967 insertions(+), 1 deletion(-) create mode 100644 share/man/man4/ig4.4 create mode 100644 sys/dev/ichiic/ig4_iic.c create mode 100644 sys/dev/ichiic/ig4_pci.c create mode 100644 sys/dev/ichiic/ig4_reg.h create mode 100644 sys/dev/ichiic/ig4_var.h create mode 100644 sys/modules/i2c/controllers/ichiic/Makefile diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 4291e7a22d71..b892cbc82fcf 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -192,6 +192,7 @@ MAN= aac.4 \ icmp6.4 \ ida.4 \ ifmib.4 \ + ig4.4 \ igb.4 \ igmp.4 \ iic.4 \ diff --git a/share/man/man4/ig4.4 b/share/man/man4/ig4.4 new file mode 100644 index 000000000000..d4d7300a5f89 --- /dev/null +++ b/share/man/man4/ig4.4 @@ -0,0 +1,79 @@ +.\" Copyright (c) 2015 Michael Gmelin +.\" 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$ +.\" +.Dd May 30, 2015 +.Dt IG4 4 +.Os +.Sh NAME +.Nm ig4 +.Nd Intel(R) fourth generation mobile CPU integrated I2C SMBus driver +.Sh SYNOPSIS +To compile this driver into the kernel, place the following lines into +the kernel configuration file: +.Bd -ragged -offset indent +.Cd "device ig4" +.Cd "device smbus" +.Ed +.Pp +Alternatively, to load the driver as a module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +ig4_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides access to peripherals attached to an I2C SMB controller. +.Nm +supports the SMBus controller found in fourth generation Intel(R) Core(TM) +processors based on the mobile U-processor line for intelligent systems. +This includes the i7-4650U, i5-4300U, i3-4010U, and 2980U. +.Sh SYSCTL VARIABLES +These +.Xr sysctl 8 +variables are available: +.Bl -tag -width "debug.ig4_dump" +.It Va debug.ig4_dump +Setting this to a non-zero value dumps controller registers to console and +syslog once. +The sysctl resets to zero immediately. +.El +.Sh SEE ALSO +.Xr smb 4 , +.Xr smbus 4 +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written for DragonFly BSD by +.An Matthew Dillon +and subsequently ported to +.Fx +by +.An Michael Gmelin Aq Mt freebsd@grem.de . +.Pp +This manual page was written by +.An Michael Gmelin Aq Mt freebsd@grem.de . diff --git a/sys/conf/files b/sys/conf/files index 5dcb6a43d75d..9660751b428f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1427,6 +1427,8 @@ dev/hptiop/hptiop.c optional hptiop scbus dev/hwpmc/hwpmc_logging.c optional hwpmc dev/hwpmc/hwpmc_mod.c optional hwpmc dev/hwpmc/hwpmc_soft.c optional hwpmc +dev/ichiic/ig4_iic.c optional ichiic +dev/ichiic/ig4_pci.c optional ichiic pci dev/ichsmb/ichsmb.c optional ichsmb dev/ichsmb/ichsmb_pci.c optional ichsmb pci dev/ida/ida.c optional ida diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c new file mode 100644 index 000000000000..e9081e3ed9b0 --- /dev/null +++ b/sys/dev/ichiic/ig4_iic.c @@ -0,0 +1,966 @@ +/* + * Copyright (c) 2014 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon and was subsequently ported + * to FreeBSD by Michael Gmelin + * + * 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. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Intel fourth generation mobile cpus integrated I2C device, smbus driver. + * + * See ig4_reg.h for datasheet reference and notes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#define TRANS_NORMAL 1 +#define TRANS_PCALL 2 +#define TRANS_BLOCK 3 + +static void ig4iic_start(void *xdev); +static void ig4iic_intr(void *cookie); +static void ig4iic_dump(ig4iic_softc_t *sc); + +static int ig4_dump; +SYSCTL_INT(_debug, OID_AUTO, ig4_dump, CTLTYPE_INT | CTLFLAG_RW, + &ig4_dump, 0, ""); + +/* + * Low-level inline support functions + */ +static __inline void +reg_write(ig4iic_softc_t *sc, uint32_t reg, uint32_t value) +{ + bus_write_4(sc->regs_res, reg, value); + bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_WRITE); +} + +static __inline uint32_t +reg_read(ig4iic_softc_t *sc, uint32_t reg) +{ + uint32_t value; + + bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_READ); + value = bus_read_4(sc->regs_res, reg); + return (value); +} + +/* + * Enable or disable the controller and wait for the controller to acknowledge + * the state change. + */ +static int +set_controller(ig4iic_softc_t *sc, uint32_t ctl) +{ + int retry; + int error; + uint32_t v; + + reg_write(sc, IG4_REG_I2C_EN, ctl); + error = SMB_ETIMEOUT; + + for (retry = 100; retry > 0; --retry) { + v = reg_read(sc, IG4_REG_ENABLE_STATUS); + if (((v ^ ctl) & IG4_I2C_ENABLE) == 0) { + error = 0; + break; + } + mtx_sleep(sc, &sc->mutex, 0, "i2cslv", 1); + } + return (error); +} + +/* + * Wait up to 25ms for the requested status using a 25uS polling loop. + */ +static int +wait_status(ig4iic_softc_t *sc, uint32_t status) +{ + uint32_t v; + int error; + int txlvl = -1; + u_int count_us = 0; + u_int limit_us = 25000; /* 25ms */ + + error = SMB_ETIMEOUT; + + for (;;) { + /* + * Check requested status + */ + v = reg_read(sc, IG4_REG_I2C_STA); + if (v & status) { + error = 0; + break; + } + + /* + * When waiting for receive data break-out if the interrupt + * loaded data into the FIFO. + */ + if (status & IG4_STATUS_RX_NOTEMPTY) { + if (sc->rpos != sc->rnext) { + error = 0; + break; + } + } + + /* + * When waiting for the transmit FIFO to become empty, + * reset the timeout if we see a change in the transmit + * FIFO level as progress is being made. + */ + if (status & IG4_STATUS_TX_EMPTY) { + v = reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK; + if (txlvl != v) { + txlvl = v; + count_us = 0; + } + } + + /* + * Stop if we've run out of time. + */ + if (count_us >= limit_us) + break; + + /* + * When waiting for receive data let the interrupt do its + * work, otherwise poll with the lock held. + */ + if (status & IG4_STATUS_RX_NOTEMPTY) { + mtx_sleep(sc, &sc->mutex, PZERO, "i2cwait", + (hz + 99) / 100); /* sleep up to 10ms */ + count_us += 10000; + } else { + DELAY(25); + count_us += 25; + } + } + + return (error); +} + +/* + * Read I2C data. The data might have already been read by + * the interrupt code, otherwise it is sitting in the data + * register. + */ +static uint8_t +data_read(ig4iic_softc_t *sc) +{ + uint8_t c; + + if (sc->rpos == sc->rnext) { + c = (uint8_t)reg_read(sc, IG4_REG_DATA_CMD); + } else { + c = sc->rbuf[sc->rpos & IG4_RBUFMASK]; + ++sc->rpos; + } + return (c); +} + +/* + * Set the slave address. The controller must be disabled when + * changing the address. + * + * This operation does not issue anything to the I2C bus but sets + * the target address for when the controller later issues a START. + */ +static void +set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op) +{ + uint32_t tar; + uint32_t ctl; + int use_10bit; + + use_10bit = sc->use_10bit; + if (trans_op & SMB_TRANS_7BIT) + use_10bit = 0; + if (trans_op & SMB_TRANS_10BIT) + use_10bit = 1; + + if (sc->slave_valid && sc->last_slave == slave && + sc->use_10bit == use_10bit) { + return; + } + sc->use_10bit = use_10bit; + + /* + * Wait for TXFIFO to drain before disabling the controller. + * + * If a write message has not been completed it's really a + * programming error, but for now in that case issue an extra + * byte + STOP. + * + * If a read message has not been completed it's also a programming + * error, for now just ignore it. + */ + wait_status(sc, IG4_STATUS_TX_NOTFULL); + if (sc->write_started) { + reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_STOP); + sc->write_started = 0; + } + if (sc->read_started) + sc->read_started = 0; + wait_status(sc, IG4_STATUS_TX_EMPTY); + + set_controller(sc, 0); + ctl = reg_read(sc, IG4_REG_CTL); + ctl &= ~IG4_CTL_10BIT; + ctl |= IG4_CTL_RESTARTEN; + + tar = slave; + if (sc->use_10bit) { + tar |= IG4_TAR_10BIT; + ctl |= IG4_CTL_10BIT; + } + reg_write(sc, IG4_REG_CTL, ctl); + reg_write(sc, IG4_REG_TAR_ADD, tar); + set_controller(sc, IG4_I2C_ENABLE); + sc->slave_valid = 1; + sc->last_slave = slave; +} + +/* + * Issue START with byte command, possible count, and a variable length + * read or write buffer, then possible turn-around read. The read also + * has a possible count received. + * + * For SMBUS - + * + * Quick: START+ADDR+RD/WR STOP + * + * Normal: START+ADDR+WR CMD DATA..DATA STOP + * + * START+ADDR+RD CMD + * RESTART+ADDR RDATA..RDATA STOP + * (can also be used for I2C transactions) + * + * Process Call: START+ADDR+WR CMD DATAL DATAH + * RESTART+ADDR+RD RDATAL RDATAH STOP + * + * Block: START+ADDR+RD CMD + * RESTART+ADDR+RD RCOUNT DATA... STOP + * + * START+ADDR+WR CMD + * RESTART+ADDR+WR WCOUNT DATA... STOP + * + * For I2C - basically, no *COUNT fields, possibly no *CMD field. If the + * sender needs to issue a 2-byte command it will incorporate it + * into the write buffer and also set NOCMD. + * + * Generally speaking, the START+ADDR / RESTART+ADDR is handled automatically + * by the controller at the beginning of a command sequence or on a data + * direction turn-around, and we only need to tell it when to issue the STOP. + */ +static int +smb_transaction(ig4iic_softc_t *sc, char cmd, int op, + char *wbuf, int wcount, char *rbuf, int rcount, int *actualp) +{ + int error; + int unit; + uint32_t last; + + /* + * Debugging - dump registers + */ + if (ig4_dump) { + unit = device_get_unit(sc->dev); + if (ig4_dump & (1 << unit)) { + ig4_dump &= ~(1 << unit); + ig4iic_dump(sc); + } + } + + /* + * Issue START or RESTART with next data byte, clear any previous + * abort condition that may have been holding the txfifo in reset. + */ + last = IG4_DATA_RESTART; + reg_read(sc, IG4_REG_CLR_TX_ABORT); + if (actualp) + *actualp = 0; + + /* + * Issue command if not told otherwise (smbus). + */ + if ((op & SMB_TRANS_NOCMD) == 0) { + error = wait_status(sc, IG4_STATUS_TX_NOTFULL); + if (error) + goto done; + last |= (u_char)cmd; + if (wcount == 0 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0) + last |= IG4_DATA_STOP; + reg_write(sc, IG4_REG_DATA_CMD, last); + last = 0; + } + + /* + * Clean out any previously received data. + */ + if (sc->rpos != sc->rnext && + (op & SMB_TRANS_NOREPORT) == 0) { + device_printf(sc->dev, + "discarding %d bytes of spurious data\n", + sc->rnext - sc->rpos); + } + sc->rpos = 0; + sc->rnext = 0; + + /* + * If writing and not told otherwise, issue the write count (smbus). + */ + if (wcount && (op & SMB_TRANS_NOCNT) == 0) { + error = wait_status(sc, IG4_STATUS_TX_NOTFULL); + if (error) + goto done; + last |= (u_char)cmd; + reg_write(sc, IG4_REG_DATA_CMD, last); + last = 0; + } + + /* + * Bulk write (i2c) + */ + while (wcount) { + error = wait_status(sc, IG4_STATUS_TX_NOTFULL); + if (error) + goto done; + last |= (u_char)*wbuf; + if (wcount == 1 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0) + last |= IG4_DATA_STOP; + reg_write(sc, IG4_REG_DATA_CMD, last); + --wcount; + ++wbuf; + last = 0; + } + + /* + * Issue reads to xmit FIFO (strange, I know) to tell the controller + * to clock in data. At the moment just issue one read ahead to + * pipeline the incoming data. + * + * NOTE: In the case of NOCMD and wcount == 0 we still issue a + * RESTART here, even if the data direction has not changed + * from the previous CHAINing call. This we force the RESTART. + * (A new START is issued automatically by the controller in + * the other nominal cases such as a data direction change or + * a previous STOP was issued). + * + * If this will be the last byte read we must also issue the STOP + * at the end of the read. + */ + if (rcount) { + last = IG4_DATA_RESTART | IG4_DATA_COMMAND_RD; + if (rcount == 1 && + (op & (SMB_TRANS_NOSTOP | SMB_TRANS_NOCNT)) == + SMB_TRANS_NOCNT) { + last |= IG4_DATA_STOP; + } + reg_write(sc, IG4_REG_DATA_CMD, last); + last = IG4_DATA_COMMAND_RD; + } + + /* + * Bulk read (i2c) and count field handling (smbus) + */ + while (rcount) { + /* + * Maintain a pipeline by queueing the allowance for the next + * read before waiting for the current read. + */ + if (rcount > 1) { + if (op & SMB_TRANS_NOCNT) + last = (rcount == 2) ? IG4_DATA_STOP : 0; + else + last = 0; + reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD | + last); + } + error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY); + if (error) { + if ((op & SMB_TRANS_NOREPORT) == 0) { + device_printf(sc->dev, + "rx timeout addr 0x%02x\n", + sc->last_slave); + } + goto done; + } + last = data_read(sc); + + if (op & SMB_TRANS_NOCNT) { + *rbuf = (u_char)last; + ++rbuf; + --rcount; + if (actualp) + ++*actualp; + } else { + /* + * Handle count field (smbus), which is not part of + * the rcount'ed buffer. The first read data in a + * bulk transfer is the count. + * + * XXX if rcount is loaded as 0 how do I generate a + * STOP now without issuing another RD or WR? + */ + if (rcount > (u_char)last) + rcount = (u_char)last; + op |= SMB_TRANS_NOCNT; + } + } + error = 0; +done: + /* XXX wait for xmit buffer to become empty */ + last = reg_read(sc, IG4_REG_TX_ABRT_SOURCE); + + return (error); +} + +/* + * SMBUS API FUNCTIONS + * + * Called from ig4iic_pci_attach/detach() + */ +int +ig4iic_attach(ig4iic_softc_t *sc) +{ + int error; + uint32_t v; + + v = reg_read(sc, IG4_REG_COMP_TYPE); + v = reg_read(sc, IG4_REG_COMP_PARAM1); + v = reg_read(sc, IG4_REG_GENERAL); + if ((v & IG4_GENERAL_SWMODE) == 0) { + v |= IG4_GENERAL_SWMODE; + reg_write(sc, IG4_REG_GENERAL, v); + v = reg_read(sc, IG4_REG_GENERAL); + } + + v = reg_read(sc, IG4_REG_SW_LTR_VALUE); + v = reg_read(sc, IG4_REG_AUTO_LTR_VALUE); + + v = reg_read(sc, IG4_REG_COMP_VER); + if (v != IG4_COMP_VER) { + error = ENXIO; + goto done; + } + v = reg_read(sc, IG4_REG_SS_SCL_HCNT); + v = reg_read(sc, IG4_REG_SS_SCL_LCNT); + v = reg_read(sc, IG4_REG_FS_SCL_HCNT); + v = reg_read(sc, IG4_REG_FS_SCL_LCNT); + v = reg_read(sc, IG4_REG_SDA_HOLD); + + v = reg_read(sc, IG4_REG_SS_SCL_HCNT); + reg_write(sc, IG4_REG_FS_SCL_HCNT, v); + v = reg_read(sc, IG4_REG_SS_SCL_LCNT); + reg_write(sc, IG4_REG_FS_SCL_LCNT, v); + + /* + * Program based on a 25000 Hz clock. This is a bit of a + * hack (obviously). The defaults are 400 and 470 for standard + * and 60 and 130 for fast. The defaults for standard fail + * utterly (presumably cause an abort) because the clock time + * is ~18.8ms by default. This brings it down to ~4ms (for now). + */ + reg_write(sc, IG4_REG_SS_SCL_HCNT, 100); + reg_write(sc, IG4_REG_SS_SCL_LCNT, 125); + reg_write(sc, IG4_REG_FS_SCL_HCNT, 100); + reg_write(sc, IG4_REG_FS_SCL_LCNT, 125); + + /* + * Use a threshold of 1 so we get interrupted on each character, + * allowing us to use mtx_sleep() in our poll code. Not perfect + * but this is better than using DELAY() for receiving data. + */ + reg_write(sc, IG4_REG_RX_TL, 1); + + reg_write(sc, IG4_REG_CTL, + IG4_CTL_MASTER | + IG4_CTL_SLAVE_DISABLE | + IG4_CTL_RESTARTEN | + IG4_CTL_SPEED_STD); + + sc->smb = device_add_child(sc->dev, "smbus", -1); + if (sc->smb == NULL) { + device_printf(sc->dev, "smbus driver not found\n"); + error = ENXIO; + goto done; + } + +#if 0 + /* + * Don't do this, it blows up the PCI config + */ + reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT); + reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT); +#endif + + /* + * Interrupt on STOP detect or receive character ready + */ + reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET | + IG4_INTR_RX_FULL); + mtx_lock(&sc->mutex); + if (set_controller(sc, 0)) + device_printf(sc->dev, "controller error during attach-1\n"); + if (set_controller(sc, IG4_I2C_ENABLE)) + device_printf(sc->dev, "controller error during attach-2\n"); + mtx_unlock(&sc->mutex); + error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, + NULL, ig4iic_intr, sc, &sc->intr_handle); + if (error) { + device_printf(sc->dev, + "Unable to setup irq: error %d\n", error); + } + + sc->enum_hook.ich_func = ig4iic_start; + sc->enum_hook.ich_arg = sc->dev; + + /* We have to wait until interrupts are enabled. I2C read and write + * only works if the interrupts are available. + */ + if (config_intrhook_establish(&sc->enum_hook) != 0) + error = ENOMEM; + else + error = 0; + +done: + return (error); +} + +void +ig4iic_start(void *xdev) +{ + int error; + ig4iic_softc_t *sc; + device_t dev = (device_t)xdev; + + sc = device_get_softc(dev); + + config_intrhook_disestablish(&sc->enum_hook); + + /* Attach us to the smbus */ + error = bus_generic_attach(sc->dev); + if (error) { + device_printf(sc->dev, + "failed to attach child: error %d\n", error); + } +} + + + +int +ig4iic_detach(ig4iic_softc_t *sc) +{ + int error; + + if (device_is_attached(sc->dev)) { + error = bus_generic_detach(sc->dev); + if (error) + return (error); + } + if (sc->smb) + device_delete_child(sc->dev, sc->smb); + if (sc->intr_handle) + bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle); + + mtx_lock(&sc->mutex); + + sc->smb = NULL; + sc->intr_handle = NULL; + reg_write(sc, IG4_REG_INTR_MASK, 0); + reg_read(sc, IG4_REG_CLR_INTR); + set_controller(sc, 0); + + mtx_unlock(&sc->mutex); + return (0); +} + +int +ig4iic_smb_callback(device_t dev, int index, void *data) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + mtx_lock(&sc->mutex); + + switch (index) { + case SMB_REQUEST_BUS: + error = 0; + break; + case SMB_RELEASE_BUS: + error = 0; + break; + default: + error = SMB_EABORT; + break; + } + + mtx_unlock(&sc->mutex); + + return (error); +} + +/* + * Quick command. i.e. START + cmd + R/W + STOP and no data. It is + * unclear to me how I could implement this with the intel i2c controller + * because the controler sends STARTs and STOPs automatically with data. + */ +int +ig4iic_smb_quick(device_t dev, u_char slave, int how) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + mtx_lock(&sc->mutex); + + switch (how) { + case SMB_QREAD: + error = SMB_ENOTSUPP; + break; + case SMB_QWRITE: + error = SMB_ENOTSUPP; + break; + default: + error = SMB_ENOTSUPP; + break; + } + mtx_unlock(&sc->mutex); + + return (error); +} + +/* + * Incremental send byte without stop (?). It is unclear why the slave + * address is specified if this presumably is used in combination with + * ig4iic_smb_quick(). + * + * (Also, how would this work anyway? Issue the last byte with writeb()?) + */ +int +ig4iic_smb_sendb(device_t dev, u_char slave, char byte) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + uint32_t cmd; + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + cmd = byte; + if (wait_status(sc, IG4_STATUS_TX_NOTFULL) == 0) { + reg_write(sc, IG4_REG_DATA_CMD, cmd); + error = 0; + } else { + error = SMB_ETIMEOUT; + } + + mtx_unlock(&sc->mutex); + return (error); +} + +/* + * Incremental receive byte without stop (?). It is unclear why the slave + * address is specified if this presumably is used in combination with + * ig4iic_smb_quick(). + */ +int +ig4iic_smb_recvb(device_t dev, u_char slave, char *byte) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD); + if (wait_status(sc, IG4_STATUS_RX_NOTEMPTY) == 0) { + *byte = data_read(sc); + error = 0; + } else { + *byte = 0; + error = SMB_ETIMEOUT; + } + + mtx_unlock(&sc->mutex); + return (error); +} + +/* + * Write command and single byte in transaction. + */ +int +ig4iic_smb_writeb(device_t dev, u_char slave, char cmd, char byte) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, + &byte, 1, NULL, 0, NULL); + + mtx_unlock(&sc->mutex); + return (error); +} + +/* + * Write command and single word in transaction. + */ +int +ig4iic_smb_writew(device_t dev, u_char slave, char cmd, short word) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + char buf[2]; + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + buf[0] = word & 0xFF; + buf[1] = word >> 8; + error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, + buf, 2, NULL, 0, NULL); + + mtx_unlock(&sc->mutex); + return (error); +} + +/* + * write command and read single byte in transaction. + */ +int +ig4iic_smb_readb(device_t dev, u_char slave, char cmd, char *byte) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, + NULL, 0, byte, 1, NULL); + + mtx_unlock(&sc->mutex); + return (error); +} + +/* + * write command and read word in transaction. + */ +int +ig4iic_smb_readw(device_t dev, u_char slave, char cmd, short *word) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + char buf[2]; + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, + NULL, 0, buf, 2, NULL)) == 0) { + *word = (u_char)buf[0] | ((u_char)buf[1] << 8); + } + + mtx_unlock(&sc->mutex); + return (error); +} + +/* + * write command and word and read word in transaction + */ +int +ig4iic_smb_pcall(device_t dev, u_char slave, char cmd, + short sdata, short *rdata) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + char rbuf[2]; + char wbuf[2]; + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + wbuf[0] = sdata & 0xFF; + wbuf[1] = sdata >> 8; + if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT, + wbuf, 2, rbuf, 2, NULL)) == 0) { + *rdata = (u_char)rbuf[0] | ((u_char)rbuf[1] << 8); + } + + mtx_unlock(&sc->mutex); + return (error); +} + +int +ig4iic_smb_bwrite(device_t dev, u_char slave, char cmd, + u_char wcount, char *buf) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + error = smb_transaction(sc, cmd, 0, + buf, wcount, NULL, 0, NULL); + + mtx_unlock(&sc->mutex); + return (error); +} + +int +ig4iic_smb_bread(device_t dev, u_char slave, char cmd, + u_char *countp_char, char *buf) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int rcount = *countp_char; + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, 0); + error = smb_transaction(sc, cmd, 0, + NULL, 0, buf, rcount, &rcount); + *countp_char = rcount; + + mtx_unlock(&sc->mutex); + return (error); +} + +int +ig4iic_smb_trans(device_t dev, int slave, char cmd, int op, + char *wbuf, int wcount, char *rbuf, int rcount, + int *actualp) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + mtx_lock(&sc->mutex); + + set_slave_addr(sc, slave, op); + error = smb_transaction(sc, cmd, op, + wbuf, wcount, rbuf, rcount, actualp); + + mtx_unlock(&sc->mutex); + return (error); +} + +/* + * Interrupt Operation + */ +static void +ig4iic_intr(void *cookie) +{ + ig4iic_softc_t *sc = cookie; + uint32_t status; + + mtx_lock(&sc->mutex); +/* reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/ + status = reg_read(sc, IG4_REG_I2C_STA); + while (status & IG4_STATUS_RX_NOTEMPTY) { + sc->rbuf[sc->rnext & IG4_RBUFMASK] = + (uint8_t)reg_read(sc, IG4_REG_DATA_CMD); + ++sc->rnext; + status = reg_read(sc, IG4_REG_I2C_STA); + } + reg_read(sc, IG4_REG_CLR_INTR); + wakeup(sc); + mtx_unlock(&sc->mutex); +} + +#define REGDUMP(sc, reg) \ + device_printf(sc->dev, " %-23s %08x\n", #reg, reg_read(sc, reg)) + +static void +ig4iic_dump(ig4iic_softc_t *sc) +{ + device_printf(sc->dev, "ig4iic register dump:\n"); + REGDUMP(sc, IG4_REG_CTL); + REGDUMP(sc, IG4_REG_TAR_ADD); + REGDUMP(sc, IG4_REG_SS_SCL_HCNT); + REGDUMP(sc, IG4_REG_SS_SCL_LCNT); + REGDUMP(sc, IG4_REG_FS_SCL_HCNT); + REGDUMP(sc, IG4_REG_FS_SCL_LCNT); + REGDUMP(sc, IG4_REG_INTR_STAT); + REGDUMP(sc, IG4_REG_INTR_MASK); + REGDUMP(sc, IG4_REG_RAW_INTR_STAT); + REGDUMP(sc, IG4_REG_RX_TL); + REGDUMP(sc, IG4_REG_TX_TL); + REGDUMP(sc, IG4_REG_I2C_EN); + REGDUMP(sc, IG4_REG_I2C_STA); + REGDUMP(sc, IG4_REG_TXFLR); + REGDUMP(sc, IG4_REG_RXFLR); + REGDUMP(sc, IG4_REG_SDA_HOLD); + REGDUMP(sc, IG4_REG_TX_ABRT_SOURCE); + REGDUMP(sc, IG4_REG_SLV_DATA_NACK); + REGDUMP(sc, IG4_REG_DMA_CTRL); + REGDUMP(sc, IG4_REG_DMA_TDLR); + REGDUMP(sc, IG4_REG_DMA_RDLR); + REGDUMP(sc, IG4_REG_SDA_SETUP); + REGDUMP(sc, IG4_REG_ENABLE_STATUS); + REGDUMP(sc, IG4_REG_COMP_PARAM1); + REGDUMP(sc, IG4_REG_COMP_VER); + REGDUMP(sc, IG4_REG_COMP_TYPE); + REGDUMP(sc, IG4_REG_CLK_PARMS); + REGDUMP(sc, IG4_REG_RESETS); + REGDUMP(sc, IG4_REG_GENERAL); + REGDUMP(sc, IG4_REG_SW_LTR_VALUE); + REGDUMP(sc, IG4_REG_AUTO_LTR_VALUE); +} +#undef REGDUMP + +DRIVER_MODULE(smbus, ig4iic, smbus_driver, smbus_devclass, NULL, NULL); diff --git a/sys/dev/ichiic/ig4_pci.c b/sys/dev/ichiic/ig4_pci.c new file mode 100644 index 000000000000..42c3664a1194 --- /dev/null +++ b/sys/dev/ichiic/ig4_pci.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2014 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon and was subsequently ported + * to FreeBSD by Michael Gmelin + * + * 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. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Intel fourth generation mobile cpus integrated I2C device, smbus driver. + * + * See ig4_reg.h for datasheet reference and notes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "smbus_if.h" + +#include +#include + +static int ig4iic_pci_detach(device_t dev); + +#define PCI_CHIP_LYNXPT_LP_I2C_1 0x9c618086 +#define PCI_CHIP_LYNXPT_LP_I2C_2 0x9c628086 + +static int +ig4iic_pci_probe(device_t dev) +{ + switch(pci_get_devid(dev)) { + case PCI_CHIP_LYNXPT_LP_I2C_1: + device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-1"); + break; + case PCI_CHIP_LYNXPT_LP_I2C_2: + device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-2"); + break; + default: + return (ENXIO); + } + return (BUS_PROBE_DEFAULT); +} + +static int +ig4iic_pci_attach(device_t dev) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + bzero(sc, sizeof(*sc)); + + mtx_init(&sc->mutex, device_get_nameunit(dev), "ig4iic", MTX_DEF); + + sc->dev = dev; + sc->regs_rid = PCIR_BAR(0); + sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->regs_rid, RF_ACTIVE); + if (sc->regs_res == NULL) { + device_printf(dev, "unable to map registers\n"); + ig4iic_pci_detach(dev); + return (ENXIO); + } + sc->intr_rid = 0; + if (pci_alloc_msi(dev, &sc->intr_rid)) { + device_printf(dev, "Using MSI\n"); + } + sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->intr_rid, RF_SHAREABLE | RF_ACTIVE); + if (sc->intr_res == NULL) { + device_printf(dev, "unable to map interrupt\n"); + ig4iic_pci_detach(dev); + return (ENXIO); + } + sc->pci_attached = 1; + + error = ig4iic_attach(sc); + if (error) + ig4iic_pci_detach(dev); + + return (error); +} + +static int +ig4iic_pci_detach(device_t dev) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error; + + if (sc->pci_attached) { + error = ig4iic_detach(sc); + if (error) + return (error); + sc->pci_attached = 0; + } + + if (sc->intr_res) { + bus_release_resource(dev, SYS_RES_IRQ, + sc->intr_rid, sc->intr_res); + sc->intr_res = NULL; + } + if (sc->intr_rid != 0) + pci_release_msi(dev); + if (sc->regs_res) { + bus_release_resource(dev, SYS_RES_MEMORY, + sc->regs_rid, sc->regs_res); + sc->regs_res = NULL; + } + mtx_destroy(&sc->mutex); + + return (0); +} + +static device_method_t ig4iic_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ig4iic_pci_probe), + DEVMETHOD(device_attach, ig4iic_pci_attach), + DEVMETHOD(device_detach, ig4iic_pci_detach), + + /* SMBus methods from ig4_smb.c */ + DEVMETHOD(smbus_callback, ig4iic_smb_callback), + DEVMETHOD(smbus_quick, ig4iic_smb_quick), + DEVMETHOD(smbus_sendb, ig4iic_smb_sendb), + DEVMETHOD(smbus_recvb, ig4iic_smb_recvb), + DEVMETHOD(smbus_writeb, ig4iic_smb_writeb), + DEVMETHOD(smbus_writew, ig4iic_smb_writew), + DEVMETHOD(smbus_readb, ig4iic_smb_readb), + DEVMETHOD(smbus_readw, ig4iic_smb_readw), + DEVMETHOD(smbus_pcall, ig4iic_smb_pcall), + DEVMETHOD(smbus_bwrite, ig4iic_smb_bwrite), + DEVMETHOD(smbus_bread, ig4iic_smb_bread), + DEVMETHOD(smbus_trans, ig4iic_smb_trans), + + DEVMETHOD_END +}; + +static driver_t ig4iic_pci_driver = { + "ig4iic", + ig4iic_pci_methods, + sizeof(struct ig4iic_softc) +}; + +static devclass_t ig4iic_pci_devclass; + +DRIVER_MODULE(ig4iic, pci, ig4iic_pci_driver, ig4iic_pci_devclass, 0, 0); +MODULE_DEPEND(ig4iic, pci, 1, 1, 1); +MODULE_DEPEND(ig4iic, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_VERSION(ig4iic, 1); diff --git a/sys/dev/ichiic/ig4_reg.h b/sys/dev/ichiic/ig4_reg.h new file mode 100644 index 000000000000..c87d1d1e9fd2 --- /dev/null +++ b/sys/dev/ichiic/ig4_reg.h @@ -0,0 +1,622 @@ +/* + * Copyright (c) 2014 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon and was subsequently ported + * to FreeBSD by Michael Gmelin + * + * 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. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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$ + */ +/* + * Intel fourth generation mobile cpus integrated I2C device. + * + * Datasheet reference: Section 22. + * + * http://www.intel.com/content/www/us/en/processors/core/4th-gen-core-family-mobile-i-o-datasheet.html?wapkw=datasheets+4th+generation + * + * This is a from-scratch driver under the BSD license using the Intel data + * sheet and the linux driver for reference. All code is freshly written + * without referencing the linux driver code. However, during testing + * I am also using the linux driver code as a reference to help resolve any + * issues that come. These will be specifically documented in the code. + * + * Please see protocol notes in section 5.21. This controller is an I2C + * master only and cannot act as a slave. The IO voltage should be set by + * the BIOS. Standard (100Kb/s) and Fast (400Kb/s) and fast mode plus + * (1MB/s) is supported. High speed mode (3.4 MB/s) is NOT supported. + */ + +#ifndef _BUS_SMBUS_INTELGEN4_IG4_REG_H_ +#define _BUS_SMBUS_INTELGEN4_IG4_REG_H_ + +/* + * 22.2 MMIO registers can be accessed through BAR0 in PCI mode or through + * BAR1 when in ACPI mode. + * + * Register width is 32-bits + * + * 22.2 Default Values on device reset are 0 except as specified here: + * TAR_ADD 0x00000055 + * SS_SCL_HCNT 0x00000264 + * SS_SCL_LCNT 0x000002C2 + * FS_SCL_HCNT 0x0000006E + * FS_SCL_LCNT 0x000000CF + * INTR_MASK 0x000008FF + * I2C_STA 0x00000006 + * SDA_HOLD 0x00000001 + * SDA_SETUP 0x00000064 + * COMP_PARAM1 0x00FFFF6E + * COMP_VER 0x3131352A + */ + +#define IG4_REG_CTL 0x0000 /* RW Control Register */ +#define IG4_REG_TAR_ADD 0x0004 /* RW Target Address */ +#define IG4_REG_DATA_CMD 0x0010 /* RW Data Buffer and Command */ +#define IG4_REG_SS_SCL_HCNT 0x0014 /* RW Std Speed clock High Count */ +#define IG4_REG_SS_SCL_LCNT 0x0018 /* RW Std Speed clock Low Count */ +#define IG4_REG_FS_SCL_HCNT 0x001C /* RW Fast Speed clock High Count */ +#define IG4_REG_FS_SCL_LCNT 0x0020 /* RW Fast Speed clock Low Count */ +#define IG4_REG_INTR_STAT 0x002C /* RO Interrupt Status */ +#define IG4_REG_INTR_MASK 0x0030 /* RW Interrupt Mask */ +#define IG4_REG_RAW_INTR_STAT 0x0034 /* RO Raw Interrupt Status */ +#define IG4_REG_RX_TL 0x0038 /* RW Receive FIFO Threshold */ +#define IG4_REG_TX_TL 0x003C /* RW Transmit FIFO Threshold */ +#define IG4_REG_CLR_INTR 0x0040 /* RO Clear Interrupt */ +#define IG4_REG_CLR_RX_UNDER 0x0044 /* RO Clear RX_Under Interrupt */ +#define IG4_REG_CLR_RX_OVER 0x0048 /* RO Clear RX_Over Interrupt */ +#define IG4_REG_CLR_TX_OVER 0x004C /* RO Clear TX_Over Interrupt */ +#define IG4_REG_CLR_TX_ABORT 0x0054 /* RO Clear TX_Abort Interrupt */ +#define IG4_REG_CLR_ACTIVITY 0x005C /* RO Clear Activity Interrupt */ +#define IG4_REG_CLR_STOP_DET 0x0060 /* RO Clear STOP Detection Int */ +#define IG4_REG_CLR_START_DET 0x0064 /* RO Clear START Detection Int */ +#define IG4_REG_CLR_GEN_CALL 0x0068 /* RO Clear General Call Interrupt */ +#define IG4_REG_I2C_EN 0x006C /* RW I2C Enable */ +#define IG4_REG_I2C_STA 0x0070 /* RO I2C Status */ +#define IG4_REG_TXFLR 0x0074 /* RO Transmit FIFO Level */ +#define IG4_REG_RXFLR 0x0078 /* RO Receive FIFO Level */ +#define IG4_REG_SDA_HOLD 0x007C /* RW SDA Hold Time Length */ +#define IG4_REG_TX_ABRT_SOURCE 0x0080 /* RO Transmit Abort Source */ +#define IG4_REG_SLV_DATA_NACK 0x0084 /* RW General Slave Data NACK */ +#define IG4_REG_DMA_CTRL 0x0088 /* RW DMA Control */ +#define IG4_REG_DMA_TDLR 0x008C /* RW DMA Transmit Data Level */ +#define IG4_REG_DMA_RDLR 0x0090 /* RW DMA Receive Data Level */ +#define IG4_REG_SDA_SETUP 0x0094 /* RW SDA Setup */ +#define IG4_REG_ENABLE_STATUS 0x009C /* RO Enable Status */ +#define IG4_REG_COMP_PARAM1 0x00F4 /* RO Component Parameter */ +#define IG4_REG_COMP_VER 0x00F8 /* RO Component Version */ +#define IG4_REG_COMP_TYPE 0x00FC /* RO Probe width/endian? (linux) */ +#define IG4_REG_CLK_PARMS 0x0800 /* RW Clock Parameters */ +#define IG4_REG_RESETS 0x0804 /* RW Reset Register */ +#define IG4_REG_GENERAL 0x0808 /* RW General Register */ +#define IG4_REG_SW_LTR_VALUE 0x0810 /* RW SW LTR Value */ +#define IG4_REG_AUTO_LTR_VALUE 0x0814 /* RW Auto LTR Value */ + +/* + * CTL - Control Register 22.2.1 + * Default Value: 0x0000007F. + * + * RESTARTEN - RW Restart Enable + * 10BIT - RW Controller operates in 10-bit mode, else 7-bit + * + * NOTE: When restart is disabled the controller is incapable of + * performing the following functions: + * + * Sending a START Byte + * Performing any high-speed mode op + * Performing direction changes in combined format mode + * Performing a read operation with a 10-bit address + * + * Attempting to perform the above operations will result in the + * TX_ABORT bit being set in RAW_INTR_STAT. + */ +#define IG4_CTL_SLAVE_DISABLE 0x0040 /* snarfed from linux */ +#define IG4_CTL_RESTARTEN 0x0020 /* Allow Restart when master */ +#define IG4_CTL_10BIT 0x0010 /* ctlr accepts 10-bit addresses */ +#define IG4_CTL_SPEED_FAST 0x0004 /* snarfed from linux */ +#define IG4_CTL_SPEED_STD 0x0002 /* snarfed from linux */ +#define IG4_CTL_MASTER 0x0001 /* snarfed from linux */ + +/* + * TAR_ADD - Target Address Register 22.2.2 + * Default Value: 0x00000055F + * + * 10BIT - RW controller starts its transfers in 10-bit + * address mode, else 7-bit. + * + * SPECIAL - RW Indicates whether software performs a General Call + * or START BYTE command. + * + * 0 Ignore GC_OR_START and use TAR address. + * + * 1 Perform special I2C Command based on GC_OR_START. + * + * GC_OR_START - RW (only if SPECIAL is set) + * + * 0 General Call Address. After issuing a General Call, + * only writes may be performed. Attempting to issue + * a read command results in IX_ABRT in RAW_INTR_STAT. + * The controller remains in General Call mode until + * bit 11 (SPECIAL) is cleared. + * + * 1 START BYTE. + * + * + * IC_TAR - RW when transmitting a general call, these bits are + * ignored. To generate a START BYTE, the address + * needs to be written into these bits once. + * + * This register should only be updated when the IIC is disabled (I2C_ENABLE=0) + */ +#define IG4_TAR_10BIT 0x1000 /* start xfer in 10-bit mode */ +#define IG4_TAR_SPECIAL 0x0800 /* Perform special command */ +#define IG4_TAR_GC_OR_START 0x0400 /* General Call or Start */ +#define IG4_TAR_ADDR_MASK 0x03FF /* Target address */ + +/* + * TAR_DATA_CMD - Data Buffer and Command Register 22.2.3 + * + * RESTART - RW This bit controls whether a forced RESTART is + * issued before the byte is sent or received. + * + * 0 If not set a RESTART is only issued if the tranfer + * direction is changing from the previous command. + * + * 1 A RESTART is issued before the byte is sent or + * received, regardless of whether or not the transfer + * direction is changing from the previous command. + * + * STOP - RW This bit controls whether a STOP is issued after + * the byte is sent or received. + * + * 0 STOP is not issued after this byte, regardless + * of whether or not the Tx FIFO is empty. + * + * 1 STOP is issued after this byte, regardless of + * whether or not the Tx FIFO is empty. If the + * Tx FIFO is not empty the master immediately tries + * to start a new transfer by issuing a START and + * arbitrating for the bus. + * + * i.e. the STOP is issued along with this byte, + * within the write stream. + * + * COMMAND - RW Control whether a read or write is performed. + * + * 0 WRITE + * + * 1 READ + * + * DATA (7:0) - RW Contains the data to be transmitted or received + * on the I2C bus. + * + * NOTE: Writing to this register causes a START + slave + RW to be + * issued if the direction has changed or the last data byte was + * sent with a STOP. + * + * NOTE: We control termination? so this register must be written + * for each byte we wish to receive. We can then drain the + * receive FIFO. + */ + +#define IG4_DATA_RESTART 0x0400 /* Force RESTART */ +#define IG4_DATA_STOP 0x0200 /* Force STOP[+START] */ +#define IG4_DATA_COMMAND_RD 0x0100 /* bus direction 0=write 1=read */ +#define IG4_DATA_MASK 0x00FF + +/* + * SS_SCL_HCNT - Standard Speed Clock High Count Register 22.2.4 + * SS_SCL_LCNT - Standard Speed Clock Low Count Register 22.2.5 + * FS_SCL_HCNT - Fast Speed Clock High Count Register 22.2.6 + * FS_SCL_LCNT - Fast Speed Clock Low Count Register 22.2.7 + * + * COUNT (15:0) - Set the period count to a value between 6 and + * 65525. + */ +#define IG4_SCL_CLOCK_MASK 0xFFFFU /* count bits in register */ + +/* + * INTR_STAT - (RO) Interrupt Status Register 22.2.8 + * INTR_MASK - (RW) Interrupt Mask Register 22.2.9 + * RAW_INTR_STAT- (RO) Raw Interrupt Status Register 22.2.10 + * + * GEN_CALL Set only when a general call (broadcast) address + * is received and acknowleged, stays set until + * cleared by reading CLR_GEN_CALL. + * + * START_DET Set when a START or RESTART condition has occurred + * on the interface. + * + * STOP_DET Set when a STOP condition has occurred on the + * interface. + * + * ACTIVITY Set by any activity on the interface. Cleared + * by reading CLR_ACTIVITY or CLR_INTR. + * + * TX_ABRT Indicates the controller as a transmitter is + * unable to complete the intended action. When set, + * the controller will hold the TX FIFO in a reset + * state (flushed) until CLR_TX_ABORT is read to + * clear the condition. Once cleared, the TX FIFO + * will be available again. + * + * TX_EMPTY Indicates that the transmitter is at or below + * the specified TX_TL threshold. Automatically + * cleared by HW when the buffer level goes above + * the threshold. + * + * TX_OVER Indicates that the processer attempted to write + * to the TX FIFO while the TX FIFO was full. Cleared + * by reading CLR_TX_OVER. + * + * RX_FULL Indicates that the receive FIFO has reached or + * exceeded the specified RX_TL threshold. Cleared + * by HW when the cpu drains the FIFO to below the + * threshold. + * + * RX_OVER Indicates that the receive FIFO was unable to + * accept new data and data was lost. Cleared by + * reading CLR_RX_OVER. + * + * RX_UNDER Indicates that the cpu attempted to read data + * from the receive buffer while the RX FIFO was + * empty. Cleared by reading CLR_RX_UNDER. + * + * NOTES ON RAW_INTR_STAT: + * + * This register can be used to monitor the GEN_CALL, START_DET, + * STOP_DET, ACTIVITY, TX_ABRT, TX_EMPTY, TX_OVER, RX_FULL, RX_OVER, + * and RX_UNDER bits. The documentation is a bit unclear but presumably + * this is the unlatched version. + * + * Code should test FIFO conditions using the I2C_STA (status) register, + * not the interrupt status registers. + */ + +#define IG4_INTR_GEN_CALL 0x0800 +#define IG4_INTR_START_DET 0x0400 +#define IG4_INTR_STOP_DET 0x0200 +#define IG4_INTR_ACTIVITY 0x0100 +#define IG4_INTR_TX_ABRT 0x0040 +#define IG4_INTR_TX_EMPTY 0x0010 +#define IG4_INTR_TX_OVER 0x0008 +#define IG4_INTR_RX_FULL 0x0004 +#define IG4_INTR_RX_OVER 0x0002 +#define IG4_INTR_RX_UNDER 0x0001 + +/* + * RX_TL - (RW) Receive FIFO Threshold Register 22.2.11 + * TX_TL - (RW) Transmit FIFO Threshold Register 22.2.12 + * + * Specify the receive and transmit FIFO threshold register. The + * FIFOs have 16 elements. The valid range is 0-15. Setting a + * value greater than 15 causes the actual value to be the maximum + * depth of the FIFO. + * + * Generally speaking since everything is messaged, we can use a + * mid-level setting for both parameters and (e.g.) fully drain the + * receive FIFO on the STOP_DET condition to handle loose ends. + */ +#define IG4_FIFO_MASK 0x00FF +#define IG4_FIFO_LIMIT 16 + +/* + * CLR_INTR - (RO) Clear Interrupt Register 22.2.13 + * CLR_RX_UNDER - (RO) Clear Interrupt Register (specific) 22.2.14 + * CLR_RX_OVER - (RO) Clear Interrupt Register (specific) 22.2.15 + * CLR_TX_OVER - (RO) Clear Interrupt Register (specific) 22.2.16 + * CLR_TX_ABORT - (RO) Clear Interrupt Register (specific) 22.2.17 + * CLR_ACTIVITY - (RO) Clear Interrupt Register (specific) 22.2.18 + * CLR_STOP_DET - (RO) Clear Interrupt Register (specific) 22.2.19 + * CLR_START_DET- (RO) Clear Interrupt Register (specific) 22.2.20 + * CLR_GEN_CALL - (RO) Clear Interrupt Register (specific) 22.2.21 + * + * CLR_* specific operations clear the appropriate bit in the + * RAW_INTR_STAT register. Intel does not really document whether + * these operations clear the normal interrupt status register. + * + * CLR_INTR clears bits in the normal interrupt status register and + * presumably also the raw(?) register? Intel is again unclear. + * + * NOTE: CLR_INTR only clears software-clearable interrupts. Hardware + * clearable interrupts are controlled entirely by the hardware. + * CLR_INTR also clears the TX_ABRT_SOURCE register. + * + * NOTE: CLR_TX_ABORT also clears the TX_ABRT_SOURCE register and releases + * the TX FIFO from its flushed/reset state, allowing more writes + * to the TX FIFO. + * + * NOTE: CLR_ACTIVITY has no effect if the I2C bus is still active. + * Intel documents that the bit is automatically cleared when + * there is no further activity on the bus. + */ +#define IG4_CLR_BIT 0x0001 /* Reflects source */ + +/* + * I2C_EN - (RW) I2C Enable Register 22.2.22 + * + * ABORT Software can abort an I2C transfer by setting this + * bit. Hardware will clear the bit once the STOP has + * been detected. This bit can only be set while the + * I2C interface is enabled. + * + * I2C_ENABLE Enable the controller, else disable it. + * (Use I2C_ENABLE_STATUS to poll enable status + * & wait for changes) + */ +#define IG4_I2C_ABORT 0x0002 +#define IG4_I2C_ENABLE 0x0001 + +/* + * I2C_STA - (RO) I2C Status Register 22.2.23 + */ +#define IG4_STATUS_ACTIVITY 0x0020 /* Controller is active */ +#define IG4_STATUS_RX_FULL 0x0010 /* RX FIFO completely full */ +#define IG4_STATUS_RX_NOTEMPTY 0x0008 /* RX FIFO not empty */ +#define IG4_STATUS_TX_EMPTY 0x0004 /* TX FIFO completely empty */ +#define IG4_STATUS_TX_NOTFULL 0x0002 /* TX FIFO not full */ +#define IG4_STATUS_I2C_ACTIVE 0x0001 /* I2C bus is active */ + +/* + * TXFLR - (RO) Transmit FIFO Level Register 22.2.24 + * RXFLR - (RO) Receive FIFO Level Register 22.2.25 + * + * Read the number of entries currently in the Transmit or Receive + * FIFOs. Note that for some reason the mask is 9 bits instead of + * the 8 bits the fill level controls. + */ +#define IG4_FIFOLVL_MASK 0x001F + +/* + * SDA_HOLD - (RW) SDA Hold Time Length Register 22.2.26 + * + * Set the SDA hold time length register in I2C clocks. + */ +#define IG4_SDA_HOLD_MASK 0x00FF + +/* + * TX_ABRT_SOURCE- (RO) Transmit Abort Source Register 22.2.27 + * + * Indicates the cause of a transmit abort. This can indicate a + * software programming error or a device expected address width + * mismatch or other issues. The NORESTART conditions and GENCALL_NOACK + * can only occur if a programming error was made in the driver software. + * + * In particular, it should be possible to detect whether any devices + * are on the bus by observing the GENCALL_READ status, and it might + * be possible to detect ADDR7 vs ADDR10 mismatches. + */ +#define IG4_ABRTSRC_TRANSFER 0x00010000 /* Abort initiated by user */ +#define IG4_ABRTSRC_ARBLOST 0x00001000 /* Arbitration lost */ +#define IG4_ABRTSRC_NORESTART_10 0x00000400 /* RESTART disabled */ +#define IG4_ABRTSRC_NORESTART_START 0x00000200 /* RESTART disabled */ +#define IG4_ABRTSRC_ACKED_START 0x00000080 /* Improper acked START */ +#define IG4_ABRTSRC_GENCALL_NOACK 0x00000020 /* Improper GENCALL */ +#define IG4_ABRTSRC_GENCALL_READ 0x00000010 /* Nobody acked GENCALL */ +#define IG4_ABRTSRC_TXNOACK_DATA 0x00000008 /* data phase no ACK */ +#define IG4_ABRTSRC_TXNOACK_ADDR10_2 0x00000004 /* addr10/1 phase no ACK */ +#define IG4_ABRTSRC_TXNOACK_ADDR10_1 0x00000002 /* addr10/2 phase no ACK */ +#define IG4_ABRTSRC_TXNOACK_ADDR7 0x00000001 /* addr7 phase no ACK */ + +/* + * SLV_DATA_NACK - (RW) Generate Slave DATA NACK Register 22.2.28 + * + * When the controller is a receiver a NACK can be generated on + * receipt of data. + * + * NACK_GENERATE Set to 0 for normal NACK/ACK generation. + * Set to 1 to generate a NACK after next data + * byte received. + * + */ +#define IG4_NACK_GENERATE 0x0001 + +/* + * DMA_CTRL - (RW) DMA Control Register 22.2.29 + * + * Enables DMA on the transmit and/or receive DMA channel. + */ +#define IG4_TX_DMA_ENABLE 0x0002 +#define IG4_RX_DMA_ENABLE 0x0001 + +/* + * DMA_TDLR - (RW) DMA Transmit Data Level Register 22.2.30 + * DMA_RDLR - (RW) DMA Receive Data Level Register 22.2.31 + * + * Similar to RX_TL and TX_TL but controls when a DMA burst occurs + * to empty or fill the FIFOs. Use the same IG4_FIFO_MASK and + * IG4_FIFO_LIMIT defines for RX_RL and TX_TL. + */ +/* empty */ + +/* + * SDA_SETUP - (RW) SDA Setup Time Length Register 22.2.32 + * + * Set the SDA setup time length register in I2C clocks. + * The register must be programmed with a value >=2. + * (Defaults to 0x64). + */ +#define IG4_SDA_SETUP_MASK 0x00FF + +/* + * ACK_GEN_CALL - (RW) ACK General Call Register 22.2.33 + * + * Control whether the controller responds with a ACK or NACK when + * it receives an I2C General Call address. + * + * If set to 0 a NACK is generated and a General Call interrupt is + * NOT generated. Otherwise an ACK + interrupt is generated. + */ +#define IG4_ACKGC_ACK 0x0001 + +/* + * ENABLE_STATUS - (RO) Enable Status Registger 22.2.34 + * + * DATA_LOST - Indicates that a slave receiver operation has + * been aborted with at least one data byte received + * from a transfer due to the I2C controller being + * disabled (IG4_I2C_ENABLE -> 0) + * + * ENABLED - Intel documentation is lacking but I assume this + * is a reflection of the IG4_I2C_ENABLE bit in the + * I2C_EN register. + * + */ +#define IG4_ENASTAT_DATA_LOST 0x0004 +#define IG4_ENASTAT_ENABLED 0x0001 + +/* + * COMP_PARAM1 - (RO) Component Parameter Register 22.2.35 + * Default Value 0x00FFFF6E + * + * VALID - Intel documentation is unclear but I believe this + * must be read as a 1 to indicate that the rest of + * the bits in the register are valid. + * + * HASDMA - Indicates that the chip is DMA-capable. Presumably + * in certain virtualization cases the chip might be + * set to not be DMA-capable. + * + * INTR_IO - Indicates that all interrupts are combined to + * generate one interrupt. If not set, interrupts + * are individual (more virtualization stuff?) + * + * HCCNT_RO - Indicates that the clock timing registers are + * RW. If not set, the registers are RO. + * (more virtualization stuff). + * + * MAXSPEED - Indicates the maximum speed supported. + * + * DATAW - Indicates the internal bus width in bits. + */ +#define IG4_PARAM1_TXFIFO_DEPTH(v) (((v) >> 16) & 0xFF) +#define IG4_PARAM1_RXFIFO_DEPTH(v) (((v) >> 8) & 0xFF) +#define IG4_PARAM1_CONFIG_VALID 0x00000080 +#define IG4_PARAM1_CONFIG_HASDMA 0x00000040 +#define IG4_PARAM1_CONFIG_INTR_IO 0x00000020 +#define IG4_PARAM1_CONFIG_HCCNT_RO 0x00000010 +#define IG4_PARAM1_CONFIG_MAXSPEED_MASK 0x0000000C +#define IG4_PARAM1_CONFIG_DATAW_MASK 0x00000003 + +#define IG4_CONFIG_MAXSPEED_RESERVED00 0x00000000 +#define IG4_CONFIG_MAXSPEED_STANDARD 0x00000004 +#define IG4_CONFIG_MAXSPEED_FAST 0x00000008 +#define IG4_CONFIG_MAXSPEED_HIGH 0x0000000C + +#define IG4_CONFIG_DATAW_8 0x00000000 +#define IG4_CONFIG_DATAW_16 0x00000001 +#define IG4_CONFIG_DATAW_32 0x00000002 +#define IG4_CONFIG_DATAW_RESERVED11 0x00000003 + +/* + * COMP_VER - (RO) Component Version Register 22.2.36 + * Default Value 0x3131352A + * + * Contains the chip version number. All 32 bits. + */ +#define IG4_COMP_VER 0x3131352A + +/* + * COMP_TYPE - (RO) (linux) Endian and bus width probe + * + * Read32 from this register and test against IG4_COMP_TYPE + * to determine the bus width. e.g. 01404457 = endian-reversed, + * and 00000140 or 00004457 means internal 16-bit bus (?). + * + * This register is not in the intel documentation, I pulled it + * from the linux driver i2c-designware-core.c. + */ +#define IG4_COMP_TYPE 0x44570140 + +/* + * RESETS - (RW) Resets Register 22.2.37 + * + * Used to reset the I2C host controller by SW. There is no timing + * requirement, software can assert and de-assert in back-to-back + * transactions. + * + * 00 I2C host controller is NOT in reset. + * 01 (reserved) + * 10 (reserved) + * 11 I2C host controller is in reset. + */ +#define IG4_RESETS_ASSERT 0x0003 +#define IG4_RESETS_DEASSERT 0x0000 + +/* + * GENERAL - (RW) General Reigster 22.2.38 + * + * IOVOLT 0=1.8V 1=3.3V + * + * LTR 0=Auto 1=SW + * + * In Auto mode the BIOS will write to the host controller's + * AUTO LTR Value register (offset 0x0814) with the active + * state LTR value, and will write to the SW LTR Value register + * (offset 0x0810) with the idle state LTR value. + * + * In SW mode the SW will write to the host controller SW LTR + * value (offset 0x0810). It is the SW responsibility to update + * the LTR with the appropriate value. + */ +#define IG4_GENERAL_IOVOLT3_3 0x0008 +#define IG4_GENERAL_SWMODE 0x0004 + +/* + * SW_LTR_VALUE - (RW) SW LTR Value Register 22.2.39 + * AUTO_LTR_VALUE - (RW) SW LTR Value Register 22.2.40 + * + * Default value is 0x00000800 which means the best possible + * service/response time. + * + * It isn't quite clear how the snooping works. There are two scale + * bits for both sets but two of the four codes are reserved. The + * *SNOOP_VALUE() is specified as a 10-bit latency value. If 0, it + * indicates that the device cannot tolerate any delay and needs the + * best possible service/response time. + * + * I think this is for snooping (testing) the I2C bus. The lowest + * delay (0) probably runs the controller polling at a high, power hungry + * rate. But I dunno. + */ +#define IG4_SWLTR_NSNOOP_REQ 0x80000000 /* (ro) */ +#define IG4_SWLTR_NSNOOP_SCALE_MASK 0x1C000000 /* (ro) */ +#define IG4_SWLTR_NSNOOP_SCALE_1US 0x08000000 /* (ro) */ +#define IG4_SWLTR_NSNOOP_SCALE_32US 0x0C000000 /* (ro) */ +#define IG4_SWLTR_NSNOOP_VALUE_DECODE(v) (((v) >> 16) & 0x3F) +#define IG4_SWLTR_NSNOOP_VALUE_ENCODE(v) (((v) & 0x3F) << 16) + +#define IG4_SWLTR_SNOOP_REQ 0x00008000 /* (rw) */ +#define IG4_SWLTR_SNOOP_SCALE_MASK 0x00001C00 /* (rw) */ +#define IG4_SWLTR_SNOOP_SCALE_1US 0x00000800 /* (rw) */ +#define IG4_SWLTR_SNOOP_SCALE_32US 0x00000C00 /* (rw) */ +#define IG4_SWLTR_SNOOP_VALUE_DECODE(v) ((v) & 0x3F) +#define IG4_SWLTR_SNOOP_VALUE_ENCODE(v) ((v) & 0x3F) + +#endif diff --git a/sys/dev/ichiic/ig4_var.h b/sys/dev/ichiic/ig4_var.h new file mode 100644 index 000000000000..6c910559b7ef --- /dev/null +++ b/sys/dev/ichiic/ig4_var.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon and was subsequently ported + * to FreeBSD by Michael Gmelin + * + * 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. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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 _BUS_SMBUS_INTELGEN4_IG4_VAR_H_ +#define _BUS_SMBUS_INTELGEN4_IG4_VAR_H_ + +#include "bus_if.h" +#include "device_if.h" +#include "pci_if.h" +#include "smbus_if.h" + +#define IG4_RBUFSIZE 128 +#define IG4_RBUFMASK (IG4_RBUFSIZE - 1) + +enum ig4_op { IG4_IDLE, IG4_READ, IG4_WRITE }; + +struct ig4iic_softc { + device_t dev; + struct intr_config_hook enum_hook; + device_t smb; + struct resource *regs_res; + int regs_rid; + struct resource *intr_res; + int intr_rid; + void *intr_handle; + int intr_type; + enum ig4_op op; + int cmd; + int rnext; + int rpos; + char rbuf[IG4_RBUFSIZE]; + int error; + uint8_t last_slave; + int pci_attached : 1; + int use_10bit : 1; + int slave_valid : 1; + int read_started : 1; + int write_started : 1; + struct mtx mutex; +}; + +typedef struct ig4iic_softc ig4iic_softc_t; + +/* Attach/Detach called from ig4iic_pci_*() */ +int ig4iic_attach(ig4iic_softc_t *sc); +int ig4iic_detach(ig4iic_softc_t *sc); + +/* SMBus methods */ +extern smbus_callback_t ig4iic_smb_callback; +extern smbus_quick_t ig4iic_smb_quick; +extern smbus_sendb_t ig4iic_smb_sendb; +extern smbus_recvb_t ig4iic_smb_recvb; +extern smbus_writeb_t ig4iic_smb_writeb; +extern smbus_writew_t ig4iic_smb_writew; +extern smbus_readb_t ig4iic_smb_readb; +extern smbus_readw_t ig4iic_smb_readw; +extern smbus_pcall_t ig4iic_smb_pcall; +extern smbus_bwrite_t ig4iic_smb_bwrite; +extern smbus_bread_t ig4iic_smb_bread; +extern smbus_trans_t ig4iic_smb_trans; + +#endif diff --git a/sys/modules/i2c/controllers/Makefile b/sys/modules/i2c/controllers/Makefile index 2b4432fef109..132ff2d3babe 100644 --- a/sys/modules/i2c/controllers/Makefile +++ b/sys/modules/i2c/controllers/Makefile @@ -3,7 +3,7 @@ .if ${MACHINE} == "pc98" SUBDIR = lpbb .else -SUBDIR = alpm amdpm amdsmb ichsmb intpm ismt nfsmb viapm lpbb pcf +SUBDIR = alpm amdpm amdsmb ichiic ichsmb intpm ismt nfsmb viapm lpbb pcf .endif .include diff --git a/sys/modules/i2c/controllers/ichiic/Makefile b/sys/modules/i2c/controllers/ichiic/Makefile new file mode 100644 index 000000000000..288a79e450bd --- /dev/null +++ b/sys/modules/i2c/controllers/ichiic/Makefile @@ -0,0 +1,8 @@ +#$FreeBSD$ + +.PATH: ${.CURDIR}/../../../../dev/ichiic +KMOD = ig4 +SRCS = device_if.h bus_if.h iicbb_if.h pci_if.h smbus_if.h \ + ig4_iic.c ig4_pci.c ig4_reg.h ig4_var.h + +.include From dc368d812a1d307a439e0a5823d4695d16c98c45 Mon Sep 17 00:00:00 2001 From: sjg Date: Sat, 30 May 2015 15:08:52 +0000 Subject: [PATCH 64/65] Define SRCTOP in src.sys.mk Because src.sys.mk should only ever be found in the src tree we can use its position (.PARSEDIR) to set SRCTOP. Reviewed by: bapt, imp --- share/mk/src.sys.mk | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/share/mk/src.sys.mk b/share/mk/src.sys.mk index 78a0c2378671..580481071eed 100644 --- a/share/mk/src.sys.mk +++ b/share/mk/src.sys.mk @@ -5,13 +5,16 @@ # to preserve historical (and useful) behavior. Changes here need to # be reflected there so SRCCONF isn't included multiple times. +# make sure this is defined in a consistent manner +SRCTOP:= ${.PARSEDIR:tA:H:H} + # Allow user to configure things that only effect src tree builds. SRCCONF?= /etc/src.conf .if (exists(${SRCCONF}) || ${SRCCONF} != "/etc/src.conf") && !target(_srcconf_included_) -.include "${SRCCONF}" +.sinclude "${SRCCONF}" _srcconf_included_: .NOTMAIN .endif -# If we were found via .../share/mk we need to replace that in +# If we were found via .../share/mk we need to replace that # with ${.PARSEDIR:tA} so that we can be found by # sub-makes launched from objdir. .if ${.MAKEFLAGS:M.../share/mk} != "" From aeffa88e8a4df5f16e1ca1e5971353bcea1a20f5 Mon Sep 17 00:00:00 2001 From: sjg Date: Sat, 30 May 2015 15:13:18 +0000 Subject: [PATCH 65/65] Use SRCTOP when defining ROOTOBJDIR Excplicitly check rather than assume that .CURDIR is a component of .OBJDIR Otherwise check for OBJTOP and if that is a match use it. --- share/mk/src.libnames.mk | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk index bfb235c46656..e8c6dd236245 100644 --- a/share/mk/src.libnames.mk +++ b/share/mk/src.libnames.mk @@ -9,8 +9,12 @@ .include -ROOTSRCDIR= ${.MAKE.MAKEFILES:M*/src.libnames.mk:H:H:H} -ROOTOBJDIR= ${.OBJDIR:S/${.CURDIR}//}${ROOTSRCDIR} +.if ${.OBJDIR:S,${.CURDIR},,} != ${.OBJDIR} +ROOTOBJDIR= ${.OBJDIR:S,${.CURDIR},,}${SRCTOP} +.elif defined(OBJTOP) && ${.OBJDIR:M${OBJTOP}*} != "" +ROOTOBJDIR= ${OBJTOP} +.endif + _PRIVATELIBS= \ atf_c \ atf_cxx \