aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/linux/linux.h22
-rw-r--r--sys/arm/conf/ARMADA38X8
-rw-r--r--sys/boot/common/dev_net.c102
-rw-r--r--sys/boot/i386/loader/Makefile6
-rw-r--r--sys/boot/i386/pxeldr/pxeboot.831
-rw-r--r--sys/cam/scsi/scsi_da.c7
-rw-r--r--sys/cam/scsi/scsi_xpt.c8
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c4
-rw-r--r--sys/compat/linux/linux_misc.c9
-rw-r--r--sys/conf/config.mk2
-rw-r--r--sys/conf/files1
-rw-r--r--sys/contrib/ipfilter/netinet/ip_nat.c2
-rw-r--r--sys/contrib/ipfilter/netinet/ip_sync.c4
-rw-r--r--sys/dev/ath/ath_hal/ah.c2
-rw-r--r--sys/dev/atkbdc/psm.c606
-rw-r--r--sys/dev/bhnd/cores/chipc/chipcreg.h2
-rw-r--r--sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c12
-rw-r--r--sys/dev/cxgbe/crypto/t4_crypto.c45
-rw-r--r--sys/dev/etherswitch/rtl8366/rtl8366rb.c106
-rw-r--r--sys/dev/etherswitch/rtl8366/rtl8366rbvar.h7
-rw-r--r--sys/dev/rtwn/if_rtwn.c8
-rw-r--r--sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c4
-rw-r--r--sys/dev/uart/uart_bus_pci.c1
-rw-r--r--sys/fs/ext2fs/ext2_acl.c521
-rw-r--r--sys/fs/ext2fs/ext2_acl.h55
-rw-r--r--sys/fs/ext2fs/ext2_extattr.c281
-rw-r--r--sys/fs/ext2fs/ext2_vnops.c179
-rw-r--r--sys/fs/nfsclient/nfs_clport.c11
-rw-r--r--sys/kern/sys_socket.c8
-rw-r--r--sys/kern/vfs_vnops.c11
-rw-r--r--sys/mips/atheros/ar71xxreg.h13
-rw-r--r--sys/mips/broadcom/bcm_pmu.c4
-rw-r--r--sys/mips/conf/AP93.hints28
-rw-r--r--sys/mips/conf/AR724X_BASE10
-rw-r--r--sys/modules/ext2fs/Makefile6
-rw-r--r--sys/modules/linux/Makefile4
-rw-r--r--sys/modules/linux64/Makefile3
-rw-r--r--sys/net/if_lagg.c40
-rw-r--r--sys/netipsec/ipsec.h6
-rw-r--r--sys/netipsec/ipsec_input.c6
-rw-r--r--sys/netipsec/ipsec_output.c20
-rw-r--r--sys/netipsec/key_debug.h4
-rw-r--r--sys/netipsec/xform_ah.c6
-rw-r--r--sys/netipsec/xform_esp.c6
-rw-r--r--sys/netipsec/xform_ipcomp.c6
-rw-r--r--sys/sys/user.h7
-rw-r--r--sys/sys/vnode.h2
-rw-r--r--sys/vm/swap_pager.c21
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);