diff options
Diffstat (limited to 'sys')
49 files changed, 1973 insertions, 286 deletions
diff --git a/sys/amd64/linux/linux.h b/sys/amd64/linux/linux.h index c56cb80f7108..d4e66821b334 100644 --- a/sys/amd64/linux/linux.h +++ b/sys/amd64/linux/linux.h @@ -101,9 +101,6 @@ typedef struct { /* * Miscellaneous */ -#define LINUX_NAME_MAX 255 -#define LINUX_CTL_MAXNAME 10 - #define LINUX_AT_COUNT 19 /* Count of used aux entry types. */ struct l___sysctl_args @@ -117,11 +114,6 @@ struct l___sysctl_args l_ulong __spare[4]; }; -/* Scheduling policies */ -#define LINUX_SCHED_OTHER 0 -#define LINUX_SCHED_FIFO 1 -#define LINUX_SCHED_RR 2 - /* Resource limits */ #define LINUX_RLIMIT_CPU 0 #define LINUX_RLIMIT_FSIZE 1 @@ -456,20 +448,6 @@ struct l_pollfd { l_short revents; }; - -#define LINUX_CLONE_VM 0x00000100 -#define LINUX_CLONE_FS 0x00000200 -#define LINUX_CLONE_FILES 0x00000400 -#define LINUX_CLONE_SIGHAND 0x00000800 -#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */ -#define LINUX_CLONE_VFORK 0x00004000 -#define LINUX_CLONE_PARENT 0x00008000 -#define LINUX_CLONE_THREAD 0x00010000 -#define LINUX_CLONE_SETTLS 0x00080000 -#define LINUX_CLONE_PARENT_SETTID 0x00100000 -#define LINUX_CLONE_CHILD_CLEARTID 0x00200000 -#define LINUX_CLONE_CHILD_SETTID 0x01000000 - #define LINUX_ARCH_SET_GS 0x1001 #define LINUX_ARCH_SET_FS 0x1002 #define LINUX_ARCH_GET_FS 0x1003 diff --git a/sys/arm/conf/ARMADA38X b/sys/arm/conf/ARMADA38X index 4351874620aa..35b68a1db9d5 100644 --- a/sys/arm/conf/ARMADA38X +++ b/sys/arm/conf/ARMADA38X @@ -76,6 +76,14 @@ device iic device iicbus device twsi +# Wireless NIC cards +device wlan # 802.11 support +device ath # Atheros NIC's +device ath_pci # Atheros pci/cardbus glue +device ath_hal +device ath_rate_sample +options ATH_ENABLE_11N + # CESA device cesa device crypto diff --git a/sys/boot/common/dev_net.c b/sys/boot/common/dev_net.c index b209185f0709..c5b1e0abd92b 100644 --- a/sys/boot/common/dev_net.c +++ b/sys/boot/common/dev_net.c @@ -97,6 +97,14 @@ struct devsw netdev = { net_cleanup }; +static struct uri_scheme { + const char *scheme; + int proto; +} uri_schemes[] = { + { "tftp:/", NET_TFTP }, + { "nfs:/", NET_NFS }, +}; + static int net_init(void) { @@ -248,8 +256,6 @@ net_getparams(int sock) { char buf[MAXHOSTNAMELEN]; n_long rootaddr, smask; - struct iodesc *d = socktodesc(sock); - extern struct in_addr servip; #ifdef SUPPORT_BOOTP /* @@ -258,26 +264,8 @@ net_getparams(int sock) * be initialized. If any remain uninitialized, we will * use RARP and RPC/bootparam (the Sun way) to get them. */ - if (try_bootp) { - int rc = -1; - if (bootp_response != NULL) { - rc = dhcp_try_rfc1048(bootp_response->bp_vend, - bootp_response_size - - offsetof(struct bootp, bp_vend)); - - if (servip.s_addr == 0) - servip = bootp_response->bp_siaddr; - if (rootip.s_addr == 0) - rootip = bootp_response->bp_siaddr; - if (gateip.s_addr == 0) - gateip = bootp_response->bp_giaddr; - if (myip.s_addr == 0) - myip = bootp_response->bp_yiaddr; - d->myip = myip; - } - if (rc < 0) - bootp(sock, BOOTP_NONE); - } + if (try_bootp) + bootp(sock); if (myip.s_addr != 0) goto exit; #ifdef NETIF_DEBUG @@ -334,11 +322,8 @@ net_getparams(int sock) return (EIO); } exit: - netproto = NET_TFTP; - if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) { - netproto = NET_NFS; + if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) rootip.s_addr = rootaddr; - } #ifdef NETIF_DEBUG if (debug) { @@ -381,20 +366,69 @@ net_print(int verbose) } /* - * Strip the server's address off of the rootpath if present and return it in - * network byte order, leaving just the pathname part in the global rootpath. + * Parses the rootpath if present + * + * The rootpath format can be in the form + * <scheme>://ip/path + * <scheme>:/path + * + * For compatibility with previous behaviour it also accepts as an NFS scheme + * ip:/path + * /path + * + * If an ip is set it returns it in network byte order. + * The default scheme defined in the global netproto, if not set it defaults to + * NFS. + * It leaves just the pathname in the global rootpath. */ uint32_t net_parse_rootpath() { - n_long addr = INADDR_NONE; - char *ptr; + n_long addr = htonl(INADDR_NONE); + size_t i; + char ip[FNAME_SIZE]; + char *ptr, *val; + + netproto = NET_NONE; + for (i = 0; i < nitems(uri_schemes); i++) { + if (strncmp(rootpath, uri_schemes[i].scheme, + strlen(uri_schemes[i].scheme)) != 0) + continue; + + netproto = uri_schemes[i].proto; + break; + } ptr = rootpath; - (void)strsep(&ptr, ":"); - if (ptr != NULL) { - addr = inet_addr(rootpath); - bcopy(ptr, rootpath, strlen(ptr) + 1); + /* Fallback for compatibility mode */ + if (netproto == NET_NONE) { + netproto = NET_NFS; + (void)strsep(&ptr, ":"); + if (ptr != NULL) { + addr = inet_addr(rootpath); + bcopy(ptr, rootpath, strlen(ptr) + 1); + } + } else { + ptr += strlen(uri_schemes[i].scheme); + if (*ptr == '/') { + /* we are in the form <scheme>://, we do expect an ip */ + ptr++; + /* + * XXX when http will be there we will need to check for + * a port, but right now we do not need it yet + */ + val = strchr(ptr, '/'); + if (val != NULL) { + snprintf(ip, sizeof(ip), "%.*s", + (int)((uintptr_t)val - (uintptr_t)ptr), + ptr); + addr = inet_addr(ip); + bcopy(val, rootpath, strlen(val) + 1); + } + } else { + ptr--; + bcopy(ptr, rootpath, strlen(ptr) + 1); + } } return (addr); diff --git a/sys/boot/i386/loader/Makefile b/sys/boot/i386/loader/Makefile index 6bdffc147bc0..84404efb05d3 100644 --- a/sys/boot/i386/loader/Makefile +++ b/sys/boot/i386/loader/Makefile @@ -10,6 +10,8 @@ INTERNALPROG= NEWVERSWHAT?= "bootstrap loader" x86 VERSION_FILE= ${.CURDIR}/../loader/version LOADER_NET_SUPPORT?= yes +LOADER_NFS_SUPPORT?= yes +LOADER_TFTP_SUPPORT?= yes # architecture-specific loader code SRCS= main.c conf.c vers.c @@ -30,10 +32,10 @@ LIBZFSBOOT= ${.OBJDIR}/../../zfs/libzfsboot.a CFLAGS+= -I${.CURDIR}/../../../../lib/libstand .endif -# Enable PXE TFTP or NFS support, not both. .if defined(LOADER_TFTP_SUPPORT) CFLAGS+= -DLOADER_TFTP_SUPPORT -.else +.endif +.if defined(LOADER_NFS_SUPPORT) CFLAGS+= -DLOADER_NFS_SUPPORT .endif diff --git a/sys/boot/i386/pxeldr/pxeboot.8 b/sys/boot/i386/pxeldr/pxeboot.8 index 91fca6d5c812..0194e218e523 100644 --- a/sys/boot/i386/pxeldr/pxeboot.8 +++ b/sys/boot/i386/pxeldr/pxeboot.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 16, 2017 +.Dd May 27, 2017 .Dt PXEBOOT 8 .Os .Sh NAME @@ -39,6 +39,11 @@ configured to run under Intel's Preboot Execution Environment (PXE) system. PXE is a form of smart boot ROM, built into Intel EtherExpress Pro/100 and 3Com 3c905c Ethernet cards, and Ethernet-equipped Intel motherboards. PXE supports DHCP configuration and provides low-level NIC access services. +.Pp +The DHCP client will set a DHCP user class named +.Va FreeBSD +to allow flexible configuration of the DHCP server. +.Pp The .Nm bootloader retrieves the kernel, modules, @@ -69,6 +74,9 @@ max-lease-time 120; subnet 10.0.0.0 netmask 255.255.255.0 { filename "pxeboot"; range 10.0.0.10 10.0.0.254; + if exists user-class and option user-class = "FreeBSD" { + option root-path "tftp://10.0.0.1/FreeBSD"; + } } .Ed @@ -85,6 +93,27 @@ expects to fetch .Pa /boot/loader.rc from the specified server before loading any other files. .Pp +Valid +.Va option root-path +Syntax is the following +.Bl -tag -width <scheme>://ip/path indent +.It /path +path to the root filesystem on the NFS server +.It ip:/path +path to the root filesystem on the NFS server +.Ar ip +.It nfs:/path +path to the root filesystem on the NFS server +.It nfs://ip/path +path to the root filesystem on the NFS server +.Ar ip +.It tftp:/path +path to the root filesystem on the TFTP server +.It tftp://ip/path +path to the root filesystem on the TFTP server +.Ar ip +.El +.Pp .Nm defaults to a conservative 1024 byte NFS data packet size. This may be changed by setting the diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 4a6f5e362d84..9cf71ab8ba4c 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -684,6 +684,13 @@ static struct da_quirk_entry da_quirk_table[] = }, { /* + * Genesys GL3224 + */ + {T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "STORAGE DEVICE*", + "120?"}, /*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_4K | DA_Q_NO_RC16 + }, + { + /* * Genesys 6-in-1 Card Reader * PR: usb/94647 */ diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index b4da50d9e0cc..74364f05f4b3 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -547,6 +547,14 @@ static struct scsi_quirk_entry scsi_quirk_table[] = CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255 }, { + { T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic", "STORAGE DEVICE*", "120?" }, + CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255 + }, + { + { T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic", "MassStorageClass", "1533" }, + CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255 + }, + { /* Default tagged queuing parameters for all devices */ { T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 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 855dd871074f..9a6fcbe347a4 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 @@ -497,7 +497,7 @@ zfsctl_common_getattr(vnode_t *vp, vattr_t *vap) vap->va_blksize = 0; vap->va_nblocks = 0; vap->va_seq = 0; - vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; + vn_fsid(vp, vap); vap->va_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; vap->va_type = VDIR; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 840ac7934af9..90514860e8ba 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -1635,7 +1635,7 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp, cn.cn_nameptr = "snapshot"; cn.cn_namelen = strlen(cn.cn_nameptr); cn.cn_nameiop = cnp->cn_nameiop; - cn.cn_flags = cnp->cn_flags; + cn.cn_flags = cnp->cn_flags & ~ISDOTDOT; cn.cn_lkflags = cnp->cn_lkflags; error = VOP_LOOKUP(zfsctl_vp, vpp, &cn); vput(zfsctl_vp); @@ -2708,7 +2708,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, #ifdef illumos vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_dev; #else - vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; + vn_fsid(vp, vap); #endif vap->va_nodeid = zp->z_id; if ((vp->v_flag & VROOT) && zfs_show_ctldir(zp)) diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 9db1767e7c43..a815ccf3afa0 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -31,6 +31,9 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" +#if defined(KLD_MODULE) +#include "opt_global.h" +#endif #include <sys/param.h> #include <sys/blist.h> @@ -2516,6 +2519,7 @@ linux_getrandom(struct thread *td, struct linux_getrandom_args *args) { struct uio uio; struct iovec iov; + int error; if (args->flags & ~(LINUX_GRND_NONBLOCK|LINUX_GRND_RANDOM)) return (EINVAL); @@ -2532,7 +2536,10 @@ linux_getrandom(struct thread *td, struct linux_getrandom_args *args) uio.uio_rw = UIO_READ; uio.uio_td = td; - return (read_random_uio(&uio, args->flags & LINUX_GRND_NONBLOCK)); + error = read_random_uio(&uio, args->flags & LINUX_GRND_NONBLOCK); + if (error == 0) + td->td_retval[0] = args->count - uio.uio_resid; + return (error); } int diff --git a/sys/conf/config.mk b/sys/conf/config.mk index ef4b8820d947..63d7ac6ec87a 100644 --- a/sys/conf/config.mk +++ b/sys/conf/config.mk @@ -8,6 +8,8 @@ # the code here when they all produce identical results # (or should) .if !defined(KERNBUILDDIR) +opt_global.h: + echo "#define DEV_RANDOM 1" >> ${.TARGET} opt_bpf.h: echo "#define DEV_BPF 1" > ${.TARGET} .if ${MK_INET_SUPPORT} != "no" diff --git a/sys/conf/files b/sys/conf/files index f929ef142265..0257f9c5be6c 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3525,6 +3525,7 @@ geom/virstor/binstream.c optional geom_virstor geom/virstor/g_virstor.c optional geom_virstor geom/virstor/g_virstor_md.c optional geom_virstor geom/zero/g_zero.c optional geom_zero +fs/ext2fs/ext2_acl.c optional ext2fs fs/ext2fs/ext2_alloc.c optional ext2fs fs/ext2fs/ext2_balloc.c optional ext2fs fs/ext2fs/ext2_bmap.c optional ext2fs diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index 1e02b4582e20..9ef170d57bae 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -497,9 +497,7 @@ ipf_nat_soft_init(softc, arg) softn->ipf_nat_pending.ifq_next = NULL; for (i = 0, tq = softn->ipf_nat_tcptq; i < IPF_TCP_NSTATES; i++, tq++) { -#ifdef LARGE_NAT if (tq->ifq_ttl < softn->ipf_nat_deficmpage) -#endif tq->ifq_ttl = softn->ipf_nat_deficmpage; #ifdef LARGE_NAT else if (tq->ifq_ttl > softn->ipf_nat_defage) diff --git a/sys/contrib/ipfilter/netinet/ip_sync.c b/sys/contrib/ipfilter/netinet/ip_sync.c index 0c2fe10b3ba3..59094097864b 100644 --- a/sys/contrib/ipfilter/netinet/ip_sync.c +++ b/sys/contrib/ipfilter/netinet/ip_sync.c @@ -939,7 +939,7 @@ ipf_sync_nat(softc, sp, data) nat_t *n, *nat; synclist_t *sl; u_int hv = 0; - int err; + int err = 0; READ_ENTER(&softs->ipf_syncnat); @@ -1016,7 +1016,7 @@ ipf_sync_nat(softc, sp, data) } RWLOCK_EXIT(&softs->ipf_syncnat); - return 0; + return err; } diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c index 42a0ebb1f99f..74c6f1a3b16b 100644 --- a/sys/dev/ath/ath_hal/ah.c +++ b/sys/dev/ath/ath_hal/ah.c @@ -302,7 +302,7 @@ ath_hal_rf_name(struct ath_hal *ah) HAL_BOOL ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val) { -#define AH_TIMEOUT 1000 +#define AH_TIMEOUT 5000 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT); #undef AH_TIMEOUT } diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index 94ea8209b6d4..c077a68190e9 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include "opt_isa.h" #include "opt_psm.h" +#include "opt_evdev.h" #include <sys/param.h> #include <sys/systm.h> @@ -90,6 +91,11 @@ __FBSDID("$FreeBSD$"); #include <isa/isavar.h> #endif +#ifdef EVDEV_SUPPORT +#include <dev/evdev/evdev.h> +#include <dev/evdev/input.h> +#endif + #include <dev/atkbdc/atkbdcreg.h> #include <dev/atkbdc/psm.h> @@ -325,8 +331,14 @@ typedef struct elantechhw { #define ELANTECH_REG_RDWR 0x00 #define ELANTECH_CUSTOM_CMD 0xf8 +#ifdef EVDEV_SUPPORT +#define ELANTECH_MAX_FINGERS 5 +#else #define ELANTECH_MAX_FINGERS PSM_FINGERS +#endif +#define ELANTECH_FINGER_MAX_P 255 +#define ELANTECH_FINGER_MAX_W 15 #define ELANTECH_FINGER_SET_XYP(pb) (finger_t) { \ .x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2], \ .y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5], \ @@ -418,6 +430,10 @@ struct psm_softc { /* Driver status information */ int cmdcount; struct sigio *async; /* Processes waiting for SIGIO */ int extended_buttons; +#ifdef EVDEV_SUPPORT + struct evdev_dev *evdev_a; /* Absolute reporting device */ + struct evdev_dev *evdev_r; /* Relative reporting device */ +#endif }; static devclass_t psm_devclass; @@ -427,6 +443,8 @@ static devclass_t psm_devclass; #define PSM_ASLP 2 /* Waiting for mouse data */ #define PSM_SOFTARMED 4 /* Software interrupt armed */ #define PSM_NEED_SYNCBITS 8 /* Set syncbits using next data pkt */ +#define PSM_EV_OPEN_R 0x10 /* Relative evdev device is open */ +#define PSM_EV_OPEN_A 0x20 /* Absolute evdev device is open */ /* driver configuration flags (config) */ #define PSM_CONFIG_RESOLUTION 0x000f /* resolution */ @@ -532,13 +550,23 @@ static int psmattach(device_t); static int psmdetach(device_t); static int psmresume(device_t); -static d_open_t psmopen; -static d_close_t psmclose; +static d_open_t psm_cdev_open; +static d_close_t psm_cdev_close; static d_read_t psmread; static d_write_t psmwrite; static d_ioctl_t psmioctl; static d_poll_t psmpoll; +static int psmopen(struct psm_softc *); +static int psmclose(struct psm_softc *); + +#ifdef EVDEV_SUPPORT +static evdev_open_t psm_ev_open_r; +static evdev_close_t psm_ev_close_r; +static evdev_open_t psm_ev_open_a; +static evdev_close_t psm_ev_close_a; +#endif + static int enable_aux_dev(KBDC); static int disable_aux_dev(KBDC); static int get_mouse_status(KBDC, int *, int, int); @@ -668,8 +696,8 @@ static driver_t psm_driver = { static struct cdevsw psm_cdevsw = { .d_version = D_VERSION, .d_flags = D_NEEDGIANT, - .d_open = psmopen, - .d_close = psmclose, + .d_open = psm_cdev_open, + .d_close = psm_cdev_close, .d_read = psmread, .d_write = psmwrite, .d_ioctl = psmioctl, @@ -677,6 +705,17 @@ static struct cdevsw psm_cdevsw = { .d_name = PSM_DRIVER_NAME, }; +#ifdef EVDEV_SUPPORT +static const struct evdev_methods psm_ev_methods_r = { + .ev_open = psm_ev_open_r, + .ev_close = psm_ev_close_r, +}; +static const struct evdev_methods psm_ev_methods_a = { + .ev_open = psm_ev_open_a, + .ev_close = psm_ev_close_a, +}; +#endif + /* device I/O routines */ static int enable_aux_dev(KBDC kbdc) @@ -1197,7 +1236,8 @@ reinitialize(struct psm_softc *sc, int doinit) splx(s); /* restore the driver state */ - if ((sc->state & PSM_OPEN) && (err == 0)) { + if ((sc->state & (PSM_OPEN | PSM_EV_OPEN_R | PSM_EV_OPEN_A)) && + (err == 0)) { /* enable the aux device and the port again */ err = doopen(sc, c); if (err != 0) @@ -1578,6 +1618,270 @@ psmprobe(device_t dev) return (0); } +#ifdef EVDEV_SUPPORT +/* Values are taken from Linux drivers for userland software compatibility */ +#define PS2_MOUSE_VENDOR 0x0002 +#define PS2_MOUSE_GENERIC_PRODUCT 0x0001 +#define PS2_MOUSE_SYNAPTICS_NAME "SynPS/2 Synaptics TouchPad" +#define PS2_MOUSE_SYNAPTICS_PRODUCT 0x0007 +#define PS2_MOUSE_TRACKPOINT_NAME "TPPS/2 IBM TrackPoint" +#define PS2_MOUSE_TRACKPOINT_PRODUCT 0x000A +#define PS2_MOUSE_ELANTECH_NAME "ETPS/2 Elantech Touchpad" +#define PS2_MOUSE_ELANTECH_ST_NAME "ETPS/2 Elantech TrackPoint" +#define PS2_MOUSE_ELANTECH_PRODUCT 0x000E + +#define ABSINFO_END { ABS_CNT, 0, 0, 0 } + +static void +psm_support_abs_bulk(struct evdev_dev *evdev, const uint16_t info[][4]) +{ + size_t i; + + for (i = 0; info[i][0] != ABS_CNT; i++) + evdev_support_abs(evdev, info[i][0], 0, info[i][1], info[i][2], + 0, 0, info[i][3]); +} + +static void +psm_push_mt_finger(struct psm_softc *sc, int id, const finger_t *f) +{ + int y = sc->synhw.minimumYCoord + sc->synhw.maximumYCoord - f->y; + + evdev_push_abs(sc->evdev_a, ABS_MT_SLOT, id); + evdev_push_abs(sc->evdev_a, ABS_MT_TRACKING_ID, id); + evdev_push_abs(sc->evdev_a, ABS_MT_POSITION_X, f->x); + evdev_push_abs(sc->evdev_a, ABS_MT_POSITION_Y, y); + evdev_push_abs(sc->evdev_a, ABS_MT_PRESSURE, f->p); +} + +static void +psm_push_st_finger(struct psm_softc *sc, const finger_t *f) +{ + int y = sc->synhw.minimumYCoord + sc->synhw.maximumYCoord - f->y; + + evdev_push_abs(sc->evdev_a, ABS_X, f->x); + evdev_push_abs(sc->evdev_a, ABS_Y, y); + evdev_push_abs(sc->evdev_a, ABS_PRESSURE, f->p); + if (sc->synhw.capPalmDetect) + evdev_push_abs(sc->evdev_a, ABS_TOOL_WIDTH, f->w); +} + +static void +psm_release_mt_slot(struct evdev_dev *evdev, int32_t slot) +{ + + evdev_push_abs(evdev, ABS_MT_SLOT, slot); + evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1); +} + +static int +psm_register(device_t dev, int model_code) +{ + struct psm_softc *sc = device_get_softc(dev); + struct evdev_dev *evdev_r; + int error, i, nbuttons, nwheels, product; + bool is_pointing_stick; + const char *name; + + name = model_name(model_code); + nbuttons = sc->hw.buttons; + product = PS2_MOUSE_GENERIC_PRODUCT; + nwheels = 0; + is_pointing_stick = false; + + switch (model_code) { + case MOUSE_MODEL_TRACKPOINT: + name = PS2_MOUSE_TRACKPOINT_NAME; + product = PS2_MOUSE_TRACKPOINT_PRODUCT; + nbuttons = 3; + is_pointing_stick = true; + break; + + case MOUSE_MODEL_ELANTECH: + name = PS2_MOUSE_ELANTECH_ST_NAME; + product = PS2_MOUSE_ELANTECH_PRODUCT; + nbuttons = 3; + is_pointing_stick = true; + break; + + case MOUSE_MODEL_MOUSEMANPLUS: + case MOUSE_MODEL_4D: + nwheels = 2; + break; + + case MOUSE_MODEL_EXPLORER: + case MOUSE_MODEL_INTELLI: + case MOUSE_MODEL_NET: + case MOUSE_MODEL_NETSCROLL: + case MOUSE_MODEL_4DPLUS: + nwheels = 1; + break; + } + + evdev_r = evdev_alloc(); + evdev_set_name(evdev_r, name); + evdev_set_phys(evdev_r, device_get_nameunit(dev)); + evdev_set_id(evdev_r, BUS_I8042, PS2_MOUSE_VENDOR, product, 0); + evdev_set_methods(evdev_r, sc, &psm_ev_methods_r); + + evdev_support_prop(evdev_r, INPUT_PROP_POINTER); + if (is_pointing_stick) + evdev_support_prop(evdev_r, INPUT_PROP_POINTING_STICK); + evdev_support_event(evdev_r, EV_SYN); + evdev_support_event(evdev_r, EV_KEY); + evdev_support_event(evdev_r, EV_REL); + evdev_support_rel(evdev_r, REL_X); + evdev_support_rel(evdev_r, REL_Y); + switch (nwheels) { + case 2: + evdev_support_rel(evdev_r, REL_HWHEEL); + /* FALLTHROUGH */ + case 1: + evdev_support_rel(evdev_r, REL_WHEEL); + } + for (i = 0; i < nbuttons; i++) + evdev_support_key(evdev_r, BTN_MOUSE + i); + + error = evdev_register_mtx(evdev_r, &Giant); + if (error) + evdev_free(evdev_r); + else + sc->evdev_r = evdev_r; + return (error); +} + +static int +psm_register_synaptics(device_t dev) +{ + struct psm_softc *sc = device_get_softc(dev); + const uint16_t synaptics_absinfo_st[][4] = { + { ABS_X, sc->synhw.minimumXCoord, + sc->synhw.maximumXCoord, sc->synhw.infoXupmm }, + { ABS_Y, sc->synhw.minimumYCoord, + sc->synhw.maximumYCoord, sc->synhw.infoYupmm }, + { ABS_PRESSURE, 0, ELANTECH_FINGER_MAX_P, 0 }, + ABSINFO_END, + }; + const uint16_t synaptics_absinfo_mt[][4] = { + { ABS_MT_SLOT, 0, PSM_FINGERS-1, 0}, + { ABS_MT_TRACKING_ID, -1, PSM_FINGERS-1, 0}, + { ABS_MT_POSITION_X, sc->synhw.minimumXCoord, + sc->synhw.maximumXCoord, sc->synhw.infoXupmm }, + { ABS_MT_POSITION_Y, sc->synhw.minimumYCoord, + sc->synhw.maximumYCoord, sc->synhw.infoYupmm }, + { ABS_MT_PRESSURE, 0, ELANTECH_FINGER_MAX_P, 0 }, + ABSINFO_END, + }; + struct evdev_dev *evdev_a; + int error, i, guest_model; + + evdev_a = evdev_alloc(); + evdev_set_name(evdev_a, PS2_MOUSE_SYNAPTICS_NAME); + evdev_set_phys(evdev_a, device_get_nameunit(dev)); + evdev_set_id(evdev_a, BUS_I8042, PS2_MOUSE_VENDOR, + PS2_MOUSE_SYNAPTICS_PRODUCT, 0); + evdev_set_methods(evdev_a, sc, &psm_ev_methods_a); + + evdev_support_event(evdev_a, EV_SYN); + evdev_support_event(evdev_a, EV_KEY); + evdev_support_event(evdev_a, EV_ABS); + evdev_support_prop(evdev_a, INPUT_PROP_POINTER); + if (sc->synhw.capAdvancedGestures) + evdev_support_prop(evdev_a, INPUT_PROP_SEMI_MT); + if (sc->synhw.capClickPad) + evdev_support_prop(evdev_a, INPUT_PROP_BUTTONPAD); + evdev_support_key(evdev_a, BTN_TOUCH); + evdev_support_nfingers(evdev_a, 3); + psm_support_abs_bulk(evdev_a, synaptics_absinfo_st); + if (sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) + psm_support_abs_bulk(evdev_a, synaptics_absinfo_mt); + if (sc->synhw.capPalmDetect) + evdev_support_abs(evdev_a, ABS_TOOL_WIDTH, 0, 0, 15, 0, 0, 0); + evdev_support_key(evdev_a, BTN_LEFT); + if (!sc->synhw.capClickPad) { + evdev_support_key(evdev_a, BTN_RIGHT); + if (sc->synhw.capExtended && sc->synhw.capMiddle) + evdev_support_key(evdev_a, BTN_MIDDLE); + } + if (sc->synhw.capExtended && sc->synhw.capFourButtons) { + evdev_support_key(evdev_a, BTN_BACK); + evdev_support_key(evdev_a, BTN_FORWARD); + } + if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) + for (i = 0; i < sc->synhw.nExtendedButtons; i++) + evdev_support_key(evdev_a, BTN_0 + i); + + error = evdev_register_mtx(evdev_a, &Giant); + if (!error && sc->synhw.capPassthrough) { + guest_model = sc->tpinfo.sysctl_tree != NULL ? + MOUSE_MODEL_TRACKPOINT : MOUSE_MODEL_GENERIC; + error = psm_register(dev, guest_model); + } + if (error) + evdev_free(evdev_a); + else + sc->evdev_a = evdev_a; + return (error); +} + +static int +psm_register_elantech(device_t dev) +{ + struct psm_softc *sc = device_get_softc(dev); + const uint16_t elantech_absinfo[][4] = { + { ABS_X, 0, sc->elanhw.sizex, + sc->elanhw.dpmmx }, + { ABS_Y, 0, sc->elanhw.sizey, + sc->elanhw.dpmmy }, + { ABS_PRESSURE, 0, ELANTECH_FINGER_MAX_P, 0 }, + { ABS_TOOL_WIDTH, 0, ELANTECH_FINGER_MAX_W, 0 }, + { ABS_MT_SLOT, 0, ELANTECH_MAX_FINGERS - 1, 0 }, + { ABS_MT_TRACKING_ID, -1, ELANTECH_MAX_FINGERS - 1, 0 }, + { ABS_MT_POSITION_X, 0, sc->elanhw.sizex, + sc->elanhw.dpmmx }, + { ABS_MT_POSITION_Y, 0, sc->elanhw.sizey, + sc->elanhw.dpmmy }, + { ABS_MT_PRESSURE, 0, ELANTECH_FINGER_MAX_P, 0 }, + { ABS_MT_TOUCH_MAJOR, 0, ELANTECH_FINGER_MAX_W * + sc->elanhw.dptracex, 0 }, + ABSINFO_END, + }; + struct evdev_dev *evdev_a; + int error; + + evdev_a = evdev_alloc(); + evdev_set_name(evdev_a, PS2_MOUSE_ELANTECH_NAME); + evdev_set_phys(evdev_a, device_get_nameunit(dev)); + evdev_set_id(evdev_a, BUS_I8042, PS2_MOUSE_VENDOR, + PS2_MOUSE_ELANTECH_PRODUCT, 0); + evdev_set_methods(evdev_a, sc, &psm_ev_methods_a); + + evdev_support_event(evdev_a, EV_SYN); + evdev_support_event(evdev_a, EV_KEY); + evdev_support_event(evdev_a, EV_ABS); + evdev_support_prop(evdev_a, INPUT_PROP_POINTER); + if (sc->elanhw.issemimt) + evdev_support_prop(evdev_a, INPUT_PROP_SEMI_MT); + if (sc->elanhw.isclickpad) + evdev_support_prop(evdev_a, INPUT_PROP_BUTTONPAD); + evdev_support_key(evdev_a, BTN_TOUCH); + evdev_support_nfingers(evdev_a, ELANTECH_MAX_FINGERS); + evdev_support_key(evdev_a, BTN_LEFT); + if (!sc->elanhw.isclickpad) + evdev_support_key(evdev_a, BTN_RIGHT); + psm_support_abs_bulk(evdev_a, elantech_absinfo); + + error = evdev_register_mtx(evdev_a, &Giant); + if (!error && sc->elanhw.hastrackpoint) + error = psm_register(dev, MOUSE_MODEL_ELANTECH); + if (error) + evdev_free(evdev_a); + else + sc->evdev_a = evdev_a; + return (error); +} +#endif + static int psmattach(device_t dev) { @@ -1609,6 +1913,24 @@ psmattach(device_t dev) sc->bdev = make_dev(&psm_cdevsw, 0, 0, 0, 0666, "bpsm%d", unit); sc->bdev->si_drv1 = sc; +#ifdef EVDEV_SUPPORT + switch (sc->hw.model) { + case MOUSE_MODEL_SYNAPTICS: + error = psm_register_synaptics(dev); + break; + + case MOUSE_MODEL_ELANTECH: + error = psm_register_elantech(dev); + break; + + default: + error = psm_register(dev, sc->hw.model); + } + + if (error) + return (error); +#endif + /* Some touchpad devices need full reinitialization after suspend. */ switch (sc->hw.model) { case MOUSE_MODEL_SYNAPTICS: @@ -1657,6 +1979,11 @@ psmdetach(device_t dev) if (sc->state & PSM_OPEN) return (EBUSY); +#ifdef EVDEV_SUPPORT + evdev_free(sc->evdev_r); + evdev_free(sc->evdev_a); +#endif + rid = KBDC_RID_AUX; bus_teardown_intr(dev, sc->intr, sc->ih); bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); @@ -1670,13 +1997,83 @@ psmdetach(device_t dev) return (0); } +#ifdef EVDEV_SUPPORT +static int +psm_ev_open_r(struct evdev_dev *evdev, void *ev_softc) +{ + struct psm_softc *sc = (struct psm_softc *)ev_softc; + int err = 0; + + /* Get device data */ + if ((sc->state & PSM_VALID) == 0) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + + if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_A))) + err = psmopen(sc); + + if (err == 0) + sc->state |= PSM_EV_OPEN_R; + + return (err); +} + +static void +psm_ev_close_r(struct evdev_dev *evdev, void *ev_softc) +{ + struct psm_softc *sc = (struct psm_softc *)ev_softc; + + sc->state &= ~PSM_EV_OPEN_R; + + if (sc->state & (PSM_OPEN | PSM_EV_OPEN_A)) + return; + + if (sc->state & PSM_VALID) + psmclose(sc); +} + +static int +psm_ev_open_a(struct evdev_dev *evdev, void *ev_softc) +{ + struct psm_softc *sc = (struct psm_softc *)ev_softc; + int err = 0; + + /* Get device data */ + if ((sc->state & PSM_VALID) == 0) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + + if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_R))) + err = psmopen(sc); + + if (err == 0) + sc->state |= PSM_EV_OPEN_A; + + return (err); +} + +static void +psm_ev_close_a(struct evdev_dev *evdev, void *ev_softc) +{ + struct psm_softc *sc = (struct psm_softc *)ev_softc; + + sc->state &= ~PSM_EV_OPEN_A; + + if (sc->state & (PSM_OPEN | PSM_EV_OPEN_R)) + return; + + if (sc->state & PSM_VALID) + psmclose(sc); +} +#endif + static int -psmopen(struct cdev *dev, int flag, int fmt, struct thread *td) +psm_cdev_open(struct cdev *dev, int flag, int fmt, struct thread *td) { struct psm_softc *sc; - int command_byte; - int err; - int s; + int err = 0; /* Get device data */ sc = dev->si_drv1; @@ -1691,6 +2088,59 @@ psmopen(struct cdev *dev, int flag, int fmt, struct thread *td) device_busy(devclass_get_device(psm_devclass, sc->unit)); +#ifdef EVDEV_SUPPORT + /* Already opened by evdev */ + if (!(sc->state & (PSM_EV_OPEN_R | PSM_EV_OPEN_A))) +#endif + err = psmopen(sc); + + if (err == 0) + sc->state |= PSM_OPEN; + else + device_unbusy(devclass_get_device(psm_devclass, sc->unit)); + + return (err); +} + +static int +psm_cdev_close(struct cdev *dev, int flag, int fmt, struct thread *td) +{ + struct psm_softc *sc; + int err = 0; + + /* Get device data */ + sc = dev->si_drv1; + if ((sc == NULL) || (sc->state & PSM_VALID) == 0) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + +#ifdef EVDEV_SUPPORT + /* Still opened by evdev */ + if (!(sc->state & (PSM_EV_OPEN_R | PSM_EV_OPEN_A))) +#endif + err = psmclose(sc); + + if (err == 0) { + sc->state &= ~PSM_OPEN; + /* clean up and sigio requests */ + if (sc->async != NULL) { + funsetown(&sc->async); + sc->async = NULL; + } + device_unbusy(devclass_get_device(psm_devclass, sc->unit)); + } + + return (err); +} + +static int +psmopen(struct psm_softc *sc) +{ + int command_byte; + int err; + int s; + /* Initialize state */ sc->mode.level = sc->dflt_mode.level; sc->mode.protocol = sc->dflt_mode.protocol; @@ -1750,16 +2200,13 @@ psmopen(struct cdev *dev, int flag, int fmt, struct thread *td) err = doopen(sc, command_byte); /* done */ - if (err == 0) - sc->state |= PSM_OPEN; kbdc_lock(sc->kbdc, FALSE); return (err); } static int -psmclose(struct cdev *dev, int flag, int fmt, struct thread *td) +psmclose(struct psm_softc *sc) { - struct psm_softc *sc = dev->si_drv1; int stat[3]; int command_byte; int s; @@ -1836,16 +2283,8 @@ psmclose(struct cdev *dev, int flag, int fmt, struct thread *td) /* remove anything left in the output buffer */ empty_aux_buffer(sc->kbdc, 10); - /* clean up and sigio requests */ - if (sc->async != NULL) { - funsetown(&sc->async); - sc->async = NULL; - } - /* close is almost always successful */ - sc->state &= ~PSM_OPEN; kbdc_lock(sc->kbdc, FALSE); - device_unbusy(devclass_get_device(psm_devclass, sc->unit)); return (0); } @@ -2496,7 +2935,7 @@ psmintr(void *arg) pb = &sc->pqueue[sc->pqueue_end]; /* discard the byte if the device is not open */ - if ((sc->state & PSM_OPEN) == 0) + if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_R | PSM_EV_OPEN_A))) continue; getmicrouptime(&now); @@ -2854,7 +3293,15 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, guest_buttons |= MOUSE_BUTTON2DOWN; if (pb->ipacket[1] & 0x02) guest_buttons |= MOUSE_BUTTON3DOWN; - +#ifdef EVDEV_SUPPORT + if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { + evdev_push_rel(sc->evdev_r, REL_X, *x); + evdev_push_rel(sc->evdev_r, REL_Y, -*y); + evdev_push_mouse_btn(sc->evdev_r, + guest_buttons); + evdev_sync(sc->evdev_r); + } +#endif ms->button = touchpad_buttons | guest_buttons | sc->extended_buttons; } @@ -2965,6 +3412,24 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, int mask = 0; maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1; mask = (1 << maskedbits) - 1; +#ifdef EVDEV_SUPPORT + int i; + if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { + if (sc->synhw.capPassthrough) { + evdev_push_mouse_btn(sc->evdev_r, + extended_buttons); + evdev_sync(sc->evdev_r); + } + for (i = 0; i < maskedbits; i++) { + evdev_push_key(sc->evdev_a, + BTN_0 + i * 2, + pb->ipacket[4] & (1 << i)); + evdev_push_key(sc->evdev_a, + BTN_0 + i * 2 + 1, + pb->ipacket[5] & (1 << i)); + } + } +#endif pb->ipacket[4] &= ~(mask); pb->ipacket[5] &= ~(mask); } else if (!sc->syninfo.directional_scrolls && @@ -3016,6 +3481,31 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, if (id >= nfingers) PSM_FINGER_RESET(f[id]); +#ifdef EVDEV_SUPPORT + if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { + for (id = 0; id < PSM_FINGERS; id++) { + if (PSM_FINGER_IS_SET(f[id])) + psm_push_mt_finger(sc, id, &f[id]); + else + psm_release_mt_slot(sc->evdev_a, id); + } + evdev_push_key(sc->evdev_a, BTN_TOUCH, nfingers > 0); + evdev_push_nfingers(sc->evdev_a, nfingers); + if (nfingers > 0) + psm_push_st_finger(sc, &f[0]); + else + evdev_push_abs(sc->evdev_a, ABS_PRESSURE, 0); + evdev_push_mouse_btn(sc->evdev_a, touchpad_buttons); + if (sc->synhw.capExtended && sc->synhw.capFourButtons) { + evdev_push_key(sc->evdev_a, BTN_FORWARD, + touchpad_buttons & MOUSE_BUTTON4DOWN); + evdev_push_key(sc->evdev_a, BTN_BACK, + touchpad_buttons & MOUSE_BUTTON5DOWN); + } + evdev_sync(sc->evdev_a); + } +#endif + ms->button = touchpad_buttons; psmgestures(sc, &f[0], nfingers, ms); @@ -4015,7 +4505,12 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); - +#ifdef EVDEV_SUPPORT + evdev_push_rel(sc->evdev_r, REL_X, *x); + evdev_push_rel(sc->evdev_r, REL_Y, -*y); + evdev_push_mouse_btn(sc->evdev_r, trackpoint_button); + evdev_sync(sc->evdev_r); +#endif ms->button = touchpad_button | trackpoint_button; return (0); @@ -4042,6 +4537,31 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0); } +#ifdef EVDEV_SUPPORT + if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { + for (id = 0; id < ELANTECH_MAX_FINGERS; id++) { + if (PSM_FINGER_IS_SET(f[id])) { + psm_push_mt_finger(sc, id, &f[id]); + /* Convert touch width to surface units */ + evdev_push_abs(sc->evdev_a, ABS_MT_TOUCH_MAJOR, + f[id].w * sc->elanhw.dptracex); + } + if (sc->elanaction.mask & (1 << id) && + !(mask & (1 << id))) + psm_release_mt_slot(sc->evdev_a, id); + } + evdev_push_key(sc->evdev_a, BTN_TOUCH, nfingers > 0); + evdev_push_nfingers(sc->evdev_a, nfingers); + if (nfingers > 0) { + if (PSM_FINGER_IS_SET(f[0])) + psm_push_st_finger(sc, &f[0]); + } else + evdev_push_abs(sc->evdev_a, ABS_PRESSURE, 0); + evdev_push_mouse_btn(sc->evdev_a, touchpad_button); + evdev_sync(sc->evdev_a); + } +#endif + ms->button = touchpad_button | trackpoint_button; /* Send finger 1 position to gesture processor */ @@ -4382,6 +4902,41 @@ psmsoftintr(void *arg) break; } +#ifdef EVDEV_SUPPORT + if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE && + sc->hw.model != MOUSE_MODEL_ELANTECH && + sc->hw.model != MOUSE_MODEL_SYNAPTICS) { + evdev_push_rel(sc->evdev_r, EV_REL, x); + evdev_push_rel(sc->evdev_r, EV_REL, -y); + + switch (sc->hw.model) { + case MOUSE_MODEL_EXPLORER: + case MOUSE_MODEL_INTELLI: + case MOUSE_MODEL_NET: + case MOUSE_MODEL_NETSCROLL: + case MOUSE_MODEL_4DPLUS: + evdev_push_rel(sc->evdev_r, REL_WHEEL, -z); + break; + case MOUSE_MODEL_MOUSEMANPLUS: + case MOUSE_MODEL_4D: + switch (z) { + case 1: + case -1: + evdev_push_rel(sc->evdev_r, REL_WHEEL, -z); + break; + case 2: + case -2: + evdev_push_rel(sc->evdev_r, REL_HWHEEL, z / 2); + break; + } + break; + } + + evdev_push_mouse_btn(sc->evdev_r, ms.button); + evdev_sync(sc->evdev_r); + } +#endif + /* scale values */ if (sc->mode.accelfactor >= 1) { if (x != 0) { @@ -6494,6 +7049,9 @@ psmresume(device_t dev) } DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, 0, 0); +#ifdef EVDEV_SUPPORT +MODULE_DEPEND(psm, evdev, 1, 1, 1); +#endif #ifdef DEV_ISA diff --git a/sys/dev/bhnd/cores/chipc/chipcreg.h b/sys/dev/bhnd/cores/chipc/chipcreg.h index b94adca847b4..87de8d674837 100644 --- a/sys/dev/bhnd/cores/chipc/chipcreg.h +++ b/sys/dev/bhnd/cores/chipc/chipcreg.h @@ -280,7 +280,7 @@ enum { #define CHIPC_PLL_TYPE1 0x2 /* 48MHz base, 3 dividers */ #define CHIPC_PLL_TYPE2 0x4 /* 48MHz, 4 dividers */ #define CHIPC_PLL_TYPE3 0x6 /* 25MHz, 2 dividers */ -#define CHIPC_PLL_TYPE4 0x8 /* 48MHz, 4 dividers */ +#define CHIPC_PLL_TYPE4 0x1 /* 48MHz, 4 dividers */ #define CHIPC_PLL_TYPE5 0x3 /* 25MHz, 4 dividers */ #define CHIPC_PLL_TYPE6 0x5 /* 100/200 or 120/240 only */ #define CHIPC_PLL_TYPE7 0x7 /* 25MHz, 4 dividers */ diff --git a/sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c b/sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c index 4cd23b3e2dac..9d5052c89c39 100644 --- a/sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c +++ b/sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c @@ -374,7 +374,7 @@ bhnd_pwrctl_slowclk_freq(struct bhnd_pwrctl_softc *sc, bool max_freq) } else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) { div = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL); div = CHIPC_GET_BITS(div, CHIPC_SCC_CD); - div *= 4; + div = 4 * (div + 1); } else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) { if (max_freq) { div = 1; @@ -503,7 +503,10 @@ bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc, bhnd_clock clock) if (bhnd_get_hwrev(sc->chipc_dev) == 10) return (ENODEV); - scc = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL); + if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) + scc = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL); + else + scc = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL); switch (clock) { case BHND_CLOCK_HT: @@ -520,7 +523,10 @@ bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc, bhnd_clock clock) return (ENODEV); } - bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc); + if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) + bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc); + else + bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc); DELAY(CHIPC_PLL_DELAY); break; diff --git a/sys/dev/cxgbe/crypto/t4_crypto.c b/sys/dev/cxgbe/crypto/t4_crypto.c index 7cbb17ea7324..c599efe22eba 100644 --- a/sys/dev/cxgbe/crypto/t4_crypto.c +++ b/sys/dev/cxgbe/crypto/t4_crypto.c @@ -117,6 +117,13 @@ __FBSDID("$FreeBSD$"); #define MAX_RX_PHYS_DSGL_SGE 32 #define DSGL_SGE_MAXLEN 65535 +/* + * The adapter only supports requests with a total input or output + * length of 64k-1 or smaller. Longer requests either result in hung + * requests or incorrect results. + */ +#define MAX_REQUEST_SIZE 65535 + static MALLOC_DEFINE(M_CCR, "ccr", "Chelsio T6 crypto"); struct ccr_session_hmac { @@ -412,6 +419,12 @@ ccr_hmac(struct ccr_softc *sc, uint32_t sid, struct ccr_session *s, u_int imm_len, iopad_size; int error, sgl_nsegs, sgl_len; + crd = crp->crp_desc; + + /* Reject requests with too large of an input buffer. */ + if (crd->crd_len > MAX_REQUEST_SIZE) + return (EFBIG); + axf = s->hmac.auth_hash; /* PADs must be 128-bit aligned. */ @@ -425,7 +438,6 @@ ccr_hmac(struct ccr_softc *sc, uint32_t sid, struct ccr_session *s, hash_size_in_response = axf->hashsize; transhdr_len = HASH_TRANSHDR_SIZE(kctx_len); - crd = crp->crp_desc; if (ccr_use_imm_data(transhdr_len, crd->crd_len)) { imm_len = crd->crd_len; sgl_nsegs = 0; @@ -538,6 +550,10 @@ ccr_blkcipher(struct ccr_softc *sc, uint32_t sid, struct ccr_session *s, (crd->crd_len % AES_BLOCK_LEN) != 0) return (EINVAL); + /* Reject requests with too large of an input buffer. */ + if (crd->crd_len > MAX_REQUEST_SIZE) + return (EFBIG); + iv_loc = IV_NOP; if (crd->crd_flags & CRD_F_ENCRYPT) { op_type = CHCR_ENCRYPT_OP; @@ -785,6 +801,13 @@ ccr_authenc(struct ccr_softc *sc, uint32_t sid, struct ccr_session *s, * the hash when encrypting. For decryption it only contains * the plain text. */ + if (op_type == CHCR_ENCRYPT_OP) { + if (crde->crd_len + hash_size_in_response > MAX_REQUEST_SIZE) + return (EFBIG); + } else { + if (crde->crd_len > MAX_REQUEST_SIZE) + return (EFBIG); + } sglist_reset(sc->sg_dsgl); error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, crde->crd_skip, crde->crd_len); @@ -824,6 +847,17 @@ ccr_authenc(struct ccr_softc *sc, uint32_t sid, struct ccr_session *s, } else aad_len = 0; input_len = aad_len + crde->crd_len; + + /* + * The firmware hangs if sent a request which is a + * bit smaller than MAX_REQUEST_SIZE. In particular, the + * firmware appears to require 512 - 16 bytes of spare room + * along with the size of the hash even if the hash isn't + * included in the input buffer. + */ + if (input_len + roundup2(axf->hashsize, 16) + (512 - 16) > + MAX_REQUEST_SIZE) + return (EFBIG); if (op_type == CHCR_DECRYPT_OP) input_len += hash_size_in_response; if (ccr_use_imm_data(transhdr_len, s->blkcipher.iv_len + input_len)) { @@ -1105,6 +1139,13 @@ ccr_gcm(struct ccr_softc *sc, uint32_t sid, struct ccr_session *s, * the tag when encrypting. For decryption it only contains * the plain text. */ + if (op_type == CHCR_ENCRYPT_OP) { + if (crde->crd_len + hash_size_in_response > MAX_REQUEST_SIZE) + return (EFBIG); + } else { + if (crde->crd_len > MAX_REQUEST_SIZE) + return (EFBIG); + } sglist_reset(sc->sg_dsgl); error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, crde->crd_skip, crde->crd_len); @@ -1136,6 +1177,8 @@ ccr_gcm(struct ccr_softc *sc, uint32_t sid, struct ccr_session *s, input_len = crda->crd_len + crde->crd_len; if (op_type == CHCR_DECRYPT_OP) input_len += hash_size_in_response; + if (input_len > MAX_REQUEST_SIZE) + return (EFBIG); if (ccr_use_imm_data(transhdr_len, iv_len + input_len)) { imm_len = input_len; sgl_nsegs = 0; diff --git a/sys/dev/etherswitch/rtl8366/rtl8366rb.c b/sys/dev/etherswitch/rtl8366/rtl8366rb.c index 6e990d979969..8ad3753c8caa 100644 --- a/sys/dev/etherswitch/rtl8366/rtl8366rb.c +++ b/sys/dev/etherswitch/rtl8366/rtl8366rb.c @@ -54,10 +54,12 @@ #include <dev/iicbus/iicbus.h> #include <dev/mii/mii.h> #include <dev/mii/miivar.h> +#include <dev/mdio/mdio.h> #include <dev/etherswitch/etherswitch.h> #include <dev/etherswitch/rtl8366/rtl8366rbvar.h> +#include "mdio_if.h" #include "iicbus_if.h" #include "miibus_if.h" #include "etherswitch_if.h" @@ -74,7 +76,9 @@ struct rtl8366rb_softc { struct ifnet *ifp[RTL8366_NUM_PHYS]; struct callout callout_tick; etherswitch_info_t info; - int chip_type; /* 0 = RTL8366RB, 1 = RTL8366SR */ + int chip_type; + int phy4cpu; + int numphys; }; #define RTL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) @@ -145,7 +149,7 @@ rtl8366rb_probe(device_t dev) bzero(sc, sizeof(*sc)); if (smi_probe(dev) != 0) return (ENXIO); - if(sc->chip_type == 0) + if (sc->chip_type == RTL8366RB) device_set_desc(dev, "RTL8366RB Ethernet Switch Controller"); else device_set_desc(dev, "RTL8366SR Ethernet Switch Controller"); @@ -215,17 +219,23 @@ rtl8366rb_attach(device_t dev) smi_read(dev, RTL8366_CVCR, &rev, RTL_WAITOK); device_printf(dev, "rev. %d\n", rev & 0x000f); - sc->info.es_nports = RTL8366_NUM_PORTS; + sc->phy4cpu = 0; + (void) resource_int_value(device_get_name(dev), device_get_unit(dev), + "phy4cpu", &sc->phy4cpu); + + sc->numphys = sc->phy4cpu ? RTL8366_NUM_PHYS - 1 : RTL8366_NUM_PHYS; + + sc->info.es_nports = sc->numphys + 1; sc->info.es_nvlangroups = RTL8366_NUM_VLANS; sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q; - if(sc->chip_type == 0) + if (sc->chip_type == RTL8366RB) sprintf(sc->info.es_name, "Realtek RTL8366RB"); else sprintf(sc->info.es_name, "Realtek RTL8366SR"); /* attach miibus and phys */ /* PHYs need an interface, so we generate a dummy one */ - for (i = 0; i < RTL8366_NUM_PHYS; i++) { + for (i = 0; i < sc->numphys; i++) { sc->ifp[i] = if_alloc(IFT_ETHER); sc->ifp[i]->if_softc = sc; sc->ifp[i]->if_flags |= IFF_UP | IFF_BROADCAST | IFF_DRV_RUNNING @@ -263,7 +273,7 @@ rtl8366rb_detach(device_t dev) sc = device_get_softc(dev); - for (i=0; i < RTL8366_NUM_PHYS; i++) { + for (i=0; i < sc->numphys; i++) { if (sc->miibus[i]) device_delete_child(dev, sc->miibus[i]); if (sc->ifp[i] != NULL) @@ -319,7 +329,7 @@ rtl833rb_miipollstat(struct rtl8366rb_softc *sc) uint16_t value; int portstatus; - for (i = 0; i < RTL8366_NUM_PHYS; i++) { + for (i = 0; i < sc->numphys; i++) { mii = device_get_softc(sc->miibus[i]); if ((i % 2) == 0) { if (smi_read(sc->dev, RTL8366_PLSR_BASE + i/2, &value, RTL_NOWAIT) != 0) { @@ -365,7 +375,7 @@ smi_probe(device_t dev) iicbus = device_get_parent(dev); iicha = device_get_parent(iicbus); - for(i = 0; i < 2; ++i) { + for (i = 0; i < 2; ++i) { iicbus_reset(iicbus, IIC_FASTEST, RTL8366_IIC_ADDR, NULL); for (j=3; j--; ) { IICBUS_STOP(iicha); @@ -380,7 +390,7 @@ smi_probe(device_t dev) err = iicbus_start(iicbus, RTL8366_IIC_ADDR | RTL_IICBUS_READ, RTL_IICBUS_TIMEOUT); if (err != 0) goto out; - if(i == 0) { + if (i == 0) { bytes[0] = RTL8366RB_CIR & 0xff; bytes[1] = (RTL8366RB_CIR >> 8) & 0xff; } else { @@ -396,22 +406,22 @@ smi_probe(device_t dev) chipid = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff); if (i == 0 && chipid == RTL8366RB_CIR_ID8366RB) { DPRINTF(dev, "chip id 0x%04x\n", chipid); - sc->chip_type = 0; + sc->chip_type = RTL8366RB; err = 0; break; } if (i == 1 && chipid == RTL8366SR_CIR_ID8366SR) { DPRINTF(dev, "chip id 0x%04x\n", chipid); - sc->chip_type = 1; + sc->chip_type = RTL8366SR; err = 0; break; } - if(i == 0) { + if (i == 0) { iicbus_stop(iicbus); iicbus_release_bus(iicbus, dev); } } - if(i == 2) + if (i == 2) err = ENXIO; out: iicbus_stop(iicbus); @@ -472,7 +482,7 @@ smi_select(device_t dev, int op, int sleep) RTL_SMI_ACQUIRED_ASSERT((struct rtl8366rb_softc *)device_get_softc(dev)); - if(sc->chip_type == 1) { // RTL8366SR work around + if (sc->chip_type == RTL8366SR) { // RTL8366SR work around // this is same work around at probe for (int i=3; i--; ) IICBUS_STOP(device_get_parent(device_get_parent(dev))); @@ -648,13 +658,18 @@ rtl_getport(device_t dev, etherswitch_port_t *p) ifmr = &p->es_ifmr; - if (p->es_port < 0 || p->es_port >= RTL8366_NUM_PORTS) + if (p->es_port < 0 || p->es_port >= (sc->numphys + 1)) return (ENXIO); - vlangroup = RTL8366_PVCR_GET(p->es_port, - rtl_readreg(dev, RTL8366_PVCR_REG(p->es_port))); + if (sc->phy4cpu && p->es_port == sc->numphys) { + vlangroup = RTL8366_PVCR_GET(p->es_port + 1, + rtl_readreg(dev, RTL8366_PVCR_REG(p->es_port + 1))); + } else { + vlangroup = RTL8366_PVCR_GET(p->es_port, + rtl_readreg(dev, RTL8366_PVCR_REG(p->es_port))); + } p->es_pvid = sc->vid[vlangroup] & ETHERSWITCH_VID_MASK; - if (p->es_port < RTL8366_NUM_PHYS) { + if (p->es_port < sc->numphys) { mii = device_get_softc(sc->miibus[p->es_port]); ifm = &mii->mii_media; err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCGIFMEDIA); @@ -687,10 +702,11 @@ rtl_setport(device_t dev, etherswitch_port_t *p) int i, err, vlangroup; struct ifmedia *ifm; struct mii_data *mii; + int port; sc = device_get_softc(dev); - if (p->es_port < 0 || p->es_port >= RTL8366_NUM_PORTS) + if (p->es_port < 0 || p->es_port >= (sc->numphys + 1)) return (ENXIO); vlangroup = -1; for (i = 0; i < RTL8366_NUM_VLANS; i++) { @@ -701,12 +717,18 @@ rtl_setport(device_t dev, etherswitch_port_t *p) } if (vlangroup == -1) return (ENXIO); - err = smi_rmw(dev, RTL8366_PVCR_REG(p->es_port), - RTL8366_PVCR_VAL(p->es_port, RTL8366_PVCR_PORT_MASK), - RTL8366_PVCR_VAL(p->es_port, vlangroup), RTL_WAITOK); + if (sc->phy4cpu && p->es_port == sc->numphys) { + port = p->es_port + 1; + } else { + port = p->es_port; + } + err = smi_rmw(dev, RTL8366_PVCR_REG(port), + RTL8366_PVCR_VAL(port, RTL8366_PVCR_PORT_MASK), + RTL8366_PVCR_VAL(port, vlangroup), RTL_WAITOK); if (err) return (err); - if (p->es_port == RTL8366_CPU_PORT) + /* CPU Port */ + if (p->es_port == sc->numphys) return (0); mii = device_get_softc(sc->miibus[p->es_port]); ifm = &mii->mii_media; @@ -720,6 +742,7 @@ rtl_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) struct rtl8366rb_softc *sc; uint16_t vmcr[3]; int i; + int member, untagged; sc = device_get_softc(dev); @@ -727,8 +750,15 @@ rtl_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) vmcr[i] = rtl_readreg(dev, RTL8366_VMCR(i, vg->es_vlangroup)); vg->es_vid = sc->vid[vg->es_vlangroup]; - vg->es_member_ports = RTL8366_VMCR_MEMBER(vmcr); - vg->es_untagged_ports = RTL8366_VMCR_UNTAG(vmcr); + member = RTL8366_VMCR_MEMBER(vmcr); + untagged = RTL8366_VMCR_UNTAG(vmcr); + if (sc->phy4cpu) { + vg->es_member_ports = ((member & 0x20) >> 1) | (member & 0x0f); + vg->es_untagged_ports = ((untagged & 0x20) >> 1) | (untagged & 0x0f); + } else { + vg->es_member_ports = member; + vg->es_untagged_ports = untagged; + } vg->es_fid = RTL8366_VMCR_FID(vmcr); return (0); } @@ -738,6 +768,7 @@ rtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) { struct rtl8366rb_softc *sc; int g; + int member, untagged; sc = device_get_softc(dev); @@ -750,16 +781,26 @@ rtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) sc->vid[g] |= ETHERSWITCH_VID_VALID; rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_DOT1Q_REG, g), (vg->es_vid << RTL8366_VMCR_DOT1Q_VID_SHIFT) & RTL8366_VMCR_DOT1Q_VID_MASK); - if(sc->chip_type == 0) { + if (sc->phy4cpu) { + /* add space at phy4 */ + member = (vg->es_member_ports & 0x0f) | + ((vg->es_member_ports & 0x10) << 1); + untagged = (vg->es_untagged_ports & 0x0f) | + ((vg->es_untagged_ports & 0x10) << 1); + } else { + member = vg->es_member_ports; + untagged = vg->es_untagged_ports; + } + if (sc->chip_type == RTL8366RB) { rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, g), - ((vg->es_member_ports << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) | - ((vg->es_untagged_ports << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK)); + ((member << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) | + ((untagged << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK)); rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_FID_REG, g), vg->es_fid); } else { rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, g), - ((vg->es_member_ports << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) | - ((vg->es_untagged_ports << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK) | + ((member << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) | + ((untagged << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK) | ((vg->es_fid << RTL8366_VMCR_FID_FID_SHIFT) & RTL8366_VMCR_FID_FID_MASK)); } return (0); @@ -886,6 +927,10 @@ static device_method_t rtl8366rb_methods[] = { DEVMETHOD(miibus_readreg, rtl_readphy), DEVMETHOD(miibus_writereg, rtl_writephy), + /* MDIO interface */ + DEVMETHOD(mdio_readreg, rtl_readphy), + DEVMETHOD(mdio_writereg, rtl_writephy), + /* etherswitch interface */ DEVMETHOD(etherswitch_getconf, rtl_getconf), DEVMETHOD(etherswitch_getinfo, rtl_getinfo), @@ -907,6 +952,7 @@ static devclass_t rtl8366rb_devclass; DRIVER_MODULE(rtl8366rb, iicbus, rtl8366rb_driver, rtl8366rb_devclass, 0, 0); DRIVER_MODULE(miibus, rtl8366rb, miibus_driver, miibus_devclass, 0, 0); +DRIVER_MODULE(mdio, rtl8366rb, mdio_driver, mdio_devclass, 0, 0); DRIVER_MODULE(etherswitch, rtl8366rb, etherswitch_driver, etherswitch_devclass, 0, 0); MODULE_VERSION(rtl8366rb, 1); MODULE_DEPEND(rtl8366rb, iicbus, 1, 1, 1); /* XXX which versions? */ diff --git a/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h b/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h index 66ca0ad245ee..661f1132ac07 100644 --- a/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h +++ b/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h @@ -30,6 +30,9 @@ #ifndef _DEV_ETHERSWITCH_RTL8366RBVAR_H_ #define _DEV_ETHERSWITCH_RTL8366RBVAR_H_ +#define RTL8366RB 0 +#define RTL8366SR 1 + #define RTL8366_IIC_ADDR 0xa8 #define RTL_IICBUS_TIMEOUT 100 /* us */ #define RTL_IICBUS_READ 1 @@ -173,9 +176,7 @@ (0x8000 | (1 << (((phy) & 0x1f) + 9)) | (((page) & (sc->chip_type == 0 ? 0xf : 0x7)) << 5) | ((reg) & 0x1f)) /* general characteristics of the chip */ -#define RTL8366_CPU_PORT 5 -#define RTL8366_NUM_PORTS 6 -#define RTL8366_NUM_PHYS (RTL8366_NUM_PORTS-1) +#define RTL8366_NUM_PHYS 5 #define RTL8366_NUM_VLANS 16 #define RTL8366_NUM_PHY_REG 32 diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index 5b2b524dfbd8..424d8a94792a 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -91,9 +91,9 @@ static struct ieee80211vap *rtwn_vap_create(struct ieee80211com *, static void rtwn_vap_delete(struct ieee80211vap *); static int rtwn_read_chipid(struct rtwn_softc *); static int rtwn_ioctl_reset(struct ieee80211vap *, u_long); -#ifndef RTWN_WITHOUT_UCODE static void rtwn_set_media_status(struct rtwn_softc *, union sec_param *); +#ifndef RTWN_WITHOUT_UCODE static int rtwn_tx_fwpkt_check(struct rtwn_softc *, struct ieee80211vap *); static int rtwn_construct_nulldata(struct rtwn_softc *, @@ -703,13 +703,13 @@ rtwn_ioctl_reset(struct ieee80211vap *vap, u_long cmd) return (error); } -#ifndef RTWN_WITHOUT_UCODE static void rtwn_set_media_status(struct rtwn_softc *sc, union sec_param *data) { sc->sc_set_media_status(sc, data->macid); } +#ifndef RTWN_WITHOUT_UCODE static int rtwn_tx_fwpkt_check(struct rtwn_softc *sc, struct ieee80211vap *vap) { @@ -1743,11 +1743,9 @@ rtwn_newassoc(struct ieee80211_node *ni, int isnew __unused) return; } -#ifndef RTWN_WITHOUT_UCODE /* Notify firmware. */ id |= RTWN_MACID_VALID; rtwn_cmd_sleepable(sc, &id, sizeof(id), rtwn_set_media_status); -#endif } static void @@ -1759,10 +1757,8 @@ rtwn_node_free(struct ieee80211_node *ni) RTWN_NT_LOCK(sc); if (un->id != RTWN_MACID_UNDEFINED) { sc->node_list[un->id] = NULL; -#ifndef RTWN_WITHOUT_UCODE rtwn_cmd_sleepable(sc, &un->id, sizeof(un->id), rtwn_set_media_status); -#endif } RTWN_NT_UNLOCK(sc); diff --git a/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c b/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c index 9f5edb00ec2d..21819e8be867 100644 --- a/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c +++ b/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c @@ -141,11 +141,13 @@ r92eu_attach(struct rtwn_usb_softc *uc) sc->sc_vap_preattach = rtwn_nop_softc_vap; sc->sc_postattach = rtwn_nop_softc; sc->sc_detach_private = r92e_detach_private; - sc->sc_set_media_status = r92e_set_media_status; #ifndef RTWN_WITHOUT_UCODE + sc->sc_set_media_status = r92e_set_media_status; sc->sc_set_rsvd_page = r88e_set_rsvd_page; sc->sc_set_pwrmode = r92e_set_pwrmode; sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */ +#else + sc->sc_set_media_status = rtwn_nop_softc_int; #endif sc->sc_beacon_init = r12a_beacon_init; sc->sc_beacon_enable = r92c_beacon_enable; diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c index 76a0f8690c38..e25e6b26ca94 100644 --- a/sys/dev/uart/uart_bus_pci.c +++ b/sys/dev/uart/uart_bus_pci.c @@ -127,6 +127,7 @@ static const struct pci_id pci_ns8250_ids[] = { 24 * DEFAULT_RCLK, 2 }, { 0x8086, 0x0f0c, 0xffff, 0, "Intel ValleyView LPIO1 HSUART#2", 0x10, 24 * DEFAULT_RCLK, 2 }, +{ 0x8086, 0x108f, 0xffff, 0, "Intel AMT - SOL", 0x10 }, { 0x8086, 0x1c3d, 0xffff, 0, "Intel AMT - KT Controller", 0x10 }, { 0x8086, 0x1d3d, 0xffff, 0, "Intel C600/X79 Series Chipset KT Controller", 0x10 }, { 0x8086, 0x1e3d, 0xffff, 0, "Intel Panther Point KT Controller", 0x10 }, diff --git a/sys/fs/ext2fs/ext2_acl.c b/sys/fs/ext2fs/ext2_acl.c new file mode 100644 index 000000000000..7ac1707cb543 --- /dev/null +++ b/sys/fs/ext2fs/ext2_acl.c @@ -0,0 +1,521 @@ +/*- + * Copyright (c) 2017, Fedor Uporov + * 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 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. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/vnode.h> +#include <sys/bio.h> +#include <sys/buf.h> +#include <sys/endian.h> +#include <sys/conf.h> +#include <sys/mount.h> +#include <sys/extattr.h> + +#include <fs/ext2fs/fs.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2_acl.h> +#include <fs/ext2fs/ext2_extattr.h> +#include <fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/ext2_dinode.h> +#include <fs/ext2fs/ext2_mount.h> + +void +ext2_sync_acl_from_inode(struct inode *ip, struct acl *acl) +{ + struct acl_entry *acl_mask, *acl_group_obj; + int i; + + /* + * Update ACL_USER_OBJ, ACL_OTHER, but simply identify ACL_MASK + * and ACL_GROUP_OBJ for use after we know whether ACL_MASK is + * present. + */ + acl_mask = NULL; + acl_group_obj = NULL; + for (i = 0; i < acl->acl_cnt; i++) { + switch (acl->acl_entry[i].ae_tag) { + case ACL_USER_OBJ: + acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm( + ACL_USER_OBJ, ip->i_mode); + acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; + break; + + case ACL_GROUP_OBJ: + acl_group_obj = &acl->acl_entry[i]; + acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; + break; + + case ACL_OTHER: + acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm( + ACL_OTHER, ip->i_mode); + acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; + break; + + case ACL_MASK: + acl_mask = &acl->acl_entry[i]; + acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; + break; + + case ACL_USER: + case ACL_GROUP: + break; + + default: + panic("ext2_sync_acl_from_inode(): bad ae_tag"); + } + } + + if (acl_group_obj == NULL) + panic("ext2_sync_acl_from_inode(): no ACL_GROUP_OBJ"); + + if (acl_mask == NULL) { + /* + * There is no ACL_MASK, so update ACL_GROUP_OBJ. + */ + acl_group_obj->ae_perm = acl_posix1e_mode_to_perm( + ACL_GROUP_OBJ, ip->i_mode); + } else { + /* + * Update the ACL_MASK entry instead of ACL_GROUP_OBJ. + */ + acl_mask->ae_perm = acl_posix1e_mode_to_perm(ACL_GROUP_OBJ, + ip->i_mode); + } +} + +static void +ext2_sync_inode_from_acl(struct acl *acl, struct inode *ip) +{ + + ip->i_mode &= ACL_PRESERVE_MASK; + ip->i_mode |= acl_posix1e_acl_to_mode(acl); +} + +/* + * Convert from filesystem to in-memory representation. + */ +static int +ext4_acl_from_disk(char *value, size_t size, struct acl *acl) +{ + const char *end = value + size; + int n, count, s; + + if (((struct ext2_acl_header *)value)->a_version != EXT4_ACL_VERSION) + return (EINVAL); + + if (!value || size < sizeof(struct ext2_acl_header)) + return (EINVAL); + + s = size - sizeof(struct ext2_acl_header); + s -= 4 * sizeof(struct ext2_acl_entry_short); + if (s < 0) + if ((size - sizeof(struct ext2_acl_header)) % + sizeof(struct ext2_acl_entry_short)) + count = -1; + else + count = (size - sizeof(struct ext2_acl_header)) / + sizeof(struct ext2_acl_entry_short); + else + if (s % sizeof(struct ext2_acl_entry)) + count = -1; + else + count = s / sizeof(struct ext2_acl_entry) + 4; + + if (count <= 0 || count > acl->acl_maxcnt) + return (EINVAL); + + value = value + sizeof(struct ext2_acl_header); + + for (n = 0; n < count; n++) { + struct ext2_acl_entry *entry = (struct ext2_acl_entry *)value; + if ((char *)value + sizeof(struct ext2_acl_entry_short) > end) + return (EINVAL); + + acl->acl_entry[n].ae_tag = entry->ae_tag; + acl->acl_entry[n].ae_perm = entry->ae_perm; + + switch (acl->acl_entry[n].ae_tag) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + value = (char *)value + sizeof(struct ext2_acl_entry_short); + break; + + case ACL_USER: + value = (char *)value + sizeof(struct ext2_acl_entry); + if ((char *)value > end) + return (EINVAL); + + acl->acl_entry[n].ae_id = entry->ae_id; + break; + + case ACL_GROUP: + value = (char *)value + sizeof(struct ext2_acl_entry); + if ((char *)value > end) + return (EINVAL); + + acl->acl_entry[n].ae_id = entry->ae_id; + break; + + default: + return (EINVAL); + } + } + + if (value != end) + return (EINVAL); + + acl->acl_cnt = count; + + return (0); +} + +static int +ext2_getacl_posix1e(struct vop_getacl_args *ap) +{ + int attrnamespace; + const char *attrname; + char *value; + int len; + int error; + + switch (ap->a_type) { + case ACL_TYPE_DEFAULT: + attrnamespace = POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE; + attrname = POSIX1E_ACL_DEFAULT_EXTATTR_NAME; + break; + case ACL_TYPE_ACCESS: + attrnamespace = POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE; + attrname = POSIX1E_ACL_ACCESS_EXTATTR_NAME; + break; + default: + return (EINVAL); + } + + len = sizeof(*ap->a_aclp) + sizeof(struct ext2_acl_header); + value = malloc(len, M_ACL, M_WAITOK); + if (!value) + return (ENOMEM); + + error = vn_extattr_get(ap->a_vp, IO_NODELOCKED, attrnamespace, attrname, + &len, value, ap->a_td); + switch (error) { + case ENOATTR: + switch (ap->a_type) { + case ACL_TYPE_ACCESS: + ap->a_aclp->acl_cnt = 3; + ap->a_aclp->acl_entry[0].ae_tag = ACL_USER_OBJ; + ap->a_aclp->acl_entry[0].ae_id = ACL_UNDEFINED_ID; + ap->a_aclp->acl_entry[0].ae_perm = ACL_PERM_NONE; + ap->a_aclp->acl_entry[1].ae_tag = ACL_GROUP_OBJ; + ap->a_aclp->acl_entry[1].ae_id = ACL_UNDEFINED_ID; + ap->a_aclp->acl_entry[1].ae_perm = ACL_PERM_NONE; + ap->a_aclp->acl_entry[2].ae_tag = ACL_OTHER; + ap->a_aclp->acl_entry[2].ae_id = ACL_UNDEFINED_ID; + ap->a_aclp->acl_entry[2].ae_perm = ACL_PERM_NONE; + break; + + case ACL_TYPE_DEFAULT: + ap->a_aclp->acl_cnt = 0; + break; + } + case 0: + if (!error) { + error = ext4_acl_from_disk(value, len, ap->a_aclp); + if (error) + goto out; + } + + if (error == ENOATTR) + error = 0; + + if (ap->a_type == ACL_TYPE_ACCESS) + ext2_sync_acl_from_inode(VTOI(ap->a_vp), ap->a_aclp); + default: + break; + } + +out: + free(value, M_TEMP); + return (error); +} + +int +ext2_getacl(struct vop_getacl_args *ap) +{ + + if (((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) || + ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 1)) + return (EOPNOTSUPP); + + if (ap->a_type == ACL_TYPE_NFS4) + return (ENOTSUP); + + return (ext2_getacl_posix1e(ap)); +} + +/* + * Convert from in-memory to filesystem representation. + */ +static int +ext4_acl_to_disk(const struct acl *acl, size_t *size, char *value) +{ + struct ext2_acl_header *ext_acl; + int disk_size; + char *e; + size_t n; + + if (acl->acl_cnt <= 4) + disk_size = sizeof(struct ext2_acl_header) + + acl->acl_cnt * sizeof(struct ext2_acl_entry_short); + else + disk_size = sizeof(struct ext2_acl_header) + + 4 * sizeof(struct ext2_acl_entry_short) + + (acl->acl_cnt - 4) * sizeof(struct ext2_acl_entry); + + if (disk_size > *size) + return (EINVAL); + + *size = disk_size; + ext_acl = (struct ext2_acl_header *)value; + + ext_acl->a_version = EXT4_ACL_VERSION; + e = (char *)ext_acl + sizeof(struct ext2_acl_header); + for (n = 0; n < acl->acl_cnt; n++) { + const struct acl_entry *acl_e = &acl->acl_entry[n]; + struct ext2_acl_entry *entry = (struct ext2_acl_entry *)e; + entry->ae_tag = acl_e->ae_tag; + entry->ae_perm = acl_e->ae_perm; + switch (acl_e->ae_tag) { + case ACL_USER: + entry->ae_id = acl_e->ae_id; + e += sizeof(struct ext2_acl_entry); + break; + + case ACL_GROUP: + entry->ae_id = acl_e->ae_id; + e += sizeof(struct ext2_acl_entry); + break; + + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + e += sizeof(struct ext2_acl_entry_short); + break; + + default: + return (EINVAL); + } + } + + return (0); +} + +static int +ext2_setacl_posix1e(struct vop_setacl_args *ap) +{ + struct inode *ip = VTOI(ap->a_vp); + char *value; + size_t len; + int error; + + if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) + return (EINVAL); + + /* + * If this is a set operation rather than a delete operation, + * invoke VOP_ACLCHECK() on the passed ACL to determine if it is + * valid for the target. This will include a check on ap->a_type. + */ + if (ap->a_aclp != NULL) { + /* + * Set operation. + */ + error = VOP_ACLCHECK(ap->a_vp, ap->a_type, ap->a_aclp, + ap->a_cred, ap->a_td); + if (error) + return (error); + } else { + /* + * Delete operation. + * POSIX.1e allows only deletion of the default ACL on a + * directory (ACL_TYPE_DEFAULT). + */ + if (ap->a_type != ACL_TYPE_DEFAULT) + return (EINVAL); + if (ap->a_vp->v_type != VDIR) + return (ENOTDIR); + } + + if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + + /* + * Authorize the ACL operation. + */ + if (ip->i_flags & (IMMUTABLE | APPEND)) + return (EPERM); + + /* + * Must hold VADMIN (be file owner) or have appropriate privilege. + */ + if ((error = VOP_ACCESS(ap->a_vp, VADMIN, ap->a_cred, ap->a_td))) + return (error); + + switch (ap->a_type) { + case ACL_TYPE_ACCESS: + len = sizeof(*ap->a_aclp) + sizeof(struct ext2_acl_header); + value = malloc(len, M_ACL, M_WAITOK | M_ZERO); + error = ext4_acl_to_disk(ap->a_aclp, &len, value); + if (error == 0) + error = vn_extattr_set(ap->a_vp, IO_NODELOCKED, + POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE, + POSIX1E_ACL_ACCESS_EXTATTR_NAME, len, + value, ap->a_td); + + free(value, M_ACL); + break; + + case ACL_TYPE_DEFAULT: + if (ap->a_aclp == NULL) { + error = vn_extattr_rm(ap->a_vp, IO_NODELOCKED, + POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE, + POSIX1E_ACL_DEFAULT_EXTATTR_NAME, ap->a_td); + + /* + * Attempting to delete a non-present default ACL + * will return success for portability purposes. + * (TRIX) + * + * XXX: Note that since we can't distinguish + * "that EA is not supported" from "that EA is not + * defined", the success case here overlaps the + * the ENOATTR->EOPNOTSUPP case below. + */ + if (error == ENOATTR) + error = 0; + } else { + len = sizeof(*ap->a_aclp) + sizeof(struct ext2_acl_header); + value = malloc(len, M_ACL, M_WAITOK | M_ZERO); + error = ext4_acl_to_disk(ap->a_aclp, &len, value); + if (error == 0) + error = vn_extattr_set(ap->a_vp, IO_NODELOCKED, + POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE, + POSIX1E_ACL_DEFAULT_EXTATTR_NAME, len, + value, ap->a_td); + + free(value, M_ACL); + } + break; + + default: + error = EINVAL; + } + + /* + * Map lack of attribute definition in UFS_EXTATTR into lack of + * support for ACLs on the filesystem. + */ + if (error == ENOATTR) + return (EOPNOTSUPP); + + if (error != 0) + return (error); + + if (ap->a_type == ACL_TYPE_ACCESS) { + /* + * Now that the EA is successfully updated, update the + * inode and mark it as changed. + */ + ext2_sync_inode_from_acl(ap->a_aclp, ip); + ip->i_flag |= IN_CHANGE; + error = ext2_update(ip->i_vnode, 1); + } + + VN_KNOTE_UNLOCKED(ap->a_vp, NOTE_ATTRIB); + + return (error); +} + +int +ext2_setacl(struct vop_setacl_args *ap) +{ + if (((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) || + ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 1)) + return (EOPNOTSUPP); + + if (ap->a_type == ACL_TYPE_NFS4) + return (ENOTSUP); + + return (ext2_setacl_posix1e(ap)); +} + +/* + * Check the validity of an ACL for a file. + */ +int +ext2_aclcheck(struct vop_aclcheck_args *ap) +{ + + if (((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) || + ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 1)) + return (EOPNOTSUPP); + + if (ap->a_type == ACL_TYPE_NFS4) + return (ENOTSUP); + + if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) + return (EINVAL); + + /* + * Verify we understand this type of ACL, and that it applies + * to this kind of object. + * Rely on the acl_posix1e_check() routine to verify the contents. + */ + switch (ap->a_type) { + case ACL_TYPE_ACCESS: + break; + + case ACL_TYPE_DEFAULT: + if (ap->a_vp->v_type != VDIR) + return (EINVAL); + break; + + default: + return (EINVAL); + } + + return (acl_posix1e_check(ap->a_aclp)); +} diff --git a/sys/fs/ext2fs/ext2_acl.h b/sys/fs/ext2fs/ext2_acl.h new file mode 100644 index 000000000000..abcb97d8517a --- /dev/null +++ b/sys/fs/ext2fs/ext2_acl.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2017, Fedor Uporov + * 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 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. + * + * $FreeBSD$ + */ + +#ifndef _FS_EXT2FS_EXT2_ACL_H_ +#define _FS_EXT2FS_EXT2_ACL_H_ + +#define EXT4_ACL_VERSION 0x0001 + +struct ext2_acl_entry { + int16_t ae_tag; + int16_t ae_perm; + int32_t ae_id; +}; + +struct ext2_acl_entry_short { + int16_t ae_tag; + int16_t ae_perm; +}; + +struct ext2_acl_header { + int32_t a_version; +}; + +void ext2_sync_acl_from_inode(struct inode *ip, struct acl *acl); + +int ext2_getacl(struct vop_getacl_args *); +int ext2_setacl(struct vop_setacl_args *); +int ext2_aclcheck(struct vop_aclcheck_args *); + +#endif /* !_FS_EXT2FS_EXT2_ACL_H_ */ diff --git a/sys/fs/ext2fs/ext2_extattr.c b/sys/fs/ext2fs/ext2_extattr.c index 28ba8f9ad1a9..9c821949b550 100644 --- a/sys/fs/ext2fs/ext2_extattr.c +++ b/sys/fs/ext2fs/ext2_extattr.c @@ -46,35 +46,92 @@ #include <fs/ext2fs/ext2_extattr.h> #include <fs/ext2fs/ext2_extern.h> - static int -ext2_extattr_index_to_bsd(int index) +ext2_extattr_attrnamespace_to_bsd(int attrnamespace) { - switch (index) { - case EXT4_XATTR_INDEX_SYSTEM: - return (EXTATTR_NAMESPACE_SYSTEM); - case EXT4_XATTR_INDEX_USER: - return (EXTATTR_NAMESPACE_USER); + switch (attrnamespace) { + case EXT4_XATTR_INDEX_SYSTEM: + return (EXTATTR_NAMESPACE_SYSTEM); + + case EXT4_XATTR_INDEX_USER: + return (EXTATTR_NAMESPACE_USER); + + case EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT: + return (POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE); + + case EXT4_XATTR_INDEX_POSIX_ACL_ACCESS: + return (POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE); } return (EXTATTR_NAMESPACE_EMPTY); } +static const char * +ext2_extattr_name_to_bsd(int attrnamespace, const char *name, int* name_len) +{ + + if (attrnamespace == EXT4_XATTR_INDEX_SYSTEM) + return (name); + else if (attrnamespace == EXT4_XATTR_INDEX_USER) + return (name); + else if (attrnamespace == EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT) { + *name_len = strlen(POSIX1E_ACL_DEFAULT_EXTATTR_NAME); + return (POSIX1E_ACL_DEFAULT_EXTATTR_NAME); + } else if (attrnamespace == EXT4_XATTR_INDEX_POSIX_ACL_ACCESS) { + *name_len = strlen(POSIX1E_ACL_ACCESS_EXTATTR_NAME); + return (POSIX1E_ACL_ACCESS_EXTATTR_NAME); + } + + /* + * XXX: Not all linux namespaces are mapped to bsd for now, + * return NULL, which will be converted to ENOTSUP on upper layer. + */ +#ifdef EXT2FS_DEBUG + printf("can not convert ext2fs name to bsd: namespace=%d\n", attrnamespace); +#endif /* DEBUG */ + + return (NULL); +} + static int -ext2_extattr_index_to_linux(int index) +ext2_extattr_attrnamespace_to_linux(int attrnamespace, const char *name) { - switch (index) { - case EXTATTR_NAMESPACE_SYSTEM: - return (EXT4_XATTR_INDEX_SYSTEM); - case EXTATTR_NAMESPACE_USER: - return (EXT4_XATTR_INDEX_USER); + if (attrnamespace == POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE && + !strcmp(name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) + return (EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT); + + if (attrnamespace == POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE && + !strcmp(name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) + return (EXT4_XATTR_INDEX_POSIX_ACL_ACCESS); + + switch (attrnamespace) { + case EXTATTR_NAMESPACE_SYSTEM: + return (EXT4_XATTR_INDEX_SYSTEM); + + case EXTATTR_NAMESPACE_USER: + return (EXT4_XATTR_INDEX_USER); } + /* + * In this case namespace conversion should be unique, + * so this point is unreachable. + */ return (-1); } +static const char * +ext2_extattr_name_to_linux(int attrnamespace, const char *name) +{ + + if (attrnamespace == POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE || + attrnamespace == POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE) + return (""); + else + return (name); +} + int ext2_extattr_valid_attrname(int attrnamespace, const char *attrname) { @@ -114,6 +171,8 @@ ext2_extattr_inode_list(struct inode *ip, int attrnamespace, struct buf *bp; struct ext2fs_extattr_dinode_header *header; struct ext2fs_extattr_entry *entry; + const char *attr_name; + int name_len; int error; fs = ip->i_e2fs; @@ -147,17 +206,26 @@ ext2_extattr_inode_list(struct inode *ip, int attrnamespace, for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry); entry = EXT2_EXTATTR_NEXT(entry)) { - if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace) + if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) != + attrnamespace) continue; + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + if (uio == NULL) - *size += entry->e_name_len + 1; + *size += name_len + 1; else { - char *attr_name = malloc(entry->e_name_len + 1, M_TEMP, M_WAITOK); - attr_name[0] = entry->e_name_len; - memcpy(&attr_name[1], entry->e_name, entry->e_name_len); - error = uiomove(attr_name, entry->e_name_len + 1, uio); - free(attr_name, M_TEMP); + char *name = malloc(name_len + 1, M_TEMP, M_WAITOK); + name[0] = name_len; + memcpy(&name[1], attr_name, name_len); + error = uiomove(name, name_len + 1, uio); + free(name, M_TEMP); if (error) break; } @@ -176,6 +244,8 @@ ext2_extattr_block_list(struct inode *ip, int attrnamespace, struct buf *bp; struct ext2fs_extattr_header *header; struct ext2fs_extattr_entry *entry; + const char *attr_name; + int name_len; int error; fs = ip->i_e2fs; @@ -202,17 +272,26 @@ ext2_extattr_block_list(struct inode *ip, int attrnamespace, for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry); entry = EXT2_EXTATTR_NEXT(entry)) { - if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace) + if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) != + attrnamespace) continue; + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + if (uio == NULL) - *size += entry->e_name_len + 1; + *size += name_len + 1; else { - char *attr_name = malloc(entry->e_name_len + 1, M_TEMP, M_WAITOK); - attr_name[0] = entry->e_name_len; - memcpy(&attr_name[1], entry->e_name, entry->e_name_len); - error = uiomove(attr_name, entry->e_name_len + 1, uio); - free(attr_name, M_TEMP); + char *name = malloc(name_len + 1, M_TEMP, M_WAITOK); + name[0] = name_len; + memcpy(&name[1], attr_name, name_len); + error = uiomove(name, name_len + 1, uio); + free(name, M_TEMP); if (error) break; } @@ -231,6 +310,8 @@ ext2_extattr_inode_get(struct inode *ip, int attrnamespace, struct buf *bp; struct ext2fs_extattr_dinode_header *header; struct ext2fs_extattr_entry *entry; + const char *attr_name; + int name_len; int error; fs = ip->i_e2fs; @@ -264,11 +345,20 @@ ext2_extattr_inode_get(struct inode *ip, int attrnamespace, for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry); entry = EXT2_EXTATTR_NEXT(entry)) { - if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace) + if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) != + attrnamespace) continue; - if (strlen(name) == entry->e_name_len && - 0 == strncmp(entry->e_name, name, entry->e_name_len)) { + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + + if (strlen(name) == name_len && + 0 == strncmp(attr_name, name, name_len)) { if (uio == NULL) *size += entry->e_value_size; else { @@ -294,6 +384,8 @@ ext2_extattr_block_get(struct inode *ip, int attrnamespace, struct buf *bp; struct ext2fs_extattr_header *header; struct ext2fs_extattr_entry *entry; + const char *attr_name; + int name_len; int error; fs = ip->i_e2fs; @@ -320,11 +412,20 @@ ext2_extattr_block_get(struct inode *ip, int attrnamespace, for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry); entry = EXT2_EXTATTR_NEXT(entry)) { - if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace) + if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) != + attrnamespace) continue; - if (strlen(name) == entry->e_name_len && - 0 == strncmp(entry->e_name, name, entry->e_name_len)) { + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + + if (strlen(name) == name_len && + 0 == strncmp(attr_name, name, name_len)) { if (uio == NULL) *size += entry->e_value_size; else { @@ -411,6 +512,8 @@ ext2_extattr_inode_delete(struct inode *ip, int attrnamespace, const char *name) struct buf *bp; struct ext2fs_extattr_dinode_header *header; struct ext2fs_extattr_entry *entry; + const char *attr_name; + int name_len; int error; fs = ip->i_e2fs; @@ -444,9 +547,20 @@ ext2_extattr_inode_delete(struct inode *ip, int attrnamespace, const char *name) /* If I am last entry, just make magic zero */ entry = EXT2_IFIRST(header); - if (EXT2_IS_LAST_ENTRY(EXT2_EXTATTR_NEXT(entry))) { - if (strlen(name) == entry->e_name_len && - 0 == strncmp(entry->e_name, name, entry->e_name_len)) { + if ((EXT2_IS_LAST_ENTRY(EXT2_EXTATTR_NEXT(entry))) && + (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) == + attrnamespace)) { + + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + + if (strlen(name) == name_len && + 0 == strncmp(attr_name, name, name_len)) { memset(header, 0, sizeof(struct ext2fs_extattr_dinode_header)); return (bwrite(bp)); @@ -455,11 +569,20 @@ ext2_extattr_inode_delete(struct inode *ip, int attrnamespace, const char *name) for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry); entry = EXT2_EXTATTR_NEXT(entry)) { - if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace) + if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) != + attrnamespace) continue; - if (strlen(name) == entry->e_name_len && - 0 == strncmp(entry->e_name, name, entry->e_name_len)) { + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + + if (strlen(name) == name_len && + 0 == strncmp(attr_name, name, name_len)) { ext2_extattr_delete_entry((char *)EXT2_IFIRST(header), EXT2_IFIRST(header), entry, (char *)dinode + EXT2_INODE_SIZE(fs)); @@ -521,6 +644,8 @@ ext2_extattr_block_delete(struct inode *ip, int attrnamespace, const char *name) struct buf *bp; struct ext2fs_extattr_header *header; struct ext2fs_extattr_entry *entry; + const char *attr_name; + int name_len; int error; fs = ip->i_e2fs; @@ -555,9 +680,20 @@ ext2_extattr_block_delete(struct inode *ip, int attrnamespace, const char *name) /* If I am last entry, clean me and free the block */ entry = EXT2_FIRST_ENTRY(bp); - if (EXT2_IS_LAST_ENTRY(EXT2_EXTATTR_NEXT(entry))) { - if (strlen(name) == entry->e_name_len && - 0 == strncmp(entry->e_name, name, entry->e_name_len)) { + if (EXT2_IS_LAST_ENTRY(EXT2_EXTATTR_NEXT(entry)) && + (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) == + attrnamespace)) { + + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + + if (strlen(name) == name_len && + 0 == strncmp(attr_name, name, name_len)) { ip->i_blocks -= btodb(fs->e2fs_bsize); ext2_blkfree(ip, ip->i_facl, fs->e2fs_bsize); ip->i_facl = 0; @@ -570,11 +706,20 @@ ext2_extattr_block_delete(struct inode *ip, int attrnamespace, const char *name) for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry); entry = EXT2_EXTATTR_NEXT(entry)) { - if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace) + if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) != + attrnamespace) continue; - if (strlen(name) == entry->e_name_len && - 0 == strncmp(entry->e_name, name, entry->e_name_len)) { + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + + if (strlen(name) == name_len && + 0 == strncmp(attr_name, name, name_len)) { ext2_extattr_delete_entry(bp->b_data, EXT2_FIRST_ENTRY(bp), entry, bp->b_data + bp->b_bufsize); @@ -592,15 +737,18 @@ static struct ext2fs_extattr_entry * allocate_entry(const char *name, int attrnamespace, uint16_t offs, uint32_t size, uint32_t hash) { - size_t name_len; + const char *attr_name; + int name_len; struct ext2fs_extattr_entry *entry; - name_len = strlen(name); + attr_name = ext2_extattr_name_to_linux(attrnamespace, name); + name_len = strlen(attr_name); + entry = malloc(sizeof(struct ext2fs_extattr_entry) + name_len, M_TEMP, M_WAITOK); entry->e_name_len = name_len; - entry->e_name_index = ext2_extattr_index_to_linux(attrnamespace); + entry->e_name_index = ext2_extattr_attrnamespace_to_linux(attrnamespace, name); entry->e_value_offs = offs; entry->e_value_block = 0; entry->e_value_size = size; @@ -727,6 +875,8 @@ ext2_extattr_inode_set(struct inode *ip, int attrnamespace, struct buf *bp; struct ext2fs_extattr_dinode_header *header; struct ext2fs_extattr_entry *entry; + const char *attr_name; + int name_len; size_t size = 0, max_size; int error; @@ -762,11 +912,20 @@ ext2_extattr_inode_set(struct inode *ip, int attrnamespace, /* Find if entry exist */ for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry); entry = EXT2_EXTATTR_NEXT(entry)) { - if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace) + if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) != + attrnamespace) continue; - if (strlen(name) == entry->e_name_len && - 0 == strncmp(entry->e_name, name, entry->e_name_len)) + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + + if (strlen(name) == name_len && + 0 == strncmp(attr_name, name, name_len)) break; } @@ -876,6 +1035,8 @@ ext2_extattr_block_set(struct inode *ip, int attrnamespace, struct buf *bp; struct ext2fs_extattr_header *header; struct ext2fs_extattr_entry *entry; + const char *attr_name; + int name_len; size_t size; int error; @@ -916,11 +1077,20 @@ ext2_extattr_block_set(struct inode *ip, int attrnamespace, /* Find if entry exist */ for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry); entry = EXT2_EXTATTR_NEXT(entry)) { - if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace) + if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) != + attrnamespace) continue; - if (strlen(name) == entry->e_name_len && - 0 == strncmp(entry->e_name, name, entry->e_name_len)) + name_len = entry->e_name_len; + attr_name = ext2_extattr_name_to_bsd(entry->e_name_index, + entry->e_name, &name_len); + if (!attr_name) { + brelse(bp); + return (ENOTSUP); + } + + if (strlen(name) == name_len && + 0 == strncmp(attr_name, name, name_len)) break; } @@ -961,7 +1131,8 @@ ext2_extattr_block_set(struct inode *ip, int attrnamespace, } size = ext2_extattr_get_size(NULL, NULL, - sizeof(struct ext2fs_extattr_header), strlen(name), uio->uio_resid); + sizeof(struct ext2fs_extattr_header), + strlen(ext2_extattr_name_to_linux(attrnamespace, name)), uio->uio_resid); if (size > fs->e2fs_bsize) return (ENOSPC); diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index b507a6200886..68d49827b3f2 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -81,6 +81,7 @@ #include <fs/ext2fs/fs.h> #include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2_acl.h> #include <fs/ext2fs/ext2_extern.h> #include <fs/ext2fs/ext2fs.h> #include <fs/ext2fs/ext2_dinode.h> @@ -163,6 +164,9 @@ struct vop_vector ext2_vnodeops = { .vop_getextattr = ext2_getextattr, .vop_listextattr = ext2_listextattr, .vop_setextattr = ext2_setextattr, + .vop_getacl = ext2_getacl, + .vop_setacl = ext2_setacl, + .vop_aclcheck = ext2_aclcheck, .vop_vptofh = ext2_vptofh, }; @@ -1083,6 +1087,150 @@ out: return (error); } +static int +ext2_do_posix1e_acl_inheritance_dir(struct vnode *dvp, struct vnode *tvp, + mode_t dmode, struct ucred *cred, struct thread *td) +{ + int error; + struct inode *ip = VTOI(tvp); + struct acl *dacl, *acl; + + acl = acl_alloc(M_WAITOK); + dacl = acl_alloc(M_WAITOK); + + /* + * Retrieve default ACL from parent, if any. + */ + error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred, td); + switch (error) { + case 0: + /* + * Retrieved a default ACL, so merge mode and ACL if + * necessary. If the ACL is empty, fall through to + * the "not defined or available" case. + */ + if (acl->acl_cnt != 0) { + dmode = acl_posix1e_newfilemode(dmode, acl); + ip->i_mode = dmode; + *dacl = *acl; + ext2_sync_acl_from_inode(ip, acl); + break; + } + /* FALLTHROUGH */ + + case EOPNOTSUPP: + /* + * Just use the mode as-is. + */ + ip->i_mode = dmode; + error = 0; + goto out; + + default: + goto out; + } + + error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred, td); + if (error == 0) + error = VOP_SETACL(tvp, ACL_TYPE_DEFAULT, dacl, cred, td); + switch (error) { + case 0: + break; + + case EOPNOTSUPP: + /* + * XXX: This should not happen, as EOPNOTSUPP above + * was supposed to free acl. + */ +#ifdef DEBUG + printf("ext2_mkdir: VOP_GETACL() but no VOP_SETACL()\n"); +#endif /* DEBUG */ + break; + + default: + goto out; + } + +out: + acl_free(acl); + acl_free(dacl); + + return (error); +} + +static int +ext2_do_posix1e_acl_inheritance_file(struct vnode *dvp, struct vnode *tvp, + mode_t mode, struct ucred *cred, struct thread *td) +{ + int error; + struct inode *ip = VTOI(tvp); + struct acl *acl; + + acl = acl_alloc(M_WAITOK); + + /* + * Retrieve default ACL for parent, if any. + */ + error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred, td); + switch (error) { + case 0: + /* + * Retrieved a default ACL, so merge mode and ACL if + * necessary. + */ + if (acl->acl_cnt != 0) { + /* + * Two possible ways for default ACL to not + * be present. First, the EA can be + * undefined, or second, the default ACL can + * be blank. If it's blank, fall through to + * the it's not defined case. + */ + mode = acl_posix1e_newfilemode(mode, acl); + ip->i_mode = mode; + ext2_sync_acl_from_inode(ip, acl); + break; + } + /* FALLTHROUGH */ + + case EOPNOTSUPP: + /* + * Just use the mode as-is. + */ + ip->i_mode = mode; + error = 0; + goto out; + + default: + goto out; + } + + error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred, td); + switch (error) { + case 0: + break; + + case EOPNOTSUPP: + /* + * XXX: This should not happen, as EOPNOTSUPP above was + * supposed to free acl. + */ + printf("ufs_do_posix1e_acl_inheritance_file: VOP_GETACL() " + "but no VOP_SETACL()\n"); + /* panic("ufs_do_posix1e_acl_inheritance_file: VOP_GETACL() " + "but no VOP_SETACL()"); */ + break; + + default: + goto out; + } + +out: + acl_free(acl); + + return (error); +} + /* * Mkdir system call */ @@ -1192,6 +1340,13 @@ ext2_mkdir(struct vop_mkdir_args *ap) ip->i_flag |= IN_CHANGE; } + if (dvp->v_mount->mnt_flag & MNT_ACLS) { + error = ext2_do_posix1e_acl_inheritance_dir(dvp, tvp, dmode, + cnp->cn_cred, cnp->cn_thread); + if (error) + goto bad; + } + /* Directory set up, now install its entry in the parent directory. */ error = ext2_direnter(ip, dvp, cnp); if (error) { @@ -1446,6 +1601,18 @@ ext2_pathconf(struct vop_pathconf_args *ap) case _PC_NO_TRUNC: *ap->a_retval = 1; break; + case _PC_ACL_EXTENDED: + if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS) + *ap->a_retval = 1; + else + *ap->a_retval = 0; + break; + case _PC_ACL_PATH_MAX: + if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS) + *ap->a_retval = ACL_MAX_ENTRIES; + else + *ap->a_retval = 3; + break; case _PC_MIN_HOLE_SIZE: *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize; break; @@ -1513,6 +1680,8 @@ ext2_deleteextattr(struct vop_deleteextattr_args *ap) if (error) return (error); + error = ENOATTR; + if (EXT2_INODE_SIZE(fs) != E2FS_REV0_INODE_SIZE) { error = ext2_extattr_inode_delete(ip, ap->a_attrnamespace, ap->a_name); if (error != ENOATTR) @@ -1552,6 +1721,8 @@ ext2_getextattr(struct vop_getextattr_args *ap) if (ap->a_size != NULL) *ap->a_size = 0; + error = ENOATTR; + if (EXT2_INODE_SIZE(fs) != E2FS_REV0_INODE_SIZE) { error = ext2_extattr_inode_get(ip, ap->a_attrnamespace, ap->a_name, ap->a_uio, ap->a_size); @@ -1755,6 +1926,14 @@ ext2_makeinode(int mode, struct vnode *dvp, struct vnode **vpp, error = ext2_update(tvp, !DOINGASYNC(tvp)); if (error) goto bad; + + if (dvp->v_mount->mnt_flag & MNT_ACLS) { + error = ext2_do_posix1e_acl_inheritance_file(dvp, tvp, mode, + cnp->cn_cred, cnp->cn_thread); + if (error) + goto bad; + } + error = ext2_direnter(ip, dvp, cnp); if (error) goto bad; diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c index dd8fcf693403..509c38b8614e 100644 --- a/sys/fs/nfsclient/nfs_clport.c +++ b/sys/fs/nfsclient/nfs_clport.c @@ -490,14 +490,13 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper, * from the value used for the top level server volume * in the mounted subtree. */ - if (vp->v_mount->mnt_stat.f_fsid.val[0] != - (uint32_t)np->n_vattr.na_filesid[0]) - vap->va_fsid = (uint32_t)np->n_vattr.na_filesid[0]; - else - vap->va_fsid = (uint32_t)hash32_buf( + vn_fsid(vp, vap); + vap->va_fsid = np->n_vattr.na_filesid[0]; + if (vap->va_fsid == np->n_vattr.na_filesid[0]) + vap->va_fsid = hash32_buf( np->n_vattr.na_filesid, 2 * sizeof(uint64_t), 0); } else - vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; + vn_fsid(vp, vap); np->n_attrstamp = time_second; if (vap->va_size != np->n_size) { if (vap->va_type == VREG) { diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index a30260bfeebc..d912b5228647 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -359,6 +359,10 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) inpcb = (struct inpcb *)(so->so_pcb); kif->kf_un.kf_sock.kf_sock_inpcb = (uintptr_t)inpcb->inp_ppcb; + kif->kf_un.kf_sock.kf_sock_sendq = + sbused(&so->so_snd); + kif->kf_un.kf_sock.kf_sock_recvq = + sbused(&so->so_rcv); } } break; @@ -372,6 +376,10 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) so->so_rcv.sb_state; kif->kf_un.kf_sock.kf_sock_snd_sb_state = so->so_snd.sb_state; + kif->kf_un.kf_sock.kf_sock_sendq = + sbused(&so->so_snd); + kif->kf_un.kf_sock.kf_sock_recvq = + sbused(&so->so_rcv); } } break; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index f61531783707..934db8725e44 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -2493,3 +2493,14 @@ vn_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t size, #endif return (error); } + +void +vn_fsid(struct vnode *vp, struct vattr *va) +{ + fsid_t *f; + + f = &vp->v_mount->mnt_stat.f_fsid; + va->va_fsid = (uint32_t)f->val[1]; + va->va_fsid <<= sizeof(f->val[1]) * NBBY; + va->va_fsid += (uint32_t)f->val[0]; +} diff --git a/sys/mips/atheros/ar71xxreg.h b/sys/mips/atheros/ar71xxreg.h index 95e36c04ba6f..1d99821ffd10 100644 --- a/sys/mips/atheros/ar71xxreg.h +++ b/sys/mips/atheros/ar71xxreg.h @@ -528,13 +528,14 @@ typedef enum { #define AR71XX_SPI_RDS 0x0C #define ATH_READ_REG(reg) \ - *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg))) - + *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg))) +/* + * Note: Don't put a flush read here; some users (eg the AR724x PCI fixup code) + * requires write-only space to certain registers. Doing the read afterwards + * causes things to break. + */ #define ATH_WRITE_REG(reg, val) \ - do { \ - *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg))) = (val); \ - (void) ATH_READ_REG(reg); \ - } while (0) + *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg))) = (val) static inline void ar71xx_ddr_flush(uint32_t reg) diff --git a/sys/mips/broadcom/bcm_pmu.c b/sys/mips/broadcom/bcm_pmu.c index 46fa70da5902..e9d6d4d2ab3f 100644 --- a/sys/mips/broadcom/bcm_pmu.c +++ b/sys/mips/broadcom/bcm_pmu.c @@ -208,7 +208,7 @@ bcm_get_uart_rclk(struct bcm_platform *bp) uint64_t bcm_get_alpfreq(struct bcm_platform *bp) { if (!bcm_has_pmu(bp)) - panic("%s requires PMU\n", __FUNCTION__); + return (BHND_PMU_ALP_CLOCK); return (bhnd_pmu_alp_clock(bcm_get_pmu(bp))); } @@ -217,7 +217,7 @@ bcm_get_alpfreq(struct bcm_platform *bp) { uint64_t bcm_get_ilpfreq(struct bcm_platform *bp) { if (!bcm_has_pmu(bp)) - panic("%s requires PMU\n", __FUNCTION__); + return (BHND_PMU_ILP_CLOCK); return (bhnd_pmu_ilp_clock(bcm_get_pmu(bp))); } diff --git a/sys/mips/conf/AP93.hints b/sys/mips/conf/AP93.hints index 4de4b8e125ce..2fbbe2904153 100644 --- a/sys/mips/conf/AP93.hints +++ b/sys/mips/conf/AP93.hints @@ -15,12 +15,14 @@ hint.argemdio.0.order=0 hint.arge.0.phymask=0x10 # PHY 4 # hint.arge.0.miimode=2 # MII hint.arge.0.mdio=mdioproxy1 # Hanging off the arswitch MDIO bus +hint.arge.0.eeprommac=0x1fff0000 # arge1: connected to the LAN switch MAC, at 1000BaseTX / GMII. hint.arge.1.phymask=0x0 # hint.arge.1.miimode=1 # GMII hint.arge.1.media=1000 # Force to 1000BaseTX/full hint.arge.1.fduplex=1 +hint.arge.1.eeprommac=0x1fff0006 # # AR7240 switch config @@ -94,29 +96,15 @@ hint.map.1.readonly=1 hint.map.2.at="flash/spi0" hint.map.2.start=0x00080000 -# hint.map.2.end=0x00380000 -hint.map.2.end=0x00780000 -# hint.map.2.name="spare-rootfs" -hint.map.2.name="rootfs" -hint.map.2.readonly=1 - -#hint.map.3.at="flash/spi0" -#hint.map.3.start=0x00380000 -#hint.map.3.end=0x00480000 -#hint.map.3.name="spare-uImage" -#hint.map.3.readonly=1 - -#hint.map.4.at="flash/spi0" -#hint.map.4.start=0x00480000 -#hint.map.4.end=0x00780000 -#hint.map.4.name="rootfs" -#hint.map.4.readonly=1 +hint.map.2.end="search:0x00080000:0x10000:.!/bin/sh" +hint.map.2.name="kernel" +hint.map.2.readonly=0 hint.map.3.at="flash/spi0" -hint.map.3.start=0x00780000 +hint.map.3.start="search:0x00080000:0x10000:.!/bin/sh" hint.map.3.end=0x00880000 -hint.map.3.name="uImage" -hint.map.3.readonly=1 +hint.map.3.name="rootfs" +hint.map.3.readonly=0 hint.map.4.at="flash/spi0" hint.map.4.start=0x00880000 diff --git a/sys/mips/conf/AR724X_BASE b/sys/mips/conf/AR724X_BASE index 8f4e24699a9b..257330602678 100644 --- a/sys/mips/conf/AR724X_BASE +++ b/sys/mips/conf/AR724X_BASE @@ -25,13 +25,14 @@ makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols # Build these as modules so small platform builds will have the # modules already built. -makeoptions MODULES_OVERRIDE="gpio ar71xx if_gif if_gre if_bridge bridgestp usb wlan wlan_xauth wlan_acl wlan_wep wlan_tkip wlan_ccmp wlan_rssadapt wlan_amrr ath ath_pci hwpmc cam" +makeoptions MODULES_OVERRIDE="gpio ar71xx if_gif if_gre if_tap if_tun libalias ipfw ipfw_nat ipfw_nptv6 if_vlan if_bridge bridgestp usb wlan wlan_xauth wlan_acl wlan_wep wlan_tkip wlan_ccmp wlan_rssadapt wlan_amrr ath_main ath_pci ath_hal ath_hal_ar5212 ath_hal_ar5416 ath_hal_ar9300 ath_rate ath_dfs hwpmc hwpmc_mips24k cam" # For small memory footprints options VM_KMEM_SIZE_SCALE=1 options DDB options KDB +options EARLY_PRINTF options SCHED_4BSD #4BSD scheduler options INET #InterNETworking @@ -59,11 +60,16 @@ options NO_SYSCTL_DESCR options FFS #Berkeley Fast Filesystem options NO_FFS_SNAPSHOT + +options IPFIREWALL_DEFAULT_TO_ACCEPT + # options SOFTUPDATES #Enable FFS soft updates support # options UFS_ACL #Support for access control lists # options UFS_DIRHASH #Improve performance on big directories # options MSDOSFS # Read MSDOS filesystems; useful for USB/CF +options UMTX_CHAINS=16 + device pci device ar724x_pci @@ -129,7 +135,7 @@ device loop device ether device md device bpf -#device random +device random #device if_bridge #device gif # ip[46] in ip[46] tunneling protocol #device gre # generic encapsulation - only for IPv4 in IPv4 though atm diff --git a/sys/modules/ext2fs/Makefile b/sys/modules/ext2fs/Makefile index 03ba089f66f6..64164798e297 100644 --- a/sys/modules/ext2fs/Makefile +++ b/sys/modules/ext2fs/Makefile @@ -3,8 +3,8 @@ .PATH: ${SRCTOP}/sys/fs/ext2fs KMOD= ext2fs SRCS= opt_ddb.h opt_directio.h opt_quota.h opt_suiddir.h vnode_if.h \ - ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_extattr.c ext2_extents.c \ - ext2_hash.c ext2_htree.c ext2_inode.c ext2_inode_cnv.c ext2_lookup.c \ - ext2_subr.c ext2_vfsops.c ext2_vnops.c + ext2_acl.c ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_extattr.c \ + ext2_extents.c ext2_hash.c ext2_htree.c ext2_inode.c ext2_inode_cnv.c \ + ext2_lookup.c ext2_subr.c ext2_vfsops.c ext2_vnops.c .include <bsd.kmod.mk> diff --git a/sys/modules/linux/Makefile b/sys/modules/linux/Makefile index 00d1de712de0..a8df54d18c49 100644 --- a/sys/modules/linux/Makefile +++ b/sys/modules/linux/Makefile @@ -15,7 +15,7 @@ SRCS= linux_fork.c linux${SFX}_dummy.c linux_file.c linux_event.c \ linux${SFX}_machdep.c linux_misc.c linux_signal.c \ linux_socket.c linux_stats.c linux_sysctl.c linux${SFX}_sysent.c \ linux${SFX}_sysvec.c linux_uid16.c linux_time.c \ - linux_timer.c linux_vdso.c \ + linux_timer.c linux_vdso.c opt_global.h \ opt_inet6.h opt_compat.h opt_posix.h opt_usb.h vnode_if.h \ device_if.h bus_if.h assym.s \ linux${SFX}_support.s @@ -64,10 +64,12 @@ linux${SFX}_support.o: linux${SFX}_assym.h assym.s ${VDSO}.so: linux${SFX}_locore.o ${OBJCOPY} --input-target binary --output-target elf64-x86-64-freebsd \ --binary-architecture i386 linux${SFX}_locore.o ${.TARGET} + strip -N _binary_linux${SFX}_locore_o_size ${.TARGET} .else ${VDSO}.so: linux${SFX}_locore.o ${OBJCOPY} --input-target binary --output-target elf32-i386-freebsd \ --binary-architecture i386 linux${SFX}_locore.o ${.TARGET} + strip -N _binary_linux_locore_o_size ${.TARGET} .endif linux${SFX}_genassym.o: diff --git a/sys/modules/linux64/Makefile b/sys/modules/linux64/Makefile index ac40344edd01..fe723da01a77 100644 --- a/sys/modules/linux64/Makefile +++ b/sys/modules/linux64/Makefile @@ -10,7 +10,7 @@ SRCS= linux_fork.c linux_dummy.c linux_file.c linux_event.c \ linux_machdep.c linux_misc.c linux_ptrace.c linux_signal.c \ linux_socket.c linux_stats.c linux_sysctl.c linux_sysent.c \ linux_sysvec.c linux_time.c linux_vdso.c linux_timer.c \ - opt_inet6.h opt_compat.h opt_posix.h opt_usb.h \ + opt_inet6.h opt_compat.h opt_global.h opt_posix.h opt_usb.h \ vnode_if.h device_if.h bus_if.h assym.s \ linux_support.s DPSRCS= linux_genassym.c @@ -38,6 +38,7 @@ linux_locore.o: linux_locore.s linux_assym.h ${VDSO}.so: linux_locore.o ${OBJCOPY} --input-target binary --output-target elf64-x86-64-freebsd \ -S -g --binary-architecture i386:x86-64 linux_locore.o ${.TARGET} + strip -N _binary_linux_locore_o_size ${.TARGET} linux_support.o: assym.s linux_assym.h ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \ diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index de5beaff712e..afcad52c3dd1 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -572,24 +572,41 @@ static void lagg_capabilities(struct lagg_softc *sc) { struct lagg_port *lp; - int cap = ~0, ena = ~0; - u_long hwa = ~0UL; + int cap, ena, pena; + uint64_t hwa; struct ifnet_hw_tsomax hw_tsomax; LAGG_XLOCK_ASSERT(sc); - memset(&hw_tsomax, 0, sizeof(hw_tsomax)); + /* Get common enabled capabilities for the lagg ports */ + ena = ~0; + SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + ena &= lp->lp_ifp->if_capenable; + ena = (ena == ~0 ? 0 : ena); + + /* + * Apply common enabled capabilities back to the lagg ports. + * May require several iterations if they are dependent. + */ + do { + pena = ena; + SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + lagg_setcaps(lp, ena); + ena &= lp->lp_ifp->if_capenable; + } + } while (pena != ena); - /* Get capabilities from the lagg ports */ + /* Get other capabilities from the lagg ports */ + cap = ~0; + hwa = ~(uint64_t)0; + memset(&hw_tsomax, 0, sizeof(hw_tsomax)); SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { cap &= lp->lp_ifp->if_capabilities; - ena &= lp->lp_ifp->if_capenable; hwa &= lp->lp_ifp->if_hwassist; if_hw_tsomax_common(lp->lp_ifp, &hw_tsomax); } cap = (cap == ~0 ? 0 : cap); - ena = (ena == ~0 ? 0 : ena); - hwa = (hwa == ~0 ? 0 : hwa); + hwa = (hwa == ~(uint64_t)0 ? 0 : hwa); if (sc->sc_ifp->if_capabilities != cap || sc->sc_ifp->if_capenable != ena || @@ -604,10 +621,6 @@ lagg_capabilities(struct lagg_softc *sc) if_printf(sc->sc_ifp, "capabilities 0x%08x enabled 0x%08x\n", cap, ena); } - - /* Apply unified capabilities back to the lagg ports. */ - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) - lagg_setcaps(lp, ena); } static int @@ -888,6 +901,7 @@ lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) LAGG_XLOCK(sc); lagg_capabilities(sc); LAGG_XUNLOCK(sc); + VLAN_CAPABILITIES(sc->sc_ifp); break; case SIOCSIFMTU: @@ -1001,6 +1015,7 @@ lagg_port_ifdetach(void *arg __unused, struct ifnet *ifp) lp->lp_detaching = 1; lagg_port_destroy(lp, 1); LAGG_XUNLOCK(sc); + VLAN_CAPABILITIES(sc->sc_ifp); } static void @@ -1360,6 +1375,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = lagg_port_create(sc, tpif); LAGG_XUNLOCK(sc); if_rele(tpif); + VLAN_CAPABILITIES(ifp); break; case SIOCSLAGGDELPORT: error = priv_check(td, PRIV_NET_LAGG); @@ -1383,6 +1399,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = lagg_port_destroy(lp, 1); LAGG_XUNLOCK(sc); if_rele(tpif); + VLAN_CAPABILITIES(ifp); break; case SIOCSIFFLAGS: /* Set flags on ports too */ @@ -1433,6 +1450,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } lagg_capabilities(sc); LAGG_XUNLOCK(sc); + VLAN_CAPABILITIES(ifp); error = 0; break; diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h index 49413e2b9ee7..147412f980e0 100644 --- a/sys/netipsec/ipsec.h +++ b/sys/netipsec/ipsec.h @@ -299,7 +299,13 @@ VNET_DECLARE(int, natt_cksum_policy); #define ipseclog(x) do { if (V_ipsec_debug) log x; } while (0) /* for openbsd compatibility */ +#ifdef IPSEC_DEBUG +#define IPSEC_DEBUG_DECLARE(x) x #define DPRINTF(x) do { if (V_ipsec_debug) printf x; } while (0) +#else +#define IPSEC_DEBUG_DECLARE(x) +#define DPRINTF(x) +#endif struct inpcb; struct m_tag; diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c index e253cc0a31d2..f30a017be146 100644 --- a/sys/netipsec/ipsec_input.c +++ b/sys/netipsec/ipsec_input.c @@ -117,7 +117,7 @@ __FBSDID("$FreeBSD$"); static int ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); union sockaddr_union dst_address; struct secasvar *sav; uint32_t spi; @@ -277,7 +277,7 @@ int ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int protoff) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); struct ipsec_ctx_data ctx; struct xform_history *xh; struct secasindex *saidx; @@ -488,7 +488,7 @@ int ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int protoff) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); struct ipsec_ctx_data ctx; struct xform_history *xh; struct secasindex *saidx; diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c index 80b6ab8300b1..ee45ce208744 100644 --- a/sys/netipsec/ipsec_output.c +++ b/sys/netipsec/ipsec_output.c @@ -183,7 +183,6 @@ next: static int ipsec4_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx) { - char sbuf[IPSEC_ADDRSTRLEN], dbuf[IPSEC_ADDRSTRLEN]; struct ipsec_ctx_data ctx; union sockaddr_union *dst; struct secasvar *sav; @@ -230,12 +229,9 @@ ipsec4_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx) ip->ip_sum = in_cksum(m, ip->ip_hl << 2); error = ipsec_encap(&m, &sav->sah->saidx); if (error != 0) { - DPRINTF(("%s: encapsulation for SA %s->%s " - "SPI 0x%08x failed with error %d\n", __func__, - ipsec_address(&sav->sah->saidx.src, sbuf, - sizeof(sbuf)), - ipsec_address(&sav->sah->saidx.dst, dbuf, - sizeof(dbuf)), ntohl(sav->spi), error)); + DPRINTF(("%s: encapsulation for SPI 0x%08x failed " + "with error %d\n", __func__, ntohl(sav->spi), + error)); /* XXXAE: IPSEC_OSTAT_INC(tunnel); */ goto bad; } @@ -497,7 +493,6 @@ next: static int ipsec6_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx) { - char sbuf[IPSEC_ADDRSTRLEN], dbuf[IPSEC_ADDRSTRLEN]; struct ipsec_ctx_data ctx; union sockaddr_union *dst; struct secasvar *sav; @@ -539,12 +534,9 @@ ipsec6_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx) } error = ipsec_encap(&m, &sav->sah->saidx); if (error != 0) { - DPRINTF(("%s: encapsulation for SA %s->%s " - "SPI 0x%08x failed with error %d\n", __func__, - ipsec_address(&sav->sah->saidx.src, sbuf, - sizeof(sbuf)), - ipsec_address(&sav->sah->saidx.dst, dbuf, - sizeof(dbuf)), ntohl(sav->spi), error)); + DPRINTF(("%s: encapsulation for SPI 0x%08x failed " + "with error %d\n", __func__, ntohl(sav->spi), + error)); /* XXXAE: IPSEC_OSTAT_INC(tunnel); */ goto bad; } diff --git a/sys/netipsec/key_debug.h b/sys/netipsec/key_debug.h index 18150b5379e5..afb11cb1c357 100644 --- a/sys/netipsec/key_debug.h +++ b/sys/netipsec/key_debug.h @@ -53,10 +53,14 @@ #define KEYDEBUG_IPSEC_DATA (KEYDEBUG_IPSEC | KEYDEBUG_DATA) #define KEYDEBUG_IPSEC_DUMP (KEYDEBUG_IPSEC | KEYDEBUG_DUMP) +#ifdef IPSEC_DEBUG #define KEYDBG(lev, arg) \ if ((V_key_debug_level & (KEYDEBUG_ ## lev)) == (KEYDEBUG_ ## lev)) { \ arg; \ } +#else +#define KEYDBG(lev, arg) +#endif /* !IPSEC_DEBUG */ VNET_DECLARE(uint32_t, key_debug_level); #define V_key_debug_level VNET(key_debug_level) diff --git a/sys/netipsec/xform_ah.c b/sys/netipsec/xform_ah.c index 0bcab46373c5..fada7b7e005f 100644 --- a/sys/netipsec/xform_ah.c +++ b/sys/netipsec/xform_ah.c @@ -544,7 +544,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) static int ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) { - char buf[128]; + IPSEC_DEBUG_DECLARE(char buf[128]); const struct auth_hash *ahx; struct cryptodesc *crda; struct cryptop *crp; @@ -681,7 +681,7 @@ bad: static int ah_input_cb(struct cryptop *crp) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); unsigned char calc[AH_ALEN_MAX]; const struct auth_hash *ahx; struct mbuf *m; @@ -831,7 +831,7 @@ static int ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav, u_int idx, int skip, int protoff) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); const struct auth_hash *ahx; struct cryptodesc *crda; struct xform_data *xd; diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c index 7eda6450bcbe..39d5b8c79e02 100644 --- a/sys/netipsec/xform_esp.c +++ b/sys/netipsec/xform_esp.c @@ -263,7 +263,7 @@ esp_zeroize(struct secasvar *sav) static int esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) { - char buf[128]; + IPSEC_DEBUG_DECLARE(char buf[128]); const struct auth_hash *esph; const struct enc_xform *espx; struct xform_data *xd; @@ -436,7 +436,7 @@ bad: static int esp_input_cb(struct cryptop *crp) { - char buf[128]; + IPSEC_DEBUG_DECLARE(char buf[128]); u_int8_t lastthree[3], aalg[AH_HMAC_MAXHASHLEN]; const struct auth_hash *esph; const struct enc_xform *espx; @@ -622,7 +622,7 @@ static int esp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav, u_int idx, int skip, int protoff) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); struct cryptodesc *crde = NULL, *crda = NULL; struct cryptop *crp; const struct auth_hash *esph; diff --git a/sys/netipsec/xform_ipcomp.c b/sys/netipsec/xform_ipcomp.c index 061937d70228..1e8fc59ae105 100644 --- a/sys/netipsec/xform_ipcomp.c +++ b/sys/netipsec/xform_ipcomp.c @@ -271,7 +271,7 @@ bad: static int ipcomp_input_cb(struct cryptop *crp) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); struct cryptodesc *crd; struct xform_data *xd; struct mbuf *m; @@ -387,7 +387,7 @@ static int ipcomp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav, u_int idx, int skip, int protoff) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); const struct comp_algo *ipcompx; struct cryptodesc *crdc; struct cryptop *crp; @@ -521,7 +521,7 @@ bad: static int ipcomp_output_cb(struct cryptop *crp) { - char buf[IPSEC_ADDRSTRLEN]; + IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); struct xform_data *xd; struct secpolicy *sp; struct secasvar *sav; diff --git a/sys/sys/user.h b/sys/sys/user.h index ba5e43a74158..548a86e9545b 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -344,7 +344,8 @@ struct kinfo_file { int64_t kf_offset; /* Seek location. */ union { struct { - uint32_t kf_spareint; + /* Sendq size */ + uint32_t kf_sock_sendq; /* Socket domain. */ int kf_sock_domain0; /* Socket type. */ @@ -365,8 +366,8 @@ struct kinfo_file { uint16_t kf_sock_snd_sb_state; /* Receive buffer state. */ uint16_t kf_sock_rcv_sb_state; - /* Round to 64 bit alignment. */ - uint32_t kf_sock_pad0; + /* Recvq size. */ + uint32_t kf_sock_recvq; } kf_sock; struct { /* Vnode type. */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 8bfe851c55e6..2e45ede7598e 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -885,6 +885,8 @@ int vn_chmod(struct file *fp, mode_t mode, struct ucred *active_cred, int vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred, struct thread *td); +void vn_fsid(struct vnode *vp, struct vattr *va); + #endif /* _KERNEL */ #endif /* !_SYS_VNODE_H_ */ diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 2a73acaad666..2788c6c74770 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -381,18 +381,14 @@ struct pagerops swappagerops = { }; /* - * dmmax is in page-sized chunks with the new swap system. It was - * dev-bsized chunks in the old. dmmax is always a power of 2. - * * swap_*() routines are externally accessible. swp_*() routines are * internal. */ -static int dmmax; static int nswap_lowat = 128; /* in pages, swap_pager_almost_full warn */ static int nswap_hiwat = 512; /* in pages, swap_pager_almost_full warn */ -SYSCTL_INT(_vm, OID_AUTO, dmmax, CTLFLAG_RD, &dmmax, 0, - "Maximum size of a swap block"); +SYSCTL_INT(_vm, OID_AUTO, dmmax, CTLFLAG_RD, &nsw_cluster_max, 0, + "Maximum size of a swap block in pages"); static void swp_sizecheck(void); static void swp_pager_async_iodone(struct buf *bp); @@ -489,11 +485,6 @@ swap_pager_init(void) mtx_init(&sw_dev_mtx, "swapdev", NULL, MTX_DEF); sx_init(&sw_alloc_sx, "swspsx"); sx_init(&swdev_syscall_lock, "swsysc"); - - /* - * Device Stripe, in PAGE_SIZE'd blocks - */ - dmmax = SWB_NPAGES * 2; } /* @@ -2310,9 +2301,13 @@ swapoff_one(struct swdevt *sp, struct ucred *cred) */ mtx_lock(&sw_dev_mtx); sp->sw_flags |= SW_CLOSING; - for (dvbase = 0; dvbase < sp->sw_end; dvbase += dmmax) { + for (dvbase = 0; dvbase < nblks; dvbase += BLIST_BMAP_RADIX) { + /* + * blist_fill() cannot allocate more than BLIST_BMAP_RADIX + * blocks per call. + */ swap_pager_avail -= blist_fill(sp->sw_blist, - dvbase, dmmax); + dvbase, ulmin(nblks - dvbase, BLIST_BMAP_RADIX)); } swap_total -= (vm_ooffset_t)nblks * PAGE_SIZE; mtx_unlock(&sw_dev_mtx); |
